withdraw_page.dart 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653
  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_colors.dart';
  10. import 'package:bbyyy/my_tools/my_cookie.dart';
  11. import 'package:bbyyy/my_tools/my_tools.dart';
  12. import 'package:bbyyy/my_tools/my_views.dart';
  13. import 'package:bbyyy/paegs/mine_page/bind_alipay_page/bind_alipay_page.dart';
  14. import 'package:bbyyy/pay/pay_tools.dart';
  15. import 'package:flustars/flustars.dart';
  16. import 'package:flutter/cupertino.dart';
  17. import 'package:flutter/gestures.dart';
  18. import 'package:flutter/material.dart';
  19. import 'package:flutter/services.dart';
  20. class WithdrawPage extends StatefulWidget {
  21. @override
  22. _WithdrawPageState createState() => _WithdrawPageState();
  23. }
  24. class _WithdrawPageState extends State<WithdrawPage> {
  25. TextEditingController _controller = TextEditingController();
  26. int withdrawalStatus = 1; //0--未提现 1--提现中 2--提现完成
  27. double percentFee = 0.0;
  28. double extraFee = 0.0;
  29. double threshold = 0.0;
  30. double maxPerHand = 0.0;
  31. double minPerHand = 0.0;
  32. int withdrawalPath = -1; // 1---支付宝 2---微信
  33. List<PayWayBeanData> payWays;
  34. bool showAlipay = false;
  35. bool showWeChat = false;
  36. bool showHandlingFee = false;
  37. double handlingFee = 0.0;
  38. @override
  39. void initState() {
  40. // TODO: implement initState
  41. super.initState();
  42. queryPersonalInformation();
  43. queryWithdrawalInstructions();
  44. Future.delayed(Duration.zero, () {
  45. checkPaymentMethod((response, hasError) {
  46. if (!hasError) {
  47. PayWayBeanEntity entity =
  48. PayWayBeanEntity().fromJson(json.decode(response.toString()));
  49. payWays = entity.data;
  50. showWeChat =
  51. payWays[payWays.indexWhere((element) => element.way == 2)]
  52. .withdraw;
  53. showAlipay =
  54. payWays[payWays.indexWhere((element) => element.way == 1)]
  55. .withdraw;
  56. if (MyCookie().userBean.wxOpenid.isNotEmpty &&
  57. payWays[payWays.indexWhere((element) => element.way == 2)]
  58. .withdraw) {
  59. withdrawalPath = 2;
  60. } else if (MyCookie().userBean.aliPayAccount.isNotEmpty &&
  61. payWays[payWays.indexWhere((element) => element.way == 1)]
  62. .withdraw) {
  63. withdrawalPath = 1;
  64. }
  65. setState(() {});
  66. }
  67. }, (e) {});
  68. });
  69. }
  70. @override
  71. Widget build(BuildContext context) {
  72. return GestureDetector(
  73. onTap: () {
  74. MyTools().hideKeyboard(context);
  75. },
  76. behavior: HitTestBehavior.translucent,
  77. child: Scaffold(
  78. backgroundColor: MyColors.cF7F7F7,
  79. body: Column(
  80. children: [
  81. MyViews().myAppBar('申请提现', context, [
  82. GestureDetector(
  83. onTap: () {
  84. MyTools().toPage(context, BindAlipayPage(), (then) {
  85. setState(() {});
  86. });
  87. },
  88. behavior: HitTestBehavior.translucent,
  89. child: Container(
  90. padding: EdgeInsets.symmetric(vertical: 8, horizontal: 16),
  91. child: Text(
  92. '修改绑定',
  93. style: TextStyle(color: MyColors.c333333, fontSize: 16),
  94. ),
  95. ),
  96. ),
  97. ]),
  98. Expanded(
  99. child: SingleChildScrollView(
  100. child: Column(
  101. children: [
  102. if (showAlipay)
  103. GestureDetector(
  104. onTap: () {
  105. if (!payWays[payWays
  106. .indexWhere((element) => element.way == 1)]
  107. .withdraw) {
  108. showToast('支付宝提现暂时维护中');
  109. return;
  110. }
  111. if (MyCookie().userBean.aliPayAccount.isEmpty) {
  112. showToast('未绑定支付宝');
  113. } else {
  114. setState(() {
  115. withdrawalPath = 1;
  116. });
  117. }
  118. },
  119. behavior: HitTestBehavior.translucent,
  120. child: Container(
  121. margin: EdgeInsets.fromLTRB(17, 24, 17, 0),
  122. child: Row(
  123. children: [
  124. Container(
  125. decoration: BoxDecoration(
  126. color: withdrawalPath == 1
  127. ? MyColors.cFF4233
  128. : MyColors.cD0D0D0,
  129. borderRadius: BorderRadius.circular(9)),
  130. height: 18,
  131. width: 18,
  132. child: Icon(
  133. Icons.check,
  134. color: Colors.white,
  135. size: 14,
  136. ),
  137. alignment: Alignment.center,
  138. margin: EdgeInsets.only(right: 10),
  139. ),
  140. MyViews().myText(
  141. '提现到支付宝:${MyCookie().userBean.aliPayAccount.isEmpty ? '未绑定支付宝' : MyCookie().userBean.aliPayAccount}',
  142. MyColors.c666666,
  143. 15),
  144. ],
  145. ),
  146. ),
  147. ),
  148. if (showWeChat)
  149. GestureDetector(
  150. onTap: () {
  151. if (!payWays[payWays
  152. .indexWhere((element) => element.way == 2)]
  153. .withdraw) {
  154. showToast('微信提现暂时维护中');
  155. return;
  156. }
  157. if (MyCookie().userBean.wxOpenid.isEmpty) {
  158. showToast('未绑定微信');
  159. } else {
  160. setState(() {
  161. withdrawalPath = 2;
  162. });
  163. }
  164. },
  165. behavior: HitTestBehavior.translucent,
  166. child: Container(
  167. margin: EdgeInsets.fromLTRB(17, 24, 17, 0),
  168. child: Row(
  169. children: [
  170. Container(
  171. decoration: BoxDecoration(
  172. color: withdrawalPath == 2
  173. ? MyColors.cFF4233
  174. : MyColors.cD0D0D0,
  175. borderRadius: BorderRadius.circular(9)),
  176. height: 18,
  177. width: 18,
  178. child: Icon(
  179. Icons.check,
  180. color: Colors.white,
  181. size: 14,
  182. ),
  183. alignment: Alignment.center,
  184. margin: EdgeInsets.only(right: 10),
  185. ),
  186. MyViews().myText('提现到微信:', MyColors.c666666, 15),
  187. MyCookie().userBean.wxOpenid.isEmpty
  188. ? MyViews()
  189. .myText('未绑定微信', MyColors.c666666, 15)
  190. : Row(
  191. children: [
  192. Container(
  193. margin: EdgeInsets.only(right: 10),
  194. child: ClipRRect(
  195. borderRadius:
  196. BorderRadius.circular(12),
  197. child: MyViews().netImg(
  198. MyCookie().userBean.wxPicture,
  199. 24,
  200. 24),
  201. ),
  202. ),
  203. MyViews().myText(
  204. MyCookie().userBean.wxName,
  205. MyColors.c666666,
  206. 15)
  207. ],
  208. )
  209. ],
  210. ),
  211. ),
  212. ),
  213. Container(
  214. decoration: BoxDecoration(
  215. color: Colors.white,
  216. borderRadius: BorderRadius.circular(4),
  217. ),
  218. margin:
  219. EdgeInsets.symmetric(horizontal: 17, vertical: 14),
  220. padding:
  221. EdgeInsets.symmetric(horizontal: 20, vertical: 15),
  222. child: Column(
  223. children: [
  224. MyViews().myText('提现金额', MyColors.c333333, 16),
  225. Container(
  226. margin: EdgeInsets.only(top: 15),
  227. child: Row(
  228. children: [
  229. Text(
  230. '¥',
  231. style: TextStyle(
  232. color: MyColors.c333333, fontSize: 30),
  233. ),
  234. Expanded(
  235. child: TextField(
  236. inputFormatters: [
  237. FilteringTextInputFormatter.allow(
  238. RegExp("[0-9.]")),
  239. MoneyTextInputFormatter()
  240. ],
  241. controller: _controller,
  242. cursorColor: MyColors.cFF4233,
  243. cursorWidth: 1.0,
  244. decoration: InputDecoration(
  245. border: InputBorder.none,
  246. disabledBorder: InputBorder.none,
  247. enabledBorder: InputBorder.none,
  248. focusedBorder: InputBorder.none,
  249. hintText: '请输入金额',
  250. hintStyle: TextStyle(
  251. color: MyColors.c999999,
  252. fontSize: 16),
  253. isDense: true,
  254. contentPadding:
  255. const EdgeInsets.fromLTRB(
  256. 14, 4.5, 8, 4.5)),
  257. maxLines: 1,
  258. style: TextStyle(
  259. color: MyColors.c333333,
  260. fontSize: 30,
  261. fontWeight: FontWeight.bold,
  262. height: 1.3,
  263. letterSpacing: 0.2),
  264. keyboardType: TextInputType.number,
  265. onChanged: (t) {
  266. try {
  267. showH();
  268. double amount = double.parse(t);
  269. if (amount > 0) {
  270. withdrawalStatus = 0;
  271. setState(() {});
  272. }
  273. } catch (e) {
  274. withdrawalStatus = 1;
  275. }
  276. setState(() {});
  277. },
  278. ),
  279. )
  280. ],
  281. ),
  282. ),
  283. Container(
  284. margin: EdgeInsets.only(top: 4, bottom: 15),
  285. color: MyColors.cE7E7E7,
  286. height: 0.5,
  287. ),
  288. RichText(
  289. text: TextSpan(
  290. text: '当前零钱余额',
  291. style: TextStyle(
  292. color: MyColors.c999999, fontSize: 15),
  293. children: [
  294. TextSpan(
  295. text: '${MyCookie().userBean.balance}',
  296. style: TextStyle(
  297. color: MyColors.cFF4233, fontSize: 15),
  298. ),
  299. TextSpan(
  300. text: '元,',
  301. style: TextStyle(
  302. color: MyColors.c999999, fontSize: 15),
  303. ),
  304. TextSpan(
  305. text: '全部提现',
  306. style: TextStyle(
  307. color: MyColors.cFF4233,
  308. fontSize: 15),
  309. recognizer: TapGestureRecognizer()
  310. ..onTap = () {
  311. _controller.text = MyCookie()
  312. .userBean
  313. .balance
  314. .toString();
  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',
  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}',
  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. try {
  498. double amount = double.parse(_controller.text.toString());
  499. if (amount <= MyCookie().userBean.balance && amount >= minPerHand) {
  500. var j = {
  501. 'user_uid': MyCookie().getUID(),
  502. 'way': withdrawalPath,
  503. 'amount': amount
  504. };
  505. if (withdrawalPath == 2) {
  506. j['wx_openid'] = MyCookie().userBean.wxOpenid;
  507. }
  508. print(j.toString());
  509. MyDio().post('/pay/withdraw', j, (response, hasError) {
  510. if (!hasError) {
  511. showToast('提现成功');
  512. withdrawalStatus = 2;
  513. queryPersonalInformation();
  514. } else {
  515. setState(() {
  516. withdrawalStatus = 0;
  517. });
  518. }
  519. }, (error) {
  520. setState(() {
  521. withdrawalStatus = 0;
  522. });
  523. });
  524. } else if (amount > MyCookie().userBean.balance) {
  525. setState(() {
  526. withdrawalStatus = 0;
  527. });
  528. showSimpleDialog('您的余额不足。', context, () {
  529. Navigator.pop(context);
  530. });
  531. } else {
  532. setState(() {
  533. withdrawalStatus = 0;
  534. });
  535. showSimpleDialog('提现失败:提现金额不能低于$minPerHand元。', context, () {
  536. Navigator.pop(context);
  537. });
  538. }
  539. } catch (e) {
  540. setState(() {
  541. withdrawalStatus = 0;
  542. EasyLoading.dismiss();
  543. });
  544. showSimpleDialog('输入内容有误,请重新输入', context, () {
  545. Navigator.pop(context);
  546. });
  547. }
  548. }
  549. void queryPersonalInformation() {
  550. MyDio().query({
  551. "key": "user",
  552. "filters": {
  553. "conditions": ["uid == ${MyCookie().getUID()}"]
  554. },
  555. "dims": userDims,
  556. "paging": [1, 20]
  557. }, (response, hasError) {
  558. if (!hasError) {
  559. UserBeanEntity entity =
  560. UserBeanEntity().fromJson(json.decode(response.data.toString()));
  561. MyCookie().userBean = entity.data.data[0];
  562. EventBus().emit('userChange');
  563. setState(() {});
  564. if (withdrawalStatus == 2) {
  565. Navigator.pop(context);
  566. }
  567. }
  568. }, (error) {});
  569. }
  570. void queryWithdrawalInstructions() {
  571. MyDio().query({
  572. "key": "withdraw_pricing",
  573. "filters": {},
  574. "dims": withdrawPricingDims,
  575. "paging": [1, 20]
  576. }, (response, hasError) {
  577. if (!hasError) {
  578. WithdrawPricingBeanEntity entity = WithdrawPricingBeanEntity()
  579. .fromJson(json.decode(response.data.toString()));
  580. if (entity.data.data.isNotEmpty) {
  581. percentFee = entity.data.data[0].percentFee;
  582. extraFee = entity.data.data[0].extraFee;
  583. threshold = entity.data.data[0].threshold;
  584. maxPerHand = entity.data.data[0].maxPerHand;
  585. minPerHand = entity.data.data[0].minPerHand;
  586. }
  587. }
  588. setState(() {});
  589. }, (error) {});
  590. }
  591. showH() {
  592. try {
  593. double amount = double.parse(_controller.text.toString());
  594. if (amount >= minPerHand) {
  595. handlingFee = double.parse((double.parse(_controller.text.toString()) *
  596. percentFee *
  597. 100)
  598. .toStringAsFixed(0)) /
  599. 100 +
  600. extraFee;
  601. setState(() {
  602. showHandlingFee = true;
  603. });
  604. } else {
  605. setState(() {
  606. showHandlingFee = false;
  607. });
  608. }
  609. } catch (e) {
  610. setState(() {
  611. showHandlingFee = false;
  612. });
  613. }
  614. }
  615. }
  616. class MoneyTextInputFormatter extends TextInputFormatter {
  617. @override
  618. TextEditingValue formatEditUpdate(
  619. TextEditingValue oldValue, TextEditingValue newValue) {
  620. // TODO: implement formatEditUpdate
  621. String newvalueText = newValue.text;
  622. if (newvalueText == ".") {
  623. //第一个数为.
  624. newvalueText = "0.";
  625. } else if (newvalueText.contains(".")) {
  626. if (newvalueText.lastIndexOf(".") != newvalueText.indexOf(".")) {
  627. //输入了2个小数点
  628. newvalueText = newvalueText.substring(0, newvalueText.lastIndexOf('.'));
  629. } else if (newvalueText.length - 1 - newvalueText.indexOf(".") > 2) {
  630. //输入了1个小数点 小数点后两位
  631. newvalueText = newvalueText.substring(0, newvalueText.indexOf(".") + 3);
  632. }
  633. }
  634. return TextEditingValue(
  635. text: newvalueText,
  636. selection: new TextSelection.collapsed(offset: newvalueText.length),
  637. );
  638. }
  639. }