app-payment.vue 16 KB

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