app-payment.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. <!-- 全局支付组件 -->
  2. <template>
  3. <view class="app-payment main-center cross-center" :class="showPayment?'show':''">
  4. <view class="modal" v-if="payData">
  5. <view class="title">
  6. <view>支付方式</view>
  7. <view class="cancel" @click="cancel">
  8. <image src="/static/image/icon/close.png"></image>
  9. </view>
  10. </view>
  11. <view class="pay-amount">支付金额 {{payData.amount}} 元</view>
  12. <view class="pay-type-list">
  13. <view v-for="(item, index) in payData.list"
  14. @click="checkPayType(index)"
  15. :key="index"
  16. class="pay-type-item cross-center">
  17. <view class="box-grow-0">
  18. <image class="pay-type-icon" :src="item.icon"></image>
  19. </view>
  20. <view class="box-grow-1">
  21. <view class="pay-type-name">{{item.name}}</view>
  22. <view class="pay-type-desc" v-if="item.desc">{{item.desc}}</view>
  23. </view>
  24. <view class="box-grow-0">
  25. <app-radio v-if="item.checked" :theme="theme" v-model="item.checked" type="round"></app-radio>
  26. </view>
  27. </view>
  28. </view>
  29. <view class="footer">
  30. <app-button type="important" :theme="theme" @click="confirm" round>立即支付</app-button>
  31. </view>
  32. </view>
  33. </view>
  34. </template>
  35. <script>
  36. import Vue from 'vue';
  37. import {mapState} from 'vuex';
  38. import AppRadio from '@/components/basic-component/app-radio/app-radio';
  39. export default {
  40. name: 'app-payment',
  41. components: {AppRadio},
  42. data() {
  43. return {};
  44. },
  45. computed: {
  46. ...mapState({
  47. theme: state => state.mallConfig.theme,
  48. showPayment: state => state.payment.showPayment,
  49. payData: state => state.payment.payData,
  50. }),
  51. },
  52. created() {
  53. this.setPayment();
  54. },
  55. methods: {
  56. setPayment() {
  57. const vm = this;
  58. Vue.use({
  59. install(Vue, options) {
  60. Vue.prototype.$payment = {
  61. pay: vm.pay,
  62. };
  63. },
  64. });
  65. },
  66. pay(id) {
  67. return new Promise((resolve, reject) => {
  68. this.$store.commit('payment/setAll', {
  69. showPayment: false,
  70. payData: null,
  71. payType: null,
  72. id: id,
  73. resolve: resolve,
  74. reject: reject,
  75. });
  76. console.log('debug payment, setAll ok, id:', this.$store.state.payment.id);
  77. console.log('debug payment, setAll ok, resolve:', this.$store.state.payment.resolve);
  78. console.log('debug payment, setAll ok, reject:', this.$store.state.payment.reject);
  79. uni.showLoading({
  80. mask: true,
  81. title: '请求支付...',
  82. });
  83. this.$request({
  84. url: this.$api.payment.get_payments,
  85. data: {
  86. id: id,
  87. }
  88. }).then(response => {
  89. uni.hideLoading();
  90. console.log('debug 1--->', response);
  91. if (response.code === 0) {
  92. console.log('debug payment, set resolve 2,', this.$store.state.payment.resolve);
  93. return this.showPaymentModal(response.data);
  94. } else {
  95. response.errMsg = response.msg || '';
  96. return this.$store.state.payment.reject(response.msg);
  97. }
  98. }).catch(e => {
  99. uni.hideLoading();
  100. e.errMsg = e.msg || '';
  101. return this.$store.state.payment.reject(e);
  102. });
  103. });
  104. },
  105. showPaymentModal(data) {
  106. console.log('debug 2--->', data);
  107. for (let i in data.list) {
  108. if (typeof data.list[i].checked === 'undefined') {
  109. data.list[i].checked = false;
  110. }
  111. }
  112. this.$store.commit('payment/payData', data);
  113. if (data.amount === 0 || data.amount === 0.00 || data.amount === '0' || data.amount === '0.00') {
  114. this.$store.commit('payment/payType', 'balance');
  115. for (let i in this.$store.state.payment.payData.list) {
  116. if (this.$store.state.payment.payData.list[i].key === 'balance') {
  117. this.$store.state.payment.payData.list[i].checked = true;
  118. } else {
  119. this.$store.state.payment.payData.list[i].checked = false;
  120. }
  121. }
  122. this.confirm();
  123. return;
  124. }
  125. this.$store.commit('payment/showPayment', true);
  126. },
  127. confirm() {
  128. console.log('payment confirm 1:');
  129. console.log('debug payment, confirm 1,', this.$store.state.payment.resolve);
  130. for (let i in this.$store.state.payment.payData.list) {
  131. if (this.$store.state.payment.payData.list[i].checked) {
  132. this.$store.commit('payment/payType', this.$store.state.payment.payData.list[i].key);
  133. }
  134. }
  135. if (!this.$store.state.payment.payType) {
  136. uni.showModal({
  137. title: '提示',
  138. content: '请选择支付方式',
  139. showCancel: false,
  140. });
  141. return;
  142. }
  143. this.$store.commit('payment/showPayment', false);
  144. console.log('payment confirm 2:', this.$store.state.payment.payType);
  145. console.log('debug payment, confirm 2,', this.$store.state.payment.resolve);
  146. return this.getPayData();
  147. },
  148. cancel() {
  149. this.$store.commit('payment/showPayment', false);
  150. return this.$store.state.payment.reject({
  151. errMsg: '支付取消',
  152. });
  153. },
  154. checkPayType(index) {
  155. if (this.$store.state.payment.payData.list[index].disabled || this.$store.state.payment.payData.list[index].checked) {
  156. return false;
  157. }
  158. const payData = this.$store.state.payment.payData;
  159. for (let i in payData.list) {
  160. if (i == index) {
  161. payData.list[i].checked = true;
  162. } else {
  163. payData.list[i].checked = false;
  164. }
  165. }
  166. this.$store.commit('payment/payData', payData);
  167. },
  168. getPayData() {
  169. console.log('debug payment, getPayData 1,', this.$store.state.payment.resolve);
  170. uni.showLoading({
  171. mask: true,
  172. title: '请求支付...',
  173. });
  174. this.$request({
  175. url: this.$api.payment.pay_data,
  176. data: {
  177. id: this.$store.state.payment.id,
  178. pay_type: this.$store.state.payment.payType,
  179. }
  180. }).then(response => {
  181. uni.hideLoading();
  182. if (response.code === 0) {
  183. switch (this.$store.state.payment.payType) {
  184. case 'balance':
  185. this.callBranch(response.data);
  186. break;
  187. case 'huodao':
  188. this.callHuodao(response.data);
  189. break;
  190. default:
  191. console.log('debug payment, getPayData 2,', this.$store.state.payment.resolve);
  192. this.callPlatformPayment(response.data);
  193. break;
  194. }
  195. } else {
  196. return this.$store.state.payment.reject(response.msg);
  197. }
  198. }).catch(e => {
  199. uni.hideLoading();
  200. e.errMsg = e.msg || '';
  201. return this.$store.state.payment.reject(e);
  202. });
  203. },
  204. callBranch(data) {
  205. if (data.order_amount === 0 || data.order_amount === 0.00 || data.order_amount === '0' || data.order_amount === '0.00') {
  206. this.payByBalance();
  207. } else {
  208. uni.showModal({
  209. title: '余额支付确认',
  210. content: `账户余额:${data.balance_amount},支付金额:${data.order_amount}`,
  211. success: (e) => {
  212. if (e.confirm) {
  213. this.payByBalance();
  214. } else {
  215. return this.$store.state.payment.reject({
  216. errMsg: '支付取消.',
  217. });
  218. }
  219. }
  220. });
  221. }
  222. },
  223. payByBalance() {
  224. uni.showLoading({
  225. mask: true,
  226. title: '支付中...',
  227. });
  228. this.$request({
  229. url: this.$api.payment.pay_buy_balance,
  230. data: {
  231. id: this.$store.state.payment.id,
  232. }
  233. }).then(response => {
  234. uni.hideLoading();
  235. if (response.code === 0) {
  236. return this.$store.state.payment.resolve({
  237. errMsg: '支付成功',
  238. });
  239. } else {
  240. return this.$store.state.payment.reject({
  241. errMsg: response.msg,
  242. });
  243. }
  244. }).catch(e => {
  245. e.errMsg = e.msg || '';
  246. return this.$store.state.payment.reject(e);
  247. });
  248. },
  249. callHuodao(data) {
  250. uni.showLoading({
  251. mask: true,
  252. title: '提交中...',
  253. });
  254. this.$request({
  255. url: this.$api.payment.pay_buy_huodao,
  256. data: {
  257. id: this.$store.state.payment.id,
  258. },
  259. }).then(response => {
  260. uni.hideLoading();
  261. if (response.code === 0) {
  262. return this.$store.state.payment.resolve({
  263. errMsg: '支付成功',
  264. });
  265. } else {
  266. return this.$store.state.payment.reject({
  267. errMsg: response.msg,
  268. });
  269. }
  270. }).catch(e => {
  271. uni.hideLoading();
  272. e.errMsg = e.msg || '';
  273. return this.$store.state.payment.reject(e);
  274. });
  275. },
  276. callPlatformPayment(data) {
  277. console.log('debug payment, callPlatformPayment 1,', this.$store.state.payment.resolve);
  278. let paymentProvider = null;
  279. // #ifdef MP-WEIXIN
  280. paymentProvider = ['wxpay'];
  281. // #endif
  282. // #ifdef MP-ALIPAY
  283. paymentProvider = ['alipay'];
  284. // #endif
  285. // #ifdef MP-BAIDU
  286. paymentProvider = ['baidu'];
  287. // #endif
  288. // #ifdef MP-TOUTIAO
  289. paymentProvider = ['toutiao'];
  290. // #endif
  291. uni.requestPayment({
  292. provider: paymentProvider,
  293. success: (e) => {
  294. console.log('debug payment, callPlatformPayment 3,', this.$store.state.payment.resolve);
  295. console.log('success:', e);
  296. // #ifndef MP-ALIPAY
  297. return this.$store.state.payment.resolve(e);
  298. // #endif
  299. // #ifdef MP-ALIPAY
  300. if (e.resultCode === 9000 || e.resultCode === '9000') {
  301. return this.$store.state.payment.resolve(e);
  302. } else {
  303. return this.$store.state.payment.reject({
  304. errMsg: e.memo,
  305. });
  306. }
  307. // #endif
  308. },
  309. fail: (e) => {
  310. const cancelMsgList = [
  311. 'requestPayment:fail cancel',
  312. ];
  313. if (e.errMsg && cancelMsgList.indexOf(e.errMsg) >= 0) {
  314. e.errMsg = '取消支付';
  315. }
  316. console.log('debug payment, callPlatformPayment 4,', this.$store.state.payment.resolve);
  317. console.log('fail:', e);
  318. return this.$store.state.payment.reject(e);
  319. },
  320. ...data
  321. });
  322. },
  323. },
  324. }
  325. </script>
  326. <style scoped lang="scss">
  327. $bigPadding: #{50rpx};
  328. $smallPadding: #{25rpx};
  329. $middlePadding: #{30rpx};
  330. $smallFont: #{24rpx};
  331. $lineWidth: #{1rpx};
  332. $modalWidth: #{600rpx};
  333. $iconWidth: #{60rpx};
  334. .app-payment {
  335. background: rgba(0, 0, 0, .5);
  336. position: fixed;
  337. z-index: 2000;
  338. left: 0;
  339. top: 0;
  340. width: 100%;
  341. height: 100%;
  342. visibility: hidden;
  343. opacity: 0;
  344. transition: 150ms;
  345. .modal {
  346. background: #fff;
  347. width: $modalWidth;
  348. border-radius: #{15rpx};
  349. .title {
  350. text-align: center;
  351. padding: $middlePadding;
  352. border-bottom: $lineWidth solid #e2e2e2;
  353. position: relative;
  354. }
  355. .cancel {
  356. position: absolute;
  357. right: 0;
  358. top: 0;
  359. padding: $middlePadding;
  360. image {
  361. width: #{36rpx};
  362. height: #{36rpx};
  363. }
  364. }
  365. .pay-amount {
  366. text-align: center;
  367. padding: $bigPadding;
  368. font-weight: bolder;
  369. }
  370. .pay-type-list {
  371. padding: 0 $bigPadding;
  372. }
  373. .pay-type-item {
  374. border-bottom: $lineWidth solid #e2e2e2;
  375. padding: $smallPadding 0;
  376. .pay-type-icon {
  377. width: $iconWidth;
  378. height: $iconWidth;
  379. margin-right: $smallPadding;
  380. }
  381. .pay-type-desc {
  382. color: #909090;
  383. font-size: $smallFont;
  384. }
  385. }
  386. .pay-type-item:last-child {
  387. border-bottom: none;
  388. }
  389. .footer {
  390. padding: $bigPadding;
  391. }
  392. }
  393. }
  394. .app-payment.show {
  395. visibility: visible;
  396. opacity: 1;
  397. }
  398. </style>