withdraw_page.dart 28 KB

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