index.js 15 KB

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