index.js 15 KB

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