pay.vue 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. <template>
  2. <div class="min-h-[500px]" v-loading="loading">
  3. <div class="main-container" v-if="payInfo">
  4. <div class="mt-[40px] py-[56px] px-[30px] bg-[#fff] flex items-center justify-between mb-[20px] rounded-[var(--rounded-big)]">
  5. <div class="flex">
  6. <img src="@/assets/images/pay/pay.png" class="w-[100px] h-[100px]">
  7. <div class="ml-[30px] w-[375px] flex flex-col justify-center">
  8. <div class="text-[20px] text-[#333] font-700 mb-[20px]">订单提交成功,去付款吧~</div>
  9. </div>
  10. </div>
  11. <div class="flex flex-col">
  12. <div class="text-[#333] text-[14px] mb-[20px] flex items-baseline">
  13. <span> 应付总额: </span>
  14. <div class="text[var(--el-price)] text-[14px] font-500">
  15. <span class="price-font">¥</span>
  16. <span class="text-[30px] price-font">{{payInfo.money}}</span>
  17. </div>
  18. </div>
  19. </div>
  20. </div>
  21. <div class="bg-[#fff] p-[30px] rounded-[var(--rounded-big)]">
  22. <div class="text-[16px] text-[#282828] mb-[30px]">选择以下支付方式</div>
  23. <div class="flex items-center mb-[30px]" v-if="payInfo.pay_type_list.length">
  24. <template v-for="(item, index) in payInfo.pay_type_list" :key="index">
  25. <div class="w-[270px] h-[80px] border-[1px] border-solid cursor-pointer rounded-[8px] flex justify-center items-center mr-[20px]" :class="{'border-[var(--el-color-primary)]' : item.key == type}" @click="payTypeFn(item.key)">
  26. <div class="iconfont icon-weixinzhifu !text-[36px] text-[#09bb07] mr-[14px]" v-if="item.key == 'wechatpay'"></div>
  27. <div class="iconfont icon-zhifubaozhifu !text-[36px] text-[#00aaea] mr-[14px]" v-else-if="item.key == 'alipay'"></div>
  28. <div class="iconfont icon-yuezhifu !text-[36px] text-[#fe9c01] mr-[14px]" v-else></div>
  29. <div class="text-[#4E4E4E] text-[16px] leading-[21px]">{{ item.name }}</div>
  30. </div>
  31. </template>
  32. </div>
  33. <div class="mt-[30px] flex justify-end items-center">
  34. <div class="w-[150px] h-[50px] text-[16px] bg-[var(--el-color-primary)] rounded-[var(--rounded-xl)] text-white text-center leading-[50px] cursor-pointer" @click="payFn">去支付</div>
  35. </div>
  36. </div>
  37. </div>
  38. <el-dialog v-model="dialogPay" :title="type == 'wechatpay' ? '微信支付' : '支付宝支付'" width="400px" center :show-close="false" custom-class="pay !rounded-[var(--rounded-big)]">
  39. <div v-if=" type == 'wechatpay' || type == 'alipay'">
  40. <div class="flex justify-center items-center" >
  41. <img class="w-[200px] h-[200px]" :src="alipayCode" v-if="type == 'alipay'">
  42. <img class="w-[200px] h-[200px]" :src="wechatpayCode" alt="" v-if="type == 'wechatpay'">
  43. </div>
  44. <div class="mt-[30px] text-center text-[16px]" v-if="type == 'alipay' ">请使用支付宝扫描二维码支付</div>
  45. <div class="mt-[30px] text-center text-[16px]" v-if="type == 'wechatpay' ">请使用微信扫描二维码支付</div>
  46. </div>
  47. <template #footer>
  48. <div class="dialog-footer">
  49. <el-button type="primary" @click="cancelPayFn">放弃支付</el-button>
  50. </div>
  51. </template>
  52. </el-dialog>
  53. </div>
  54. </template>
  55. <script setup lang="ts">
  56. import { ref, reactive,computed,watch } from 'vue'
  57. import { useRoute,useRouter } from 'vue-router'
  58. import { debounce,isUrl } from '@/utils/common'
  59. import QRCode from 'qrcode'
  60. import { getPayInfo,pay } from '@/app/api/pay'
  61. const route = useRoute()
  62. const router = useRouter()
  63. const tradeId = route.query.trade_id
  64. const tradeType = route.query.trade_type
  65. const loading = ref(false)
  66. let payIntervalId;
  67. let payInfo = ref(null)
  68. const type = ref('')
  69. const getPayInfoFn = ()=>{
  70. loading.value = true
  71. getPayInfo(tradeType, tradeId).then(res =>{
  72. payInfo.value = res.data
  73. loading.value = false
  74. // 支付类型
  75. type.value = res.data.pay_type_list[0] ? res.data.pay_type_list[0].key : ''
  76. //检测支付状态,当status为二时,表示支付完成,需跳转订单列表
  77. if (payInfo.value.status == 2) {
  78. clearInterval(payIntervalId);
  79. router.replace(`/pay/pay_succeed?trade_id=${tradeId}&trade_type=${tradeType}`)
  80. }
  81. // if (['alipay', 'wechatpay'].includes(type.value)) {
  82. // payFn()
  83. // }
  84. }).catch((res) => {
  85. loading.value = false;
  86. })
  87. }
  88. getPayInfoFn()
  89. // 监听路由变化关闭定时器
  90. watch(
  91. () => router.currentRoute.value.path,
  92. (toPath) => {
  93. if (toPath != '/pay/pay') {
  94. clearInterval(payIntervalId)
  95. }
  96. }, { immediate: true, deep: true }
  97. )
  98. // 确定支付
  99. let wechatpayCode = ref('') //微信支付码
  100. let alipayCode = ref('') //微信支付码
  101. let dialogPay = ref(false) //弹框数据
  102. let qrcodeData = ref({})
  103. const payFn = () => {
  104. if (loading.value) return
  105. loading.value = true
  106. pay({
  107. trade_type: payInfo.value?.trade_type,
  108. trade_id: payInfo.value?.trade_id,
  109. type: type.value
  110. }).then(res => {
  111. if(type.value == 'balancepay'){
  112. router.replace(`/pay/pay_succeed?trade_id=${tradeId}&trade_type=${tradeType}`);
  113. return;
  114. }else if (type.value == 'wechatpay') {
  115. QRCode.toDataURL(res.data.code_url, { errorCorrectionLevel: 'L', margin: 0, width: 100 }).then(url => {
  116. wechatpayCode.value = url
  117. });
  118. clearInterval(payIntervalId);
  119. qrcodeData.value.title ='微信支付'
  120. qrcodeData.value.desc = '请使用微信扫描二维码支付'
  121. dialogPay.value = true
  122. payIntervalId = setInterval(() => {
  123. getPayInfoCirculationFn(route.query.trade_id, route.query.trade_type);
  124. }, 2000)
  125. }else if (type.value == 'alipay') {
  126. QRCode.toDataURL(res.data.qr_code, { errorCorrectionLevel: 'L', margin: 0, width: 100 }).then(url => {
  127. alipayCode.value = url
  128. });
  129. clearInterval(payIntervalId);
  130. qrcodeData.value.title ='支付宝支付'
  131. qrcodeData.value.desc = '请使用支付宝扫描二维码支付'
  132. dialogPay.value = true
  133. payIntervalId = setInterval(() => {
  134. getPayInfoCirculationFn(route.query.trade_id, route.query.trade_type);
  135. }, 2000)
  136. }else if(res.data.url){
  137. isUrl(res.data.url) ? window.location.href = res.data.url : router.replace(res.data.url);
  138. }
  139. loading.value = false;
  140. }).catch((res) => {
  141. loading.value = false;
  142. })
  143. }
  144. //选择支付
  145. const payTypeFn =debounce((payType) => {
  146. type.value = payType
  147. })
  148. // 用于不断请求支付结果
  149. const getPayInfoCirculationFn = (trade_id, trade_type) => {
  150. getPayInfo(trade_type, trade_id).then((res) => {
  151. //检测支付状态,当status为二时,表示支付完成,需跳转订单列表
  152. if (res.data.status == 2) {
  153. clearInterval(payIntervalId);
  154. router.replace(`/pay/pay_succeed?trade_id=${tradeId}&trade_type=${tradeType}`);
  155. }
  156. })
  157. }
  158. // 放弃支付
  159. const cancelPayFn = () =>{
  160. clearInterval(payIntervalId);
  161. dialogPay.value = false
  162. }
  163. </script>
  164. <style lang="scss" scoped>
  165. .count :deep(.el-statistic__number){
  166. color:#e93323;
  167. font-size: 14px;
  168. font-weight: normal;
  169. }
  170. :deep(.pay .el-dialog__header){
  171. padding: 30px 0 36px!important;
  172. margin-right: 0!important;
  173. }
  174. :deep(.pay .el-dialog__title){
  175. color: #333!important;
  176. font-size: 20px!important;
  177. }
  178. :deep(.pay .el-dialog__body){
  179. padding: 0 25px 30px!important;
  180. }
  181. </style>