withdraw_page.dart 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656
  1. import 'dart:convert';
  2. import 'package:bbyyy/beans/pay_way_bean_entity.dart';
  3. import 'package:bbyyy/beans/user_bean_entity.dart';
  4. import 'package:bbyyy/beans/withdraw_pricing_bean_entity.dart';
  5. import 'package:bbyyy/https/MyDio.dart';
  6. import 'package:bbyyy/my_tools/dims.dart';
  7. import 'package:bbyyy/my_tools/easy_loading/easy_loading.dart';
  8. import 'package:bbyyy/my_tools/event_bus.dart';
  9. import 'package:bbyyy/my_tools/my_apis.dart';
  10. import 'package:bbyyy/my_tools/my_colors.dart';
  11. import 'package:bbyyy/my_tools/my_cookie.dart';
  12. import 'package:bbyyy/my_tools/my_tools.dart';
  13. import 'package:bbyyy/my_tools/my_views.dart';
  14. import 'package:bbyyy/paegs/mine_page/bind_alipay_page/bind_alipay_page.dart';
  15. import 'package:bbyyy/pay/pay_tools.dart';
  16. import 'package:flustars/flustars.dart';
  17. import 'package:flutter/cupertino.dart';
  18. import 'package:flutter/gestures.dart';
  19. import 'package:flutter/material.dart';
  20. import 'package:flutter/services.dart';
  21. class WithdrawPage extends StatefulWidget {
  22. @override
  23. _WithdrawPageState createState() => _WithdrawPageState();
  24. }
  25. class _WithdrawPageState extends State<WithdrawPage> {
  26. TextEditingController _controller = TextEditingController();
  27. int withdrawalStatus = 1; //0--未提现 1--提现中 2--提现完成
  28. double percentFee = 0.0;
  29. double extraFee = 0.0;
  30. double threshold = 0.0;
  31. double maxPerHand = 0.0;
  32. double minPerHand = 0.0;
  33. int withdrawalPath = -1; // 1---支付宝 2---微信
  34. List<PayWayBeanData> payWays;
  35. bool showAlipay = false;
  36. bool showWeChat = false;
  37. bool showHandlingFee = false;
  38. double handlingFee = 0.0;
  39. double balance = 0.0;
  40. @override
  41. void initState() {
  42. // TODO: implement initState
  43. super.initState();
  44. queryPersonalInformation();
  45. queryWithdrawalInstructions();
  46. Future.delayed(Duration.zero, () {
  47. checkPaymentMethod((response, hasError) {
  48. if (!hasError) {
  49. PayWayBeanEntity entity =
  50. PayWayBeanEntity().fromJson(json.decode(response.toString()));
  51. payWays = entity.data;
  52. showWeChat =
  53. payWays[payWays.indexWhere((element) => element.way == 2)]
  54. .withdraw;
  55. showAlipay =
  56. payWays[payWays.indexWhere((element) => element.way == 1)]
  57. .withdraw;
  58. if (MyCookie().userBean.aliPayAccount.isNotEmpty &&
  59. payWays[payWays.indexWhere((element) => element.way == 1)]
  60. .withdraw) {
  61. withdrawalPath = 1;
  62. } else if (MyCookie().userBean.wxOpenid.isNotEmpty &&
  63. payWays[payWays.indexWhere((element) => element.way == 2)]
  64. .withdraw) {
  65. withdrawalPath = 2;
  66. }
  67. setState(() {});
  68. }
  69. }, (e) {});
  70. });
  71. }
  72. @override
  73. Widget build(BuildContext context) {
  74. return GestureDetector(
  75. onTap: () {
  76. MyTools().hideKeyboard(context);
  77. },
  78. behavior: HitTestBehavior.translucent,
  79. child: Scaffold(
  80. backgroundColor: MyColors.cF7F7F7,
  81. body: Column(
  82. children: [
  83. MyViews().myAppBar('申请提现', context, [
  84. GestureDetector(
  85. onTap: () {
  86. MyTools().toPage(context, BindAlipayPage(), (then) {
  87. setState(() {});
  88. });
  89. },
  90. behavior: HitTestBehavior.translucent,
  91. child: Container(
  92. padding: EdgeInsets.symmetric(vertical: 8, horizontal: 16),
  93. child: Text(
  94. '修改绑定',
  95. style: TextStyle(color: MyColors.c333333, fontSize: 16),
  96. ),
  97. ),
  98. ),
  99. ]),
  100. Expanded(
  101. child: SingleChildScrollView(
  102. child: Column(
  103. children: [
  104. if (showAlipay)
  105. GestureDetector(
  106. onTap: () {
  107. if (!payWays[payWays
  108. .indexWhere((element) => element.way == 1)]
  109. .withdraw) {
  110. showToast('支付宝提现暂时维护中');
  111. return;
  112. }
  113. if (MyCookie().userBean.aliPayAccount.isEmpty) {
  114. showToast('未绑定支付宝');
  115. } else {
  116. setState(() {
  117. withdrawalPath = 1;
  118. });
  119. }
  120. },
  121. behavior: HitTestBehavior.translucent,
  122. child: Container(
  123. margin: EdgeInsets.fromLTRB(17, 24, 17, 0),
  124. child: Row(
  125. children: [
  126. Container(
  127. decoration: BoxDecoration(
  128. color: withdrawalPath == 1
  129. ? MyColors.cFF4233
  130. : MyColors.cD0D0D0,
  131. borderRadius: BorderRadius.circular(9)),
  132. height: 18,
  133. width: 18,
  134. child: Icon(
  135. Icons.check,
  136. color: Colors.white,
  137. size: 14,
  138. ),
  139. alignment: Alignment.center,
  140. margin: EdgeInsets.only(right: 10),
  141. ),
  142. MyViews().myText(
  143. '提现到支付宝:${MyCookie().userBean.aliPayAccount.isEmpty ? '未绑定支付宝' : MyCookie().userBean.aliPayAccount}',
  144. MyColors.c666666,
  145. 15),
  146. ],
  147. ),
  148. ),
  149. ),
  150. if (showWeChat)
  151. GestureDetector(
  152. onTap: () {
  153. // if (!payWays[payWays
  154. // .indexWhere((element) => element.way == 2)]
  155. // .withdraw) {
  156. // showToast('微信提现暂时维护中');
  157. // return;
  158. // }
  159. if (MyCookie().userBean.wxOpenid.isEmpty) {
  160. showToast('未绑定微信');
  161. } else {
  162. setState(() {
  163. withdrawalPath = 2;
  164. });
  165. }
  166. },
  167. behavior: HitTestBehavior.translucent,
  168. child: Container(
  169. margin: EdgeInsets.fromLTRB(17, 24, 17, 0),
  170. child: Row(
  171. children: [
  172. Container(
  173. decoration: BoxDecoration(
  174. color: withdrawalPath == 2
  175. ? MyColors.cFF4233
  176. : MyColors.cD0D0D0,
  177. borderRadius: BorderRadius.circular(9)),
  178. height: 18,
  179. width: 18,
  180. child: Icon(
  181. Icons.check,
  182. color: Colors.white,
  183. size: 14,
  184. ),
  185. alignment: Alignment.center,
  186. margin: EdgeInsets.only(right: 10),
  187. ),
  188. MyViews().myText('提现到微信:', MyColors.c666666, 15),
  189. MyCookie().userBean.wxOpenid.isEmpty
  190. ? MyViews()
  191. .myText('未绑定微信', MyColors.c666666, 15)
  192. : Row(
  193. children: [
  194. Container(
  195. margin: EdgeInsets.only(right: 10),
  196. child: ClipRRect(
  197. borderRadius:
  198. BorderRadius.circular(12),
  199. child: MyViews().netImg(
  200. MyCookie().userBean.wxPicture,
  201. 24,
  202. 24),
  203. ),
  204. ),
  205. MyViews().myText(
  206. MyCookie().userBean.wxName,
  207. MyColors.c666666,
  208. 15)
  209. ],
  210. )
  211. ],
  212. ),
  213. ),
  214. ),
  215. Container(
  216. decoration: BoxDecoration(
  217. color: Colors.white,
  218. borderRadius: BorderRadius.circular(4),
  219. ),
  220. margin:
  221. EdgeInsets.symmetric(horizontal: 17, vertical: 14),
  222. padding:
  223. EdgeInsets.symmetric(horizontal: 20, vertical: 15),
  224. child: Column(
  225. children: [
  226. MyViews().myText('提现金额', MyColors.c333333, 16),
  227. Container(
  228. margin: EdgeInsets.only(top: 15),
  229. child: Row(
  230. children: [
  231. Text(
  232. '¥',
  233. style: TextStyle(
  234. color: MyColors.c333333, fontSize: 30),
  235. ),
  236. Expanded(
  237. child: TextField(
  238. inputFormatters: [
  239. FilteringTextInputFormatter.allow(
  240. RegExp("[0-9.]")),
  241. MoneyTextInputFormatter()
  242. ],
  243. controller: _controller,
  244. cursorColor: MyColors.cFF4233,
  245. cursorWidth: 1.0,
  246. decoration: InputDecoration(
  247. border: InputBorder.none,
  248. disabledBorder: InputBorder.none,
  249. enabledBorder: InputBorder.none,
  250. focusedBorder: InputBorder.none,
  251. hintText: '请输入金额',
  252. hintStyle: TextStyle(
  253. color: MyColors.c999999,
  254. fontSize: 16),
  255. isDense: true,
  256. contentPadding:
  257. const EdgeInsets.fromLTRB(
  258. 14, 4.5, 8, 4.5)),
  259. maxLines: 1,
  260. style: TextStyle(
  261. color: MyColors.c333333,
  262. fontSize: 30,
  263. fontWeight: FontWeight.bold,
  264. height: 1.3,
  265. letterSpacing: 0.2),
  266. keyboardType: TextInputType.number,
  267. onChanged: (t) {
  268. try {
  269. showH();
  270. double amount = double.parse(t);
  271. if (amount > 0) {
  272. withdrawalStatus = 0;
  273. setState(() {});
  274. }
  275. } catch (e) {
  276. withdrawalStatus = 1;
  277. }
  278. setState(() {});
  279. },
  280. ),
  281. )
  282. ],
  283. ),
  284. ),
  285. Container(
  286. margin: EdgeInsets.only(top: 4, bottom: 15),
  287. color: MyColors.cE7E7E7,
  288. height: 0.5,
  289. ),
  290. RichText(
  291. text: TextSpan(
  292. text: '当前零钱余额',
  293. style: TextStyle(
  294. color: MyColors.c999999, fontSize: 15),
  295. children: [
  296. TextSpan(
  297. text: '${balanceDisplay(balance).toStringAsFixed(2)}',
  298. style: TextStyle(
  299. color: MyColors.cFF4233, fontSize: 15),
  300. ),
  301. TextSpan(
  302. text: '元,',
  303. style: TextStyle(
  304. color: MyColors.c999999, fontSize: 15),
  305. ),
  306. TextSpan(
  307. text: '全部提现',
  308. style: TextStyle(
  309. color: MyColors.cFF4233,
  310. fontSize: 15),
  311. recognizer: TapGestureRecognizer()
  312. ..onTap = () {
  313. _controller.text = balance
  314. .toStringAsFixed(2);
  315. showH();
  316. setState(() {
  317. withdrawalStatus = 0;
  318. });
  319. }),
  320. ]),
  321. ),
  322. if (showHandlingFee)
  323. RichText(
  324. text: TextSpan(
  325. text: '手续费',
  326. style: TextStyle(
  327. color: MyColors.c999999, fontSize: 15),
  328. children: [
  329. TextSpan(
  330. text: '${handlingFee.toStringAsFixed(2)}',
  331. style: TextStyle(
  332. color: MyColors.cFF4233,
  333. fontSize: 15),
  334. ),
  335. ]),
  336. ),
  337. if (showHandlingFee)
  338. RichText(
  339. text: TextSpan(
  340. text: '实际到账',
  341. style: TextStyle(
  342. color: MyColors.c999999, fontSize: 15),
  343. children: [
  344. TextSpan(
  345. text:
  346. '${(double.parse(_controller.text.toString()) - handlingFee).toStringAsFixed(2)}',
  347. style: TextStyle(
  348. color: MyColors.cFF4233,
  349. fontSize: 15),
  350. ),
  351. ]),
  352. ),
  353. GestureDetector(
  354. onTap: () {
  355. if (withdrawalPath == -1) {
  356. showToast('请选择提现方式');
  357. return;
  358. }
  359. if (MyCookie().userBean.forbidWithdraw) {
  360. showSimpleDialog('你已经被冻结提现,请联系群主或客服。', context,
  361. () {
  362. Navigator.pop(context);
  363. });
  364. return;
  365. }
  366. if (withdrawalStatus == 0) {
  367. withdrawalStatus = 1;
  368. withdraw();
  369. } else {}
  370. },
  371. behavior: HitTestBehavior.translucent,
  372. child: Container(
  373. decoration: BoxDecoration(
  374. color: withdrawalStatus == 0
  375. ? MyColors.cFF4233
  376. : MyColors.cEFEFEF,
  377. borderRadius: BorderRadius.circular(20)),
  378. child: MyViews().myText('提现', Colors.white, 14),
  379. alignment: Alignment.center,
  380. height: 40,
  381. margin: EdgeInsets.only(top: 20, bottom: 15),
  382. ),
  383. ),
  384. Container(
  385. margin: EdgeInsets.only(bottom: 8),
  386. child: RichText(
  387. text: TextSpan(
  388. text: '您的提现手续费为:',
  389. style: TextStyle(
  390. color: MyColors.c999999, fontSize: 14),
  391. children: [
  392. TextSpan(
  393. text:
  394. '${NumUtil.multiply(percentFee, 100)}%${extraFee == 0 ? '' : '+$extraFee'}',
  395. style: TextStyle(
  396. color: MyColors.cE2A62D,
  397. fontSize: 14),
  398. ),
  399. // TextSpan(
  400. // text: '元',
  401. // style: TextStyle(
  402. // color: MyColors.c999999,
  403. // fontSize: 14),
  404. // ),
  405. ]),
  406. ),
  407. ),
  408. Visibility(
  409. visible: maxPerHand != 0,
  410. child: Container(
  411. margin: EdgeInsets.only(bottom: 8),
  412. child: RichText(
  413. text: TextSpan(
  414. text: '单笔最高限额:',
  415. style: TextStyle(
  416. color: MyColors.c999999, fontSize: 14),
  417. children: [
  418. TextSpan(
  419. text: '$maxPerHand',
  420. style: TextStyle(
  421. color: MyColors.cE2A62D,
  422. fontSize: 14),
  423. ),
  424. TextSpan(
  425. text: '元',
  426. style: TextStyle(
  427. color: MyColors.c999999,
  428. fontSize: 14),
  429. ),
  430. ]),
  431. ),
  432. ),
  433. ),
  434. Visibility(
  435. visible: minPerHand != 0,
  436. child: Container(
  437. margin: EdgeInsets.only(bottom: 8),
  438. child: RichText(
  439. text: TextSpan(
  440. text: '单笔最低限额:',
  441. style: TextStyle(
  442. color: MyColors.c999999, fontSize: 14),
  443. children: [
  444. TextSpan(
  445. text: '$minPerHand',
  446. style: TextStyle(
  447. color: MyColors.cE2A62D,
  448. fontSize: 14),
  449. ),
  450. TextSpan(
  451. text: '元',
  452. style: TextStyle(
  453. color: MyColors.c999999,
  454. fontSize: 14),
  455. ),
  456. ]),
  457. ),
  458. ),
  459. ),
  460. Visibility(
  461. visible: threshold != 0,
  462. child: RichText(
  463. text: TextSpan(
  464. text: '当日免手续费提现额度:',
  465. style: TextStyle(
  466. color: MyColors.c999999, fontSize: 14),
  467. children: [
  468. TextSpan(
  469. text: '$threshold',
  470. style: TextStyle(
  471. color: MyColors.cE2A62D,
  472. fontSize: 14),
  473. ),
  474. TextSpan(
  475. text: '元',
  476. style: TextStyle(
  477. color: MyColors.c999999,
  478. fontSize: 14),
  479. ),
  480. ]),
  481. ),
  482. ),
  483. ],
  484. crossAxisAlignment: CrossAxisAlignment.start,
  485. ),
  486. )
  487. ],
  488. ),
  489. ),
  490. ),
  491. ],
  492. ),
  493. ),
  494. );
  495. }
  496. void withdraw() {
  497. EasyLoading.show();
  498. try {
  499. double amount = double.parse(_controller.text.toString());
  500. if (amount <= balance && amount >= minPerHand) {
  501. var j = {
  502. 'user_uid': MyCookie().getUID(),
  503. 'way': withdrawalPath,
  504. 'amount': amount
  505. };
  506. if (withdrawalPath == 2) {
  507. j['wx_openid'] = MyCookie().userBean.wxOpenid;
  508. }
  509. print(j.toString());
  510. MyDio().post(MyApis.getApi('withdraw'), j, (response, hasError) {
  511. if (!hasError) {
  512. showToast('提现成功');
  513. withdrawalStatus = 2;
  514. queryPersonalInformation();
  515. } else {
  516. setState(() {
  517. withdrawalStatus = 0;
  518. });
  519. }
  520. }, (error) {
  521. setState(() {
  522. withdrawalStatus = 0;
  523. });
  524. });
  525. } else if (amount > balance) {
  526. setState(() {
  527. withdrawalStatus = 0;
  528. });
  529. showSimpleDialog('您的余额不足。', context, () {
  530. Navigator.pop(context);
  531. });
  532. } else {
  533. setState(() {
  534. withdrawalStatus = 0;
  535. });
  536. showSimpleDialog('提现失败:提现金额不能低于$minPerHand元。', context, () {
  537. Navigator.pop(context);
  538. });
  539. }
  540. } catch (e) {
  541. EasyLoading.dismiss();
  542. setState(() {
  543. withdrawalStatus = 0;
  544. EasyLoading.dismiss();
  545. });
  546. showSimpleDialog('输入内容有误,请重新输入', context, () {
  547. Navigator.pop(context);
  548. });
  549. }
  550. }
  551. void queryPersonalInformation() {
  552. MyDio().query({
  553. "key": "user",
  554. "filters": {
  555. "conditions": ["uid == ${MyCookie().getUID()}"]
  556. },
  557. "dims": userDims,
  558. "paging": [1, 20]
  559. }, (response, hasError) {
  560. if (!hasError) {
  561. UserBeanEntity entity =
  562. UserBeanEntity().fromJson(json.decode(response.data.toString()));
  563. MyCookie().userBean = entity.data.data[0];
  564. balance = balanceDisplay(MyCookie().userBean.balance);
  565. EventBus().emit('userChange');
  566. setState(() {});
  567. if (withdrawalStatus == 2) {
  568. Navigator.pop(context);
  569. }
  570. }
  571. }, (error) {});
  572. }
  573. void queryWithdrawalInstructions() {
  574. MyDio().query({
  575. "key": "withdraw_pricing",
  576. "filters": {},
  577. "dims": withdrawPricingDims,
  578. "paging": [1, 20]
  579. }, (response, hasError) {
  580. if (!hasError) {
  581. WithdrawPricingBeanEntity entity = WithdrawPricingBeanEntity()
  582. .fromJson(json.decode(response.data.toString()));
  583. if (entity.data.data.isNotEmpty) {
  584. percentFee = entity.data.data[0].percentFee;
  585. extraFee = entity.data.data[0].extraFee;
  586. threshold = entity.data.data[0].threshold;
  587. maxPerHand = entity.data.data[0].maxPerHand;
  588. minPerHand = entity.data.data[0].minPerHand;
  589. }
  590. }
  591. setState(() {});
  592. }, (error) {});
  593. }
  594. showH() {
  595. try {
  596. double amount = double.parse(_controller.text.toString());
  597. if (amount >= minPerHand) {
  598. handlingFee = double.parse((double.parse(_controller.text.toString()) *
  599. percentFee *
  600. 100)
  601. .toStringAsFixed(0)) /
  602. 100 +
  603. extraFee;
  604. setState(() {
  605. showHandlingFee = true;
  606. });
  607. } else {
  608. setState(() {
  609. showHandlingFee = false;
  610. });
  611. }
  612. } catch (e) {
  613. setState(() {
  614. showHandlingFee = false;
  615. });
  616. }
  617. }
  618. }
  619. class MoneyTextInputFormatter extends TextInputFormatter {
  620. @override
  621. TextEditingValue formatEditUpdate(
  622. TextEditingValue oldValue, TextEditingValue newValue) {
  623. // TODO: implement formatEditUpdate
  624. String newvalueText = newValue.text;
  625. if (newvalueText == ".") {
  626. //第一个数为.
  627. newvalueText = "0.";
  628. } else if (newvalueText.contains(".")) {
  629. if (newvalueText.lastIndexOf(".") != newvalueText.indexOf(".")) {
  630. //输入了2个小数点
  631. newvalueText = newvalueText.substring(0, newvalueText.lastIndexOf('.'));
  632. } else if (newvalueText.length - 1 - newvalueText.indexOf(".") > 2) {
  633. //输入了1个小数点 小数点后两位
  634. newvalueText = newvalueText.substring(0, newvalueText.indexOf(".") + 3);
  635. }
  636. }
  637. return TextEditingValue(
  638. text: newvalueText,
  639. selection: new TextSelection.collapsed(offset: newvalueText.length),
  640. );
  641. }
  642. }