purchase.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  1. <template>
  2. <layout
  3. bgImgName="purchase-img"
  4. bgColor="#FDF2E3"
  5. bgHeight="188"
  6. @goBack="goBack"
  7. >
  8. <div class="purchase">
  9. <div class="purchase-privilege">
  10. <div>
  11. <img src="@/assets/image/claimCloudPhone/privilege-1.png" alt="" />
  12. 应用预装已完成
  13. </div>
  14. <div>
  15. <img src="@/assets/image/claimCloudPhone/privilege-2.png" alt="" />
  16. 任意下单
  17. </div>
  18. <div>
  19. <img src="@/assets/image/claimCloudPhone/privilege-3.png" alt="" />
  20. 立即使用云机
  21. </div>
  22. </div>
  23. <template v-for="item in packageList">
  24. <setMealItem
  25. :key="item.serialNumber"
  26. :data="item"
  27. v-if="item.mealList && item.mealList.length"
  28. :type="0"
  29. @buy="buy"
  30. />
  31. </template>
  32. <van-popup
  33. v-model="visible"
  34. position="bottom"
  35. :style="{ background: 'transparent' }"
  36. >
  37. <div class="payment-container">
  38. <div class="payment-container-title">新增云手机</div>
  39. <div class="payment-container-info">
  40. <div>
  41. <div class="payment-container-info_value">
  42. <span>¥</span>{{ currentData.actualPrice }}
  43. </div>
  44. <div class="payment-container-info_name">
  45. {{ packageType[currentData.phoneType]
  46. }}{{ currentData.day }}天卡
  47. </div>
  48. </div>
  49. </div>
  50. <div class="payment-container-num">
  51. 数量:<van-stepper button-size="18" v-model="stepper" />
  52. </div>
  53. <div class="payment-container-method">
  54. <div class="payment-container-method_title">选择支付方式</div>
  55. <div class="payment-container-method_select">
  56. <template v-for="item in paymentList">
  57. <div
  58. :key="item.key"
  59. v-if="
  60. currentData.paySupportTypeList &&
  61. currentData.paySupportTypeList.includes(item.key)
  62. "
  63. :class="{ active: active === item.key }"
  64. @click="active = item.key"
  65. >
  66. <img
  67. :src="active === item.key ? item.activeImg : item.img"
  68. alt=""
  69. />
  70. {{ item.name }}
  71. <div v-if="active === item.key" class="active-icon">
  72. <van-icon name="success" />
  73. </div>
  74. </div>
  75. </template>
  76. </div>
  77. </div>
  78. <div class="payment-container-amount">
  79. <div>
  80. 需支付金额:<span
  81. ><span>¥</span>{{ currentData.actualPrice * stepper }}
  82. </span>
  83. </div>
  84. <div @click="payment" :class="{ disabled: btnLoading }">
  85. <template v-if="btnLoading"> 正在支付中... </template>
  86. <template v-else> 确认协议并付款</template>
  87. </div>
  88. </div>
  89. <div class="payment-container-agreement">
  90. 购买前阅读<span @click="toAgreement">
  91. 《双子星云手机类型服务协议》
  92. </span>
  93. </div>
  94. </div>
  95. </van-popup>
  96. <van-dialog
  97. v-model="activityPurchaseVisible"
  98. @cancel="confirm(false)"
  99. @confirm="confirm(true)"
  100. show-cancel-button
  101. confirmButtonText="“已完成支付"
  102. confirmButtonColor="#3367d1"
  103. >
  104. <div
  105. style="
  106. font-size: 18px;
  107. font-weight: bold;
  108. text-align: center;
  109. padding-top: 10px;
  110. "
  111. >
  112. 如果您已支付成功
  113. </div>
  114. <div
  115. style="
  116. font-size: 18px;
  117. font-weight: bold;
  118. text-align: center;
  119. padding-bottom: 10px;
  120. "
  121. >
  122. 请点击"已完成支付"按钮
  123. </div>
  124. </van-dialog>
  125. </div>
  126. </layout>
  127. </template>
  128. <script>
  129. import layout from './components/layout';
  130. import setMealItem from './components/setMealItem.vue';
  131. import common from './mixins/common.js';
  132. const RSA = require('@/plugins/wx_rsa.js');
  133. export default {
  134. auth: false,
  135. name: 'purchase',
  136. head: {
  137. title: '0元购机,尽情享受',
  138. },
  139. mixins: [common],
  140. data() {
  141. return {
  142. visible: false,
  143. currentData: {},
  144. packageType: {
  145. VIP: '星动',
  146. SVIP: '星耀',
  147. STARRYSKY: '星空',
  148. STAR: '唔即',
  149. STARPRO: '唔即Pro',
  150. },
  151. stepper: 1,
  152. active: '',
  153. paymentList: [
  154. {
  155. name: '微信',
  156. img: require('@/assets/image/claimCloudPhone/weChat.png'),
  157. activeImg: require('@/assets/image/claimCloudPhone/weChatActvie.png'),
  158. key: 'wxPay',
  159. },
  160. {
  161. name: '支付宝',
  162. img: require('@/assets/image/claimCloudPhone/alipay.png'),
  163. activeImg: require('@/assets/image/claimCloudPhone/alipayActive.png'),
  164. key: 'aliPay',
  165. },
  166. ],
  167. btnLoading: false,
  168. activityPurchaseVisible: false,
  169. };
  170. },
  171. mounted() {
  172. if (sessionStorage.getItem('isAgreementBool')) {
  173. this.currentData = JSON.parse(sessionStorage.getItem('currentData'));
  174. this.stepper = sessionStorage.getItem('stepper');
  175. this.active = sessionStorage.getItem('active');
  176. this.visible = true;
  177. sessionStorage.removeItem('isAgreementBool');
  178. sessionStorage.removeItem('currentData');
  179. sessionStorage.removeItem('active');
  180. sessionStorage.removeItem('stepper');
  181. }
  182. if (localStorage.getItem('activityPurchaseVisible')) {
  183. this.activityPurchaseVisible = true;
  184. localStorage.removeItem('activityPurchaseVisible');
  185. }
  186. this.getActivitySortRuleAndActivityMealList({
  187. personnelMealType: 2,
  188. });
  189. },
  190. components: { layout, setMealItem },
  191. methods: {
  192. buy(data) {
  193. console.log(data);
  194. this.stepper = 1;
  195. this.visible = true;
  196. this.currentData = JSON.parse(JSON.stringify(data));
  197. this.currentData.paySupportTypeList =
  198. this.currentData.paySupportTypeList.split(',');
  199. this.active = this.currentData.paySupportTypeList[0];
  200. },
  201. // 确认支付
  202. payment() {
  203. let params = {
  204. buyType: 1,
  205. quantity: this.stepper,
  206. id: this.currentData.id,
  207. phoneType: this.currentData.phoneType,
  208. activityId: 690009,
  209. returnUrl: location.origin + '/h5/claimCloudPhone/confirmation',
  210. };
  211. params = this.sort_ASCII(params);
  212. console.log(params);
  213. const sign = this.jiaqian(JSON.stringify(params));
  214. this.btnLoading = true;
  215. this.$axios
  216. .$post('pay/v1/order/create', params, { headers: { sign } })
  217. .then((res) => {
  218. console.log(res);
  219. const obj = {
  220. aliPay: 'pay/v1/alipay/h5/spend',
  221. wxPay: 'pay/v1/wxPay/h5/spend',
  222. };
  223. if (res.success) {
  224. localStorage.setItem(
  225. 'activityPurchaseMyOrderNum',
  226. res.data.myOrderNum,
  227. );
  228. const data = {
  229. myOrderNum: res.data.myOrderNum,
  230. };
  231. const headers = {
  232. sign: this.jiaqian(JSON.stringify(data)),
  233. };
  234. this.$axios
  235. .$get(obj[this.active], { headers, params: data })
  236. .then((res) => {
  237. if (this.active === 'aliPay') {
  238. const div = document.createElement('div');
  239. div.innerHTML = res.data;
  240. document.body.appendChild(div);
  241. document.forms[0].submit();
  242. // 这个是为了兼容安卓支付宝没有跳转页面
  243. localStorage.setItem('activityPurchaseVisible', 1);
  244. setTimeout(() => {
  245. this.activityPurchaseVisible = true;
  246. }, 3000);
  247. div.remove();
  248. } else {
  249. window.location.replace(res.data);
  250. }
  251. })
  252. .catch((error) => {
  253. setTimeout(() => {
  254. this.$toast(error.message);
  255. });
  256. })
  257. .finally(() => {
  258. this.btnLoading = false;
  259. });
  260. }
  261. })
  262. .catch((error) => {
  263. this.$toast(error.message);
  264. this.btnLoading = false;
  265. });
  266. // function
  267. },
  268. sort_ASCII(obj) {
  269. var arr = [];
  270. var num = 0;
  271. for (const i in obj) {
  272. arr[num] = i;
  273. num++;
  274. }
  275. var sortArr = arr.sort();
  276. var sortObj = {};
  277. for (var i in sortArr) {
  278. sortObj[sortArr[i]] = obj[sortArr[i]];
  279. }
  280. return sortObj;
  281. },
  282. jiaqian(content) {
  283. console.log(content);
  284. const PrivateKey =
  285. '-----BEGIN PRIVATE KEY-----MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKCIK/zTSJCP4XhNsb7Mc5lALog+oAja/spMjg8U6rAmVzRtKv8qhw1HK0CRbW/XV66uM+kY7fhjaYbjbbzu2PMMfs2GVpG15jCWLug9fn2hvPT1wkXfooJX61yHK7+inxAXPi4vPNi263mSQGbhZTeqbU5p7nLeRGbdFyBQXVKpAgMBAAECgYAu/475RxZAlI8rPHvkY1EYteypoMQTs6HSslUI31PSXHc9dxSWfenqHkLwdWM30jDuiDvUa6MIDHrRrfXr0XWcQ0IJ93jT7ABkFCdxcKEOG1WE8f1kZ5JyPDJjeQiI9R4jJCukpGU0DdzO7ORvRb4oTFQ15quM+3+SjnK5TtfUsQJBAOLLk03D2s7t2R0GPLZq+WL/ebowbRSy4VHP/IQi4K1bJrll0HLznov60m9UML1ATlS2ub98fBRFXEAaAwJE2O0CQQC1NDEWhrAPU5o3xjjcxIUbbYskskbhjaiX/1Vz0UzS4XfYek4SL68WBWPGWTrSbgbvXtaXj0gmcChF5jxOHtUtAkA4mPsqxfy99UdgYeUW1P1lgkH7gAhIyRdH1nK6+wU83el9DPaHKVrgrfiEBeuf3wNtSqhyK/u/B0wtRxCHKW1FAkAXfwcGdryJoDuVE9z3s3vXDKNIRN2wDaBY5UD9XZxqk9XoeiN5dDltz5EafSOFecLocxG8YVXntg9i0PHs506ZAkEAge9AKaXisZ4jCNHRn1LR2R82RtHTLb2mN3Cc6sGo+SnAKczwRwVg9RgnmaLG4Z/7kJpq0ALgEBlkOmy+9joxAw==-----END PRIVATE KEY-----';
  286. const signature = new RSA.KJUR.crypto.Signature({
  287. alg: 'SHA256withRSA',
  288. });
  289. signature.init(PrivateKey);
  290. signature.updateString(content);
  291. const signData = signature.sign();
  292. // 将内容转成base64
  293. return RSA.hex2b64(signData);
  294. },
  295. toAgreement() {
  296. sessionStorage.setItem('currentData', JSON.stringify(this.currentData));
  297. sessionStorage.setItem('active', this.active);
  298. sessionStorage.setItem('stepper', this.stepper);
  299. this.$router.push(
  300. '/claimCloudPhone/agreement?agreementCoding=XYPZYHXY2002',
  301. );
  302. },
  303. goBack() {
  304. this.$router.push('/claimCloudPhone/inviteeExits');
  305. },
  306. confirm(bool) {
  307. if (bool) return this.$router.replace('/claimCloudPhone/confirmation');
  308. this.activityPurchaseVisible = false;
  309. localStorage.removeItem('activityPurchaseVisible');
  310. },
  311. },
  312. };
  313. </script>
  314. <style lang="less" scoped>
  315. .purchase {
  316. height: 100%;
  317. box-sizing: border-box;
  318. padding-top: 188px;
  319. .purchase-privilege {
  320. padding: 16px;
  321. height: 102px;
  322. background: #ffffff;
  323. box-shadow: 0px 2px 4px 0px #f6e5d3;
  324. border-radius: 8px;
  325. display: flex;
  326. justify-content: space-between;
  327. & > div {
  328. text-align: center;
  329. font-family: PingFangSC, PingFang SC;
  330. font-weight: 400;
  331. font-size: 14px;
  332. color: #1c2023;
  333. line-height: 20px;
  334. font-style: normal;
  335. & > img {
  336. width: 42px;
  337. height: 42px;
  338. display: block;
  339. margin: 0 auto;
  340. }
  341. }
  342. }
  343. .payment-container {
  344. border-radius: 10px 10px 0 0;
  345. padding: 16px;
  346. display: flex;
  347. flex-direction: column;
  348. background: #f4f6f8;
  349. overflow-y: auto;
  350. .payment-container-title {
  351. font-family: PingFangSC, PingFang SC;
  352. font-weight: 500;
  353. font-size: 18px;
  354. color: #0a132b;
  355. line-height: 20px;
  356. text-align: center;
  357. font-style: normal;
  358. }
  359. .payment-container-info {
  360. margin-top: 16px;
  361. height: 100px;
  362. background: #ffffff;
  363. border-radius: 16px;
  364. display: flex;
  365. justify-content: center;
  366. align-items: center;
  367. .payment-container-info_value {
  368. font-family: PingFangSC, PingFang SC;
  369. font-weight: 500;
  370. font-size: 28px;
  371. color: #0a132b;
  372. line-height: 32px;
  373. text-align: center;
  374. font-style: normal;
  375. span {
  376. font-size: 18px;
  377. }
  378. }
  379. .payment-container-info_name {
  380. font-family: PingFangSC, PingFang SC;
  381. font-weight: 400;
  382. font-size: 14px;
  383. color: #0a132b;
  384. line-height: 18px;
  385. text-align: center;
  386. font-style: normal;
  387. }
  388. }
  389. .payment-container-num {
  390. margin-top: 16px;
  391. padding: 16px;
  392. box-sizing: border-box;
  393. height: 50px;
  394. background: #ffffff;
  395. border-radius: 16px;
  396. font-family: PingFangSC, PingFang SC;
  397. font-weight: bold;
  398. font-size: 14px;
  399. color: #0a132b;
  400. line-height: 18px;
  401. text-align: left;
  402. display: flex;
  403. font-style: normal;
  404. .van-stepper {
  405. margin-left: 10px;
  406. }
  407. }
  408. .payment-container-method {
  409. .payment-container-method_title {
  410. font-family: PingFangSC, PingFang SC;
  411. font-weight: bold;
  412. font-size: 14px;
  413. color: #0a132b;
  414. line-height: 18px;
  415. text-align: left;
  416. font-style: normal;
  417. margin: 16px 0;
  418. }
  419. .payment-container-method_select {
  420. display: grid;
  421. grid-gap: 10px;
  422. grid-template-columns: repeat(3, 1fr);
  423. & > div {
  424. height: 54px;
  425. line-height: 54px;
  426. background: #edeef0;
  427. border-radius: 6px;
  428. display: flex;
  429. justify-content: center;
  430. align-items: center;
  431. font-family: PingFangSC, PingFang SC;
  432. color: #666666;
  433. border: 1px solid transparent;
  434. font-style: normal;
  435. font-weight: 500;
  436. font-size: 14px;
  437. line-height: 18px;
  438. font-style: normal;
  439. &.active {
  440. background: #ffffff;
  441. border-radius: 6px;
  442. border: 1px solid #3b7fff;
  443. position: relative;
  444. .active-icon {
  445. position: absolute;
  446. top: 0;
  447. right: 0;
  448. width: 26px;
  449. height: 15px;
  450. background: #3a86fe;
  451. border-radius: 0px 6px 0px 6px;
  452. display: flex;
  453. justify-content: center;
  454. align-items: center;
  455. .van-icon-success {
  456. color: #fff;
  457. }
  458. }
  459. }
  460. & > img {
  461. width: 24px;
  462. height: 24px;
  463. margin-right: 4px;
  464. }
  465. }
  466. }
  467. }
  468. .payment-container-amount {
  469. background: #ffffff;
  470. box-shadow: 0px 0px 13px 0px rgba(206, 206, 206, 0.5);
  471. border-radius: 16px;
  472. display: flex;
  473. justify-content: space-between;
  474. margin-top: 24px;
  475. & > div:first-of-type {
  476. font-family: PingFangSC, PingFang SC;
  477. font-weight: 500;
  478. font-size: 14px;
  479. color: #0a132b;
  480. line-height: 20px;
  481. font-style: normal;
  482. padding: 16px 0 16px 16px;
  483. & > span {
  484. font-weight: 500;
  485. font-size: 24px;
  486. color: #f04646;
  487. line-height: 20px;
  488. text-align: left;
  489. font-style: normal;
  490. span {
  491. font-size: 14px;
  492. }
  493. }
  494. }
  495. & > div:last-of-type {
  496. font-family: PingFangSC, PingFang SC;
  497. font-weight: 600;
  498. font-size: 16px;
  499. color: #ffffff;
  500. line-height: 22px;
  501. text-align: center;
  502. font-style: normal;
  503. line-height: 55px;
  504. height: 55px;
  505. width: 136px;
  506. background: linear-gradient(90deg, #38aefc 0%, #3b7fff 100%);
  507. border-radius: 16px;
  508. }
  509. }
  510. .payment-container-agreement {
  511. margin-top: 9px;
  512. font-family: PingFangSC, PingFang SC;
  513. font-weight: 500;
  514. font-size: 12px;
  515. color: #bbbbbb;
  516. line-height: 16px;
  517. text-align: center;
  518. font-style: normal;
  519. span {
  520. color: #3a86fe;
  521. }
  522. }
  523. }
  524. }
  525. .disabled {
  526. opacity: 0.3;
  527. }
  528. </style>