index.js 16 KB

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