Pay.vue 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. <template>
  2. <div class="j-pay">
  3. <div class="j-main">
  4. <div class="price-info">
  5. <span class="info-text">需支付金额</span>
  6. <span class="price-count">
  7. <span class="pc-l">&yen;</span>
  8. <span class="pc-r">{{ orderInfo.price }}</span>
  9. </span>
  10. </div>
  11. <van-radio-group v-model="payWay">
  12. <van-cell-group>
  13. <van-cell v-for="(item, index) in payPlatFormWayMap[env.platform]" :key="index" center clickable :title="item.title" @click="radioCheck(item.type)">
  14. <template #icon>
  15. <div class="label-icon j-icon" :class="item.iconClass"></div>
  16. </template>
  17. <template #right-icon>
  18. <van-radio :name="item.type">
  19. <template #icon>
  20. <div class="radio-icon j-icon icon-duihao"></div>
  21. </template>
  22. </van-radio>
  23. </template>
  24. </van-cell>
  25. </van-cell-group>
  26. </van-radio-group>
  27. </div>
  28. <div class="j-button-group j-footer">
  29. <button class="j-button-confirm" @click="confirmPay">确认支付</button>
  30. </div>
  31. </div>
  32. </template>
  33. <script lang="ts">
  34. import { Component, Vue } from 'vue-property-decorator'
  35. import { Cell, CellGroup, Radio, RadioGroup } from 'vant'
  36. import { mapActions } from 'vuex'
  37. declare const JyObj: any
  38. @Component({
  39. name: 'pay',
  40. components: {
  41. [Cell.name]: Cell,
  42. [CellGroup.name]: CellGroup,
  43. [Radio.name]: Radio,
  44. [RadioGroup.name]: RadioGroup
  45. },
  46. methods: {
  47. ...mapActions({
  48. getOrderDetail: 'pay/orderDetail',
  49. getPaySign: 'pay/paySign',
  50. isPaySuccess: 'pay/isPaySuccess'
  51. })
  52. }
  53. })
  54. export default class Pay extends Vue {
  55. protected getOrderDetail!: any
  56. protected getPaySign!: any
  57. protected isPaySuccess!: any
  58. orderInfo = {
  59. ordercode: '',
  60. paymoney: ''
  61. }
  62. // 将原型的全局变量提出来
  63. env = this.$env
  64. payPlatFormWayMap = {
  65. wx: [
  66. {
  67. title: '微信支付',
  68. type: 'wx_js',
  69. iconClass: 'icon-wx-pay'
  70. }
  71. ],
  72. app: [
  73. {
  74. title: '微信支付',
  75. type: 'wx_app',
  76. iconClass: 'icon-wx-pay'
  77. },
  78. {
  79. title: '支付宝支付',
  80. type: 'ali_app',
  81. iconClass: 'icon-ali-pay'
  82. }
  83. ]
  84. }
  85. payWay = this.payPlatFormWayMap[this.env.platform][0].type
  86. created () {
  87. this.orderInfo.ordercode = this.$route.params.ordercode
  88. }
  89. mounted () {
  90. this.getInfo()
  91. console.log(this.$wxSdk)
  92. }
  93. radioCheck (type) {
  94. this.payWay = type
  95. }
  96. // 获取订单金额
  97. getInfo () {
  98. const toast = this.$toast.loading({
  99. message: '加载中...',
  100. forbidClick: true,
  101. duration: 0
  102. })
  103. this.getOrderDetail({ ordercode: this.orderInfo.ordercode }).then(res => {
  104. toast.clear()
  105. if (res.error_code === 0) {
  106. if (res.data.status === 1) {
  107. this.orderInfo.paymoney = res.data.paymoney
  108. } else {
  109. this.$toast(res.error_msg || '查询订单信息失败')
  110. }
  111. }
  112. })
  113. }
  114. // 确认支付
  115. confirmPay () {
  116. this.$toast.loading({
  117. message: '加载中...',
  118. forbidClick: true,
  119. duration: 0
  120. })
  121. const data = {
  122. payway: this.payWay,
  123. ordercode: this.orderInfo.ordercode
  124. }
  125. this.getPaySign(data).then(res => {
  126. if (res.error_code === 0) {
  127. this.$toast.clear()
  128. if (res.status === 1) {
  129. // 获取参数成功,判断是微信h5还是非微信h5
  130. if (this.env.isWeiXinBrowser) {
  131. this.wxPayCallBack(res.data.payStr)
  132. } else {
  133. this.appPayCallBack(res.data.payStr)
  134. }
  135. } else {
  136. this.$toast(res.error_msg || '获取支付信息失败')
  137. }
  138. }
  139. })
  140. }
  141. // 微信h5支付逻辑
  142. wxPayCallBack (paySign) {
  143. console.log('wxPay')
  144. console.log(paySign)
  145. if (!this.$wxSdk) {
  146. return this.$toast({
  147. message: '微信Sdk初始化失败',
  148. forbidClick: true,
  149. duration: 1000
  150. })
  151. }
  152. const sign = {
  153. timestamp: '',
  154. nonceStr: '',
  155. package: '',
  156. signType: '',
  157. paySign: '',
  158. appId: ''
  159. }
  160. // 进行支付
  161. console.log(this.$wxSdk)
  162. this.$wxSdk.chooseWXPay({
  163. config: {
  164. timestamp: sign.timestamp,
  165. nonceStr: sign.nonceStr,
  166. package: sign.package,
  167. signType: sign.signType,
  168. paySign: sign.paySign,
  169. appId: sign.appId
  170. }
  171. })
  172. }
  173. // app支付逻辑
  174. appPayCallBack (paySign) {
  175. console.log('appPay')
  176. if (this.payWay === 'wx_app') {
  177. // 调微信支付
  178. try {
  179. JyObj.wxPay(paySign)
  180. } catch (error) {
  181. console.log('请在指定环境运行', error)
  182. }
  183. } else if (this.payWay === 'ali_app') {
  184. // 调支付宝支付
  185. try {
  186. JyObj.aliPay(paySign)
  187. } catch (error) {
  188. console.log('请在指定环境运行', error)
  189. }
  190. }
  191. this.checkAppPaySuccess()
  192. }
  193. // 开启定时任务,3s查询一次是否支付成功
  194. checkAppPaySuccess () {
  195. const ordercode = this.orderInfo.ordercode
  196. const checkPaySuccessTimer = setInterval(() => {
  197. this.isPaySuccess({ ordercode }).then(res => {
  198. if (res.error_code === 0 && res.data.status === 1) {
  199. // 支付完成订单,关闭定时器
  200. clearInterval(checkPaySuccessTimer)
  201. this.$router.push(`/pay-success/${ordercode}`)
  202. }
  203. })
  204. }, 3000)
  205. }
  206. }
  207. </script>
  208. <style lang="scss">
  209. .j-pay {
  210. .price-info {
  211. display: flex;
  212. align-items: center;
  213. justify-content: center;
  214. flex-direction: column;
  215. margin-bottom: 8px;
  216. height: 80px;
  217. background-color: #fff;
  218. .info-text {
  219. color: #9B9CA3;
  220. font-size: 12px;
  221. line-height: 18px;
  222. margin-bottom: 4px;
  223. }
  224. .price-count {
  225. color: #FB483D;
  226. font-size: 18px;
  227. line-height: 30px;
  228. .pc-r {
  229. margin-left: 4px;
  230. font-size: 22px;
  231. }
  232. }
  233. }
  234. .van-cell {
  235. height: 54px;
  236. }
  237. .van-radio-group {
  238. .label-icon {
  239. width: 28px;
  240. height: 28px;
  241. }
  242. .van-cell__title {
  243. margin-left: 14px;
  244. font-size: 15px;
  245. line-height: 22px;
  246. color: #171826;
  247. }
  248. .radio-icon {
  249. display: none;
  250. }
  251. .van-radio__icon--checked {
  252. .radio-icon {
  253. display: inline-block;
  254. }
  255. }
  256. }
  257. }
  258. </style>