index.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  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. this.setState({ show: false, showEnd: true, order: result, checkout });
  100. } else {
  101. User.closePay();
  102. }
  103. });
  104. }
  105. confirm() {
  106. const { pay } = this.state;
  107. if (pay === 'bank') {
  108. this.setState({ showBank: true, show: false });
  109. } else {
  110. //
  111. }
  112. }
  113. open() {
  114. const { checkout } = this.state;
  115. Order.useRecord(checkout.id)
  116. .then(() => {
  117. User.closePay();
  118. this.setState({ show: true, pay: null });
  119. });
  120. }
  121. read() {
  122. User.closePay();
  123. linkTo('/my/data');
  124. }
  125. close() {
  126. const { showEnd, showBank } = this.state;
  127. User.closePay(showEnd || showBank ? null : new Error('支付失败'));
  128. this.setState({ show: true, pay: null, showEnd: false, showBank: false });
  129. }
  130. render() {
  131. const { needPay, order } = this.props.user;
  132. const { show, showBank, showEnd, showDataEnd, showVipEnd, contract, payInfo } = this.state;
  133. if (!needPay) return [];
  134. return [
  135. showBank && <PayKBankModal
  136. show
  137. order={order}
  138. checkout={order.checkouts[0]}
  139. onConfirm={() => this.close()}
  140. />,
  141. showEnd && <PayMEndModal
  142. show
  143. order={order}
  144. checkout={order.checkouts[0]}
  145. onCancel={() => this.close()}
  146. onClose={() => this.close()}
  147. onConfirm={() => this.open()}
  148. />,
  149. showDataEnd && <PayMDataEndModal
  150. show
  151. order={order}
  152. checkout={order.checkouts[0]}
  153. onCancel={() => this.close()}
  154. onClose={() => this.close()}
  155. onConfirm={() => this.read()}
  156. />,
  157. showVipEnd && <PayMVipEndModal
  158. show
  159. order={order}
  160. checkout={order.checkouts[0]}
  161. onConfirm={() => this.close()}
  162. />,
  163. show && (order.checkouts.length > 1 || order.checkouts[0].productType === 'course_package') && <PayMutilModal
  164. show
  165. contract={contract}
  166. order={order}
  167. payInfo={payInfo}
  168. onChangePay={(key) => this.changePay(key)}
  169. onCancel={() => this.close()}
  170. onClose={() => this.close()}
  171. onConfirm={() => this.confirm()}
  172. />,
  173. show && (order.checkouts.length === 1 && order.checkouts[0].productType !== 'course_package') && <PayMModal
  174. show
  175. contract={contract}
  176. order={order}
  177. payInfo={payInfo}
  178. checkout={order.checkouts[0]}
  179. productType={order.productTypes[0]}
  180. onChangePay={(key) => this.changePay(key)}
  181. onCancel={() => this.close()}
  182. onClose={() => this.close()}
  183. onConfirm={() => this.confirm()}
  184. />,
  185. ];
  186. }
  187. }
  188. export class PayMModal extends Component {
  189. constructor(props) {
  190. super(props);
  191. const payList = [{ key: 'alipay', title: '支付宝' }, { key: 'wechatpay', title: '微信' }];
  192. if (props.productType === 'course') {
  193. payList.push({ key: 'bank', title: '银行转账' });
  194. }
  195. this.state = { pay: 'alipay', payList, checked: true, showChecked: props.productType === 'course' };
  196. setTimeout(() => {
  197. props.onChangePay('alipay');
  198. }, 100);
  199. }
  200. render() {
  201. const { show, checkout, onClose, onConfirm, onChangePay, order, payInfo = {}, contract = {}, productType } = this.props;
  202. const { info } = checkout;
  203. const { pay, payList, checked, showChecked } = this.state;
  204. return (
  205. <Modal
  206. className="pay-modal"
  207. show={show}
  208. width={760}
  209. title={`购买${checkout.title}`}
  210. confirmText={pay === 'bank' ? '确认' : '支付成功'}
  211. onConfirm={pay === 'bank' ? onConfirm : null}
  212. // cancelText="稍后开通"
  213. // onCancel={onCancel}
  214. onClose={onClose}
  215. >
  216. <div className="pay-modal-wrapper">
  217. <div className="info-layout">
  218. <div className="desc">
  219. 商品: {productType === 'data' ? info.title : checkout.title}<br />
  220. {productType !== 'course' && `服务: ${productType === 'data' ? checkout.title : info.description}`}{productType === 'course' && <span>服务: 见<a href={`/contract/${contract.key}`} target="_blank">{contract.title}</a></span>}<br />
  221. 开通有效期: {checkout.expireDays ? `${checkout.expireDays}天` : '付款后立即生效'}
  222. <br />
  223. 使用有效期: {checkout.useExpireDays ? `${checkout.useExpireDays}天` : '永久'}
  224. <br />
  225. 退款政策: {info.refund_policy}
  226. <br />
  227. 版权说明: {info.copyright_notes}
  228. </div>
  229. <div className="money">
  230. <div className="t-2">应付金额:</div>
  231. <div className="t-1 f-w-b t-s-24">¥ {order.money}</div>
  232. </div>
  233. </div>
  234. <div className="pay-layout">
  235. <Tabs
  236. border
  237. size="small"
  238. active={pay}
  239. width={80}
  240. tabs={payList}
  241. render={item => <Assets name={item.key} />}
  242. onChange={key => {
  243. this.setState({ pay: key });
  244. onChangePay(key);
  245. }}
  246. />
  247. <div hidden={pay === 'bank'} className="pay">
  248. <div className="qrcode">
  249. <QrCode width={140} height={140} qrCode={payInfo.qr} vague={!checked} refresh onRefresh={() => onChangePay(pay)} />
  250. </div>
  251. <div className="t">请使用手机微信或支付宝扫码付款</div>
  252. <div className="t">支付金额: ¥ {order.money}</div>
  253. </div>
  254. <div hidden={pay !== 'bank'} className="bank">
  255. <div className="t">汇款银行:{checked ? '中国工商银行上海市浦东支行' : 'xxxxxxxxxxxxx'}</div>
  256. <div className="t">汇款账号:{checked ? '6100 0000 0000 000' : 'xxxx xxxx xxxx xxxx'}</div>
  257. </div>
  258. <div className="agree">
  259. <Checkbox className="m-r-1" disabled={!showChecked} checked={checked} onClick={() => {
  260. this.setState({ showChecked: checked, checked: !checked });
  261. }} />
  262. 我已阅读并同意<a href={`/contract/${contract.key}`} target="_blank">《{contract.title}》</a>
  263. </div>
  264. </div>
  265. <div style={{ bottom: 20, left: 0 }} className="p-a t-3 t-s-14">
  266. *若在购买过程中遇到问题
  267. </div>
  268. <div style={{ bottom: 0, left: 0 }} className="p-a t-3 t-s-14">
  269. 请联系千行小助手:0193191safad 协助解决。
  270. </div>
  271. </div>
  272. </Modal>
  273. );
  274. }
  275. }
  276. export class PayMutilModal extends Component {
  277. constructor(props) {
  278. super(props);
  279. this.state = { pay: 'alipay', checked: true, showChecked: true };
  280. setTimeout(() => {
  281. props.onChangePay('alipay');
  282. }, 100);
  283. }
  284. render() {
  285. const { show, onConfirm, onClose, onChangePay, order, payInfo = {}, contract = {} } = this.props;
  286. const { pay, checked, showChecked } = this.state;
  287. return (
  288. <Modal
  289. className="pay-modal"
  290. show={show}
  291. width={760}
  292. title={'购物车结账'}
  293. confirmText={pay === 'bank' ? '确认' : '支付成功'}
  294. onConfirm={pay === 'bank' ? onConfirm : null}
  295. // onCancel={onCancel}
  296. onClose={onClose}
  297. >
  298. <div className="pay-modal-wrapper">
  299. <div className="info-layout">
  300. <div className="desc">
  301. 商品: {order.checkouts.map(row => (row.productType === 'course_package' ? row.children.map(r => r.title).join(' ') : row.title)).join(' ')}<br />
  302. 服务: 见<a href={`/contract/${contract.key}`} target="_blank">{contract.title}</a><br />
  303. 开通有效期: 见订单详情
  304. <br />
  305. 使用有效期: 见订单详情
  306. <br />
  307. 退款政策: 本商品为虚拟产品,购买成功后不支持退款。<br />
  308. 版权说明: 本商品为虚拟产品,购买成功后不支持退款。
  309. </div>
  310. <div className="money">
  311. <div className="t-2">应付金额:</div>
  312. <div className="t-1 f-w-b t-s-24">¥ {order.money}</div>
  313. </div>
  314. </div>
  315. <div className="pay-layout">
  316. <Tabs
  317. border
  318. size="small"
  319. active={pay}
  320. width={80}
  321. tabs={[
  322. { key: 'alipay', title: '支付宝' },
  323. { key: 'wechatpay', title: '微信' },
  324. { key: 'bank', title: '银行转账' },
  325. ]}
  326. render={item => <Assets name={item.key} />}
  327. onChange={key => {
  328. this.setState({ pay: key });
  329. onChangePay(key);
  330. }}
  331. />
  332. <div hidden={pay === 'bank'} className="pay">
  333. <div className="qrcode">
  334. <QrCode width={140} height={140} qrCode={payInfo.qr} vague={!checked} refresh onRefresh={() => onChangePay(pay)} />
  335. </div>
  336. <div className="t">请使用手机微信或支付宝扫码付款</div>
  337. <div className="t">支付金额: ¥ {order.money}</div>
  338. </div>
  339. <div hidden={pay !== 'bank'} className="bank">
  340. <div className="t">汇款银行:{checked ? '中国工商银行上海市浦东支行' : 'xxxxxxxxxxxxx'}</div>
  341. <div className="t">汇款账号:{checked ? '6100 0000 0000 000' : 'xxxx xxxx xxxx xxxx'}</div>
  342. </div>
  343. <div className="agree">
  344. <Checkbox className="m-r-1" disabled={!showChecked} checked={checked} onClick={() => {
  345. this.setState({ showChecked: checked, checked: !checked });
  346. }} />
  347. 我已阅读并同意<a href={`/contract/${contract.key}`} target="_blank">《{contract.title}》</a>
  348. </div>
  349. </div>
  350. <div style={{ bottom: 20, left: 0 }} className="p-a t-3 t-s-14">
  351. *若在购买过程中遇到问题
  352. </div>
  353. <div style={{ bottom: 0, left: 0 }} className="p-a t-3 t-s-14">
  354. 请联系千行小助手:0193191safad 协助解决。
  355. </div>
  356. </div>
  357. </Modal>
  358. );
  359. }
  360. }
  361. export class PayKBankModal extends Component {
  362. render() {
  363. const { show, onConfirm } = this.props;
  364. return (
  365. <Modal
  366. show={show}
  367. width={630}
  368. title="银行汇款"
  369. btnAlign="center"
  370. confirmText="好的,知道了"
  371. onConfirm={onConfirm}
  372. >
  373. <div style={{ width: 400 }} className="t-2 t-s-18 m-b-2">
  374. 汇款成功后,请添加微信号XXX或扫描二维码联系小助手,进行核实。
  375. </div>
  376. <div className="p-a" style={{ right: 0, top: 50 }}>
  377. <Assets name={QrCodeAssets} width={150} height={150} />
  378. </div>
  379. </Modal>
  380. );
  381. }
  382. }
  383. export class PayMEndModal extends Component {
  384. render() {
  385. const { show, onConfirm, onCancel, checkout = {} } = this.props;
  386. const { info } = checkout;
  387. return (
  388. <Modal
  389. show={show}
  390. width={630}
  391. title="付款成功"
  392. confirmText="立即开通"
  393. cancelText="稍后开通"
  394. onConfirm={onConfirm}
  395. onCancel={onCancel}
  396. >
  397. <div className="t-2 ws-pl">
  398. <Icon className="t-5 m-r-5" type="check" />{info.result}
  399. </div>
  400. {info.tips && <div style={{ bottom: 10, left: 0 }} className="p-a t-3 t-s-14">
  401. *{info.tips}
  402. </div>}
  403. </Modal>
  404. );
  405. }
  406. }
  407. export class PayMDataEndModal extends Component {
  408. render() {
  409. const { show, onConfirm, onCancel, checkout = {} } = this.props;
  410. const { info } = checkout;
  411. return (
  412. <Modal
  413. show={show}
  414. width={630}
  415. title="付款成功"
  416. confirmText="立即查看"
  417. cancelText="暂不查看"
  418. onConfirm={onConfirm}
  419. onCancel={onCancel}
  420. >
  421. <div className="t-2 ws-pl">
  422. <Icon className="t-5 m-r-5" type="check" />{info.result}
  423. </div>
  424. {info.tips && <div style={{ bottom: 10, left: 0 }} className="p-a t-3 t-s-14">
  425. *{info.tips}
  426. </div>}
  427. </Modal>
  428. );
  429. }
  430. }
  431. export class PayMVipEndModal extends Component {
  432. render() {
  433. const { show, onConfirm, checkout = {} } = this.props;
  434. const { info } = checkout;
  435. return (
  436. <Modal
  437. show={show}
  438. width={630}
  439. title="付款成功"
  440. confirmText="知道了"
  441. // cancelText="稍后开通"
  442. onConfirm={onConfirm}
  443. // onCancel={onCancel}
  444. >
  445. <div className="t-2 ws-pl">
  446. <Icon className="t-5 m-r-5" type="check" />{info.result}
  447. </div>
  448. {info.tips && <div style={{ bottom: 10, left: 0 }} className="p-a t-3 t-s-14">
  449. *{info.tips}
  450. </div>}
  451. </Modal>
  452. );
  453. }
  454. }