index.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  1. import React, { Component } from 'react';
  2. import './index.less';
  3. import { Checkbox, Icon } from 'antd';
  4. import Assets from '@src/components/Assets';
  5. import { formatDate } from '@src/services/Tools';
  6. import Tabs from '../Tabs';
  7. import Modal from '../Modal';
  8. import QrCode from '../QrCode';
  9. import { QrCodeAssets } from '../../../Constant';
  10. import { Order } from '../../stores/order';
  11. import { Main } from '../../stores/main';
  12. import { My } from '../../stores/my';
  13. import { User } from '../../stores/user';
  14. export class PayModal extends Component {
  15. constructor(props) {
  16. super(props);
  17. this.state = { show: true };
  18. }
  19. componentWillReceiveProps(nextProps) {
  20. if (nextProps.user.needPay && !this.init) {
  21. this.init = true;
  22. Main.getContract('course')
  23. .then((result) => {
  24. this.setState({ contract: result });
  25. });
  26. }
  27. }
  28. changePay(key) {
  29. const { order } = this.props.user;
  30. if (!order) return;
  31. this.setState({ payInfo: {}, pay: key });
  32. let handler = null;
  33. switch (key) {
  34. case 'wechatpay':
  35. handler = Order.wechatQr(order.id)
  36. .then((result) => {
  37. result.qr = Main.qrCode(result.request);
  38. this.setState({ payInfo: result });
  39. });
  40. break;
  41. case 'alipay':
  42. handler = Order.alipayQr(order.id)
  43. .then((result) => {
  44. result.qr = Main.qrCode(result.request);
  45. this.setState({ payInfo: result });
  46. });
  47. break;
  48. default:
  49. return;
  50. }
  51. handler.then(() => {
  52. this.queryPay();
  53. });
  54. }
  55. queryPay(force) {
  56. const { order, needPay } = this.props.user;
  57. if (this.time) {
  58. clearTimeout(this.time);
  59. }
  60. if (force) {
  61. this.times = 0;
  62. } else {
  63. this.times = (this.times || 0) + 1;
  64. }
  65. this.time = setTimeout(() => {
  66. Order.query(order.id)
  67. .then(result => {
  68. if (result) {
  69. // 支付成功
  70. this.paySuccess();
  71. } else if (needPay) {
  72. this.queryPay();
  73. } else {
  74. this.setState({ select: null, pay: null, order: null, info: null });
  75. }
  76. });
  77. }, 1000);
  78. }
  79. paySuccess() {
  80. const { order } = this.props.user;
  81. const { info } = this.props.user;
  82. Order.getOrder(order.id).then(result => {
  83. User.formatOrder(result);
  84. // 确保开通用的是record记录id
  85. const [checkout] = result.checkouts;
  86. checkout.info.result = checkout.info.result.replace('{email}', info.email).replace('{useExpireDays}', checkout.useExpireDays).replace('{title}', checkout.title);
  87. if (checkout.service === 'vip') {
  88. // 查询最后有效期
  89. My.getVipInfo().then(vip => {
  90. checkout.info.result = checkout.info.result.replace('{endTime}', formatDate(vip.expireTime, 'YYYY-MM-DD'));
  91. User.refreshToken();
  92. this.setState({ show: false, showVipEnd: true, order: result, checkout });
  93. });
  94. } else if (checkout.productType === 'service') {
  95. User.refreshToken();
  96. } else if (order.checkouts.length === 1 && checkout.productType === 'data') {
  97. this.setState({ show: false, showDataEnd: true, order: result, checkout });
  98. } else if (order.checkouts.length === 1) {
  99. if (checkout.productType === 'course' && checkout.number > 0) {
  100. this.setState({ show: false, showVsEnd: true, order: result, checkout });
  101. } else {
  102. this.setState({ show: false, showEnd: true, order: result, checkout });
  103. }
  104. } else {
  105. User.closePay();
  106. }
  107. });
  108. }
  109. confirm() {
  110. const { pay } = this.state;
  111. if (pay === 'bank') {
  112. this.setState({ showBank: true, show: false });
  113. } else {
  114. //
  115. }
  116. }
  117. open() {
  118. const { checkout } = this.state;
  119. Order.useRecord(checkout.id)
  120. .then(() => {
  121. User.closePay();
  122. this.setState({ show: true, pay: null });
  123. });
  124. }
  125. read() {
  126. Order.allCheckout();
  127. User.closePay();
  128. linkTo('/my/data');
  129. }
  130. vs() {
  131. Order.allCheckout();
  132. User.closePay();
  133. linkTo('/my/course?tab=vs');
  134. }
  135. close() {
  136. const { showEnd, showBank } = this.state;
  137. Order.allCheckout();
  138. User.closePay(showEnd || showBank ? null : new Error('支付失败'));
  139. this.setState({ show: true, pay: null, showEnd: false, showBank: false });
  140. }
  141. render() {
  142. const { needPay, order } = this.props.user;
  143. const { show, showBank, showEnd, showVsEnd, showDataEnd, showVipEnd, contract, payInfo } = this.state;
  144. if (!needPay) return [];
  145. return [
  146. showBank && <PayKBankModal
  147. show
  148. order={order}
  149. checkout={order.checkouts[0]}
  150. onConfirm={() => this.close()}
  151. />,
  152. showEnd && <PayMEndModal
  153. show
  154. order={order}
  155. checkout={order.checkouts[0]}
  156. onCancel={() => this.close()}
  157. onClose={() => this.close()}
  158. onConfirm={() => this.open()}
  159. />,
  160. showVsEnd && <PayMEndModal
  161. show
  162. order={order}
  163. checkout={order.checkouts[0]}
  164. onCancel={() => this.close()}
  165. onClose={() => this.close()}
  166. onConfirm={() => this.vs()}
  167. />,
  168. showDataEnd && <PayMDataEndModal
  169. show
  170. order={order}
  171. checkout={order.checkouts[0]}
  172. onCancel={() => this.close()}
  173. onClose={() => this.close()}
  174. onConfirm={() => this.read()}
  175. />,
  176. showVipEnd && <PayMVipEndModal
  177. show
  178. order={order}
  179. checkout={order.checkouts[0]}
  180. onConfirm={() => this.close()}
  181. />,
  182. show && (order.checkouts.length > 1 || order.checkouts[0].productType === 'course_package') && <PayMutilModal
  183. show
  184. contract={contract}
  185. order={order}
  186. payInfo={payInfo}
  187. onChangePay={(key) => this.changePay(key)}
  188. onCancel={() => this.close()}
  189. onClose={() => this.close()}
  190. onConfirm={() => this.confirm()}
  191. />,
  192. show && (order.checkouts.length === 1 && order.checkouts[0].productType !== 'course_package') && <PayMModal
  193. show
  194. contract={contract}
  195. order={order}
  196. payInfo={payInfo}
  197. checkout={order.checkouts[0]}
  198. productType={order.productTypes[0]}
  199. onChangePay={(key) => this.changePay(key)}
  200. onCancel={() => this.close()}
  201. onClose={() => this.close()}
  202. onConfirm={() => this.confirm()}
  203. />,
  204. ];
  205. }
  206. }
  207. export class PayMModal extends Component {
  208. constructor(props) {
  209. super(props);
  210. const payList = [{ key: 'alipay', title: '支付宝' }, { key: 'wechatpay', title: '微信' }];
  211. if (props.productType === 'course') {
  212. payList.push({ key: 'bank', title: '银行转账' });
  213. }
  214. this.state = { pay: 'alipay', payList, checked: true, showChecked: props.productType === 'course' };
  215. setTimeout(() => {
  216. props.onChangePay('alipay');
  217. }, 100);
  218. }
  219. render() {
  220. const { show, checkout, onClose, onConfirm, onChangePay, order, payInfo = {}, contract = {}, productType } = this.props;
  221. const { info } = checkout;
  222. const { pay, payList, checked, showChecked } = this.state;
  223. return (
  224. <Modal
  225. className="pay-modal"
  226. show={show}
  227. width={760}
  228. title={`购买${checkout.title}`}
  229. confirmText={pay === 'bank' ? '确认' : '支付成功'}
  230. onConfirm={pay === 'bank' ? onConfirm : null}
  231. // cancelText="稍后开通"
  232. // onCancel={onCancel}
  233. onClose={onClose}
  234. >
  235. <div className="pay-modal-wrapper">
  236. <div className="info-layout">
  237. <div className="desc">
  238. 商品: {productType === 'data' ? info.title : checkout.title}<br />
  239. {productType !== 'course' && `服务: ${productType === 'data' ? checkout.title : info.description}`}{productType === 'course' && <span>服务: 见<a href={`/contract/${contract.key}`} target="_blank">{contract.title}</a></span>}<br />
  240. 开通有效期: {checkout.expireDays ? `${checkout.expireDays}天` : '付款后立即生效'}
  241. <br />
  242. 使用有效期: {checkout.useExpireDays ? `${checkout.useExpireDays}天` : '永久'}
  243. <br />
  244. 退款政策: {info.refund_policy}
  245. <br />
  246. 版权说明: {info.copyright_notes}
  247. </div>
  248. <div className="money">
  249. <div className="t-2">应付金额:</div>
  250. <div className="t-1 f-w-b t-s-24">¥ {order.money}</div>
  251. </div>
  252. </div>
  253. <div className="pay-layout">
  254. <Tabs
  255. border
  256. size="small"
  257. active={pay}
  258. width={80}
  259. tabs={payList}
  260. render={item => <Assets name={item.key} />}
  261. onChange={key => {
  262. this.setState({ pay: key });
  263. onChangePay(key);
  264. }}
  265. />
  266. <div hidden={pay === 'bank'} className="pay">
  267. <div className="qrcode">
  268. <QrCode width={140} height={140} qrCode={payInfo.qr} vague={!checked} refresh onRefresh={() => onChangePay(pay)} />
  269. </div>
  270. <div className="t">请使用手机微信或支付宝扫码付款</div>
  271. <div className="t">支付金额: ¥ {order.money}</div>
  272. </div>
  273. <div hidden={pay !== 'bank'} className="bank">
  274. <div className="t">汇款银行:{checked ? '中国工商银行上海市浦东支行' : 'xxxxxxxxxxxxx'}</div>
  275. <div className="t">汇款账号:{checked ? '6100 0000 0000 000' : 'xxxx xxxx xxxx xxxx'}</div>
  276. </div>
  277. <div className="agree">
  278. <Checkbox className="m-r-1" disabled={!showChecked} checked={checked} onClick={() => {
  279. this.setState({ showChecked: checked, checked: !checked });
  280. }} />
  281. 我已阅读并同意<a href={`/contract/${contract.key}`} target="_blank">《{contract.title}》</a>
  282. </div>
  283. </div>
  284. <div style={{ bottom: 20, left: 0 }} className="p-a t-3 t-s-14">
  285. *若在购买过程中遇到问题
  286. </div>
  287. <div style={{ bottom: 0, left: 0 }} className="p-a t-3 t-s-14">
  288. 请联系千行小助手:0193191safad 协助解决。
  289. </div>
  290. </div>
  291. </Modal>
  292. );
  293. }
  294. }
  295. export class PayMutilModal extends Component {
  296. constructor(props) {
  297. super(props);
  298. this.state = { pay: 'alipay', checked: true, showChecked: true };
  299. setTimeout(() => {
  300. props.onChangePay('alipay');
  301. }, 100);
  302. }
  303. render() {
  304. const { show, onConfirm, onClose, onChangePay, order, payInfo = {}, contract = {} } = this.props;
  305. const { pay, checked, showChecked } = this.state;
  306. return (
  307. <Modal
  308. className="pay-modal"
  309. show={show}
  310. width={760}
  311. title={'购物车结账'}
  312. confirmText={pay === 'bank' ? '确认' : '支付成功'}
  313. onConfirm={pay === 'bank' ? onConfirm : null}
  314. // onCancel={onCancel}
  315. onClose={onClose}
  316. >
  317. <div className="pay-modal-wrapper">
  318. <div className="info-layout">
  319. <div className="desc">
  320. 商品: {order.checkouts.map(row => (row.productType === 'course_package' ? row.children.map(r => r.title).join(' ') : row.title)).join(' ')}<br />
  321. 服务: 见<a href={`/contract/${contract.key}`} target="_blank">{contract.title}</a><br />
  322. 开通有效期: 见订单详情
  323. <br />
  324. 使用有效期: 见订单详情
  325. <br />
  326. 退款政策: 本商品为虚拟产品,购买成功后不支持退款。<br />
  327. 版权说明: 本商品为虚拟产品,购买成功后不支持退款。
  328. </div>
  329. <div className="money">
  330. <div className="t-2">应付金额:</div>
  331. <div className="t-1 f-w-b t-s-24">¥ {order.money}</div>
  332. </div>
  333. </div>
  334. <div className="pay-layout">
  335. <Tabs
  336. border
  337. size="small"
  338. active={pay}
  339. width={80}
  340. tabs={[
  341. { key: 'alipay', title: '支付宝' },
  342. { key: 'wechatpay', title: '微信' },
  343. { key: 'bank', title: '银行转账' },
  344. ]}
  345. render={item => <Assets name={item.key} />}
  346. onChange={key => {
  347. this.setState({ pay: key });
  348. onChangePay(key);
  349. }}
  350. />
  351. <div hidden={pay === 'bank'} className="pay">
  352. <div className="qrcode">
  353. <QrCode width={140} height={140} qrCode={payInfo.qr} vague={!checked} refresh onRefresh={() => onChangePay(pay)} />
  354. </div>
  355. <div className="t">请使用手机微信或支付宝扫码付款</div>
  356. <div className="t">支付金额: ¥ {order.money}</div>
  357. </div>
  358. <div hidden={pay !== 'bank'} className="bank">
  359. <div className="t">汇款银行:{checked ? '中国工商银行上海市浦东支行' : 'xxxxxxxxxxxxx'}</div>
  360. <div className="t">汇款账号:{checked ? '6100 0000 0000 000' : 'xxxx xxxx xxxx xxxx'}</div>
  361. </div>
  362. <div className="agree">
  363. <Checkbox className="m-r-1" disabled={!showChecked} checked={checked} onClick={() => {
  364. this.setState({ showChecked: checked, checked: !checked });
  365. }} />
  366. 我已阅读并同意<a href={`/contract/${contract.key}`} target="_blank">《{contract.title}》</a>
  367. </div>
  368. </div>
  369. <div style={{ bottom: 20, left: 0 }} className="p-a t-3 t-s-14">
  370. *若在购买过程中遇到问题
  371. </div>
  372. <div style={{ bottom: 0, left: 0 }} className="p-a t-3 t-s-14">
  373. 请联系千行小助手:0193191safad 协助解决。
  374. </div>
  375. </div>
  376. </Modal>
  377. );
  378. }
  379. }
  380. export class PayKBankModal extends Component {
  381. render() {
  382. const { show, onConfirm } = this.props;
  383. return (
  384. <Modal
  385. show={show}
  386. width={630}
  387. title="银行汇款"
  388. btnAlign="center"
  389. confirmText="好的,知道了"
  390. onConfirm={onConfirm}
  391. >
  392. <div style={{ width: 400 }} className="t-2 t-s-18 m-b-2">
  393. 汇款成功后,请添加微信号XXX或扫描二维码联系小助手,进行核实。
  394. </div>
  395. <div className="p-a" style={{ right: 0, top: 50 }}>
  396. <Assets name={QrCodeAssets} width={150} height={150} />
  397. </div>
  398. </Modal>
  399. );
  400. }
  401. }
  402. export class PayMEndModal extends Component {
  403. render() {
  404. const { show, onConfirm, onCancel, checkout = {} } = this.props;
  405. const { info } = checkout;
  406. return (
  407. <Modal
  408. show={show}
  409. width={630}
  410. title="付款成功"
  411. confirmText="立即开通"
  412. cancelText="稍后开通"
  413. onConfirm={onConfirm}
  414. onCancel={onCancel}
  415. >
  416. <div className="t-2 ws-pl">
  417. <Icon className="t-5 m-r-5" type="check" />{info.result}
  418. </div>
  419. {info.tips && <div style={{ bottom: 10, left: 0 }} className="p-a t-3 t-s-14">
  420. *{info.tips}
  421. </div>}
  422. </Modal>
  423. );
  424. }
  425. }
  426. export class PayVsEndModal extends Component {
  427. render() {
  428. const { show, onConfirm, onCancel, checkout = {} } = this.props;
  429. const { info } = checkout;
  430. return (
  431. <Modal
  432. show={show}
  433. width={630}
  434. title="付款成功"
  435. confirmText="立即开通"
  436. cancelText="稍后开通"
  437. onConfirm={onConfirm}
  438. onCancel={onCancel}
  439. >
  440. <div className="t-2 ws-pl">
  441. <Icon className="t-5 m-r-5" type="check" />{info.result}
  442. </div>
  443. {info.tips && <div style={{ bottom: 10, left: 0 }} className="p-a t-3 t-s-14">
  444. *{info.tips}
  445. </div>}
  446. </Modal>
  447. );
  448. }
  449. }
  450. export class PayMDataEndModal extends Component {
  451. render() {
  452. const { show, onConfirm, onCancel, checkout = {} } = this.props;
  453. const { info } = checkout;
  454. return (
  455. <Modal
  456. show={show}
  457. width={630}
  458. title="付款成功"
  459. confirmText="立即查看"
  460. cancelText="暂不查看"
  461. onConfirm={onConfirm}
  462. onCancel={onCancel}
  463. >
  464. <div className="t-2 ws-pl">
  465. <Icon className="t-5 m-r-5" type="check" />{info.result}
  466. </div>
  467. {info.tips && <div style={{ bottom: 10, left: 0 }} className="p-a t-3 t-s-14">
  468. *{info.tips}
  469. </div>}
  470. </Modal>
  471. );
  472. }
  473. }
  474. export class PayMVipEndModal extends Component {
  475. render() {
  476. const { show, onConfirm, checkout = {} } = this.props;
  477. const { info } = checkout;
  478. return (
  479. <Modal
  480. show={show}
  481. width={630}
  482. title="付款成功"
  483. confirmText="知道了"
  484. // cancelText="稍后开通"
  485. onConfirm={onConfirm}
  486. // onCancel={onCancel}
  487. >
  488. <div className="t-2 ws-pl">
  489. <Icon className="t-5 m-r-5" type="check" />{info.result}
  490. </div>
  491. {info.tips && <div style={{ bottom: 10, left: 0 }} className="p-a t-3 t-s-14">
  492. *{info.tips}
  493. </div>}
  494. </Modal>
  495. );
  496. }
  497. }