index.tsx 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. import request from '@/helpers/request'
  2. import { browser, getHttpOrigin, getUrlCode, moneyFormat } from '@/helpers/utils'
  3. import { goAliAuth, goWechatAuth } from '@/state'
  4. import { Cell, CellGroup, Dialog, Icon, Loading, Toast } from 'vant'
  5. import { defineComponent, onMounted, reactive } from 'vue'
  6. import { useRouter, useRoute } from 'vue-router'
  7. import styles from './index.module.less'
  8. import { state as baseState } from '@/state'
  9. export default defineComponent({
  10. name: 'pay-result',
  11. setup() {
  12. const router = useRouter()
  13. const route = useRoute()
  14. const state = reactive({
  15. errorText: '',
  16. browserStatus: false,
  17. code: null as any,
  18. pay_channel: route.query.pay_channel as any,
  19. wxAppId: route.query.wxAppId as any,
  20. paymentType: route.query.paymentType as any,
  21. alipayAppId: route.query.alipayAppId as any,
  22. body: route.query.body as any,
  23. price: route.query.price as any,
  24. orderNo: route.query.orderNo as any,
  25. userId: route.query.userId as any,
  26. payInfo: {} as any,
  27. isYeePay: false // 是否为易宝支付
  28. })
  29. const init = () => {
  30. const query = route.query
  31. const isYeePay = state.paymentType?.indexOf('yeepay') !== -1
  32. // 判断是否有支付对象
  33. if (!query.orderNo || !query.pay_channel) {
  34. Dialog.confirm({
  35. message: '支付订单信息错误请重新支付',
  36. showCancelButton: false
  37. }).then(() => {
  38. router.back()
  39. })
  40. } else {
  41. // 判断当前浏览器
  42. if (browser().weixin) {
  43. state.browserStatus = true
  44. getWxPay()
  45. } else if (browser().alipay) {
  46. if (isYeePay) {
  47. const code = getUrlCode('auth_code')
  48. if (code) {
  49. state.code = code // 赋值code码
  50. state.browserStatus = true
  51. getPayment()
  52. } else {
  53. goAliAuth(state.alipayAppId)
  54. }
  55. } else {
  56. state.browserStatus = true
  57. getPayment()
  58. }
  59. } else {
  60. state.errorText = '请在微信或支付宝客户端打开'
  61. document.title = 'ERROR'
  62. }
  63. }
  64. }
  65. const getPayment = async () => {
  66. try {
  67. if (parseFloat(state.price) <= 0) {
  68. Toast('支付金额异常')
  69. return
  70. }
  71. const payMap: any = {
  72. merOrderNo: state.orderNo,
  73. paymentChannel: state.pay_channel, // 支付渠道
  74. userId: state.userId,
  75. code: state.code
  76. }
  77. // // 判断是否是微信公众号支付
  78. // if (state.pay_channel == 'wx_pub') {
  79. // payMap.code = state.code;
  80. // }
  81. const { data } = await request.post(
  82. '/api-student/open/userOrder/executePayment/v2',
  83. {
  84. data: {
  85. ...payMap
  86. }
  87. }
  88. )
  89. state.isYeePay = data.paymentVender?.indexOf('yeepay') !== -1
  90. console.log(data, 'data')
  91. scanCodePay(data.reqParams)
  92. } catch (e) {
  93. //
  94. console.log(e)
  95. // 接口报错也跳转到支付回调页
  96. window.location.replace(
  97. getHttpOrigin() +
  98. baseState.payBackPath +
  99. '#/tradeDetail?orderNo=' +
  100. state.orderNo
  101. )
  102. }
  103. }
  104. // 由于js的载入是异步的,所以可以通过该方法,当AlipayJSBridgeReady事件发生后,再执行callback方法
  105. const ready = (callback: any) => {
  106. if ((window as any).AlipayJSBridge) {
  107. callback && callback()
  108. } else {
  109. document.addEventListener('AlipayJSBridgeReady', callback, false)
  110. }
  111. }
  112. const tradePay = (tradeNO: any) => {
  113. ready(function () {
  114. // 通过传入交易号唤起快捷调用方式(注意tradeNO大小写严格)
  115. ;(window as any).AlipayJSBridge.call(
  116. 'tradePay',
  117. {
  118. tradeNO: tradeNO
  119. },
  120. function (data: any) {
  121. if ('9000' == data.resultCode) {
  122. window.location.replace(
  123. getHttpOrigin() +
  124. baseState.payBackPath +
  125. '#/tradeDetail?orderNo=' +
  126. state.orderNo
  127. )
  128. } else {
  129. window.location.replace(
  130. getHttpOrigin() +
  131. baseState.payBackPath +
  132. '#/tradeDetail?orderNo=' +
  133. state.orderNo
  134. )
  135. }
  136. //使用的支付宝内置api实现关闭H5
  137. ;(window as any).AlipayJSBridge.call('closeWebview')
  138. }
  139. )
  140. })
  141. }
  142. const scanCodePay = (data: any) => {
  143. // 判断支付方式 如果是 test 模式 支付用测试url 否则用生产url
  144. if (state.pay_channel == 'alipay_qr') {
  145. if (state.isYeePay) {
  146. tradePay(data.tradeNO)
  147. } else {
  148. const url =
  149. data.prod_mode === 'false'
  150. ? data?.expend?.qrcode_url +
  151. '?payment_id=' +
  152. data.id +
  153. '&pay_channel=' +
  154. data.pay_channel
  155. : data?.expend?.qrcode_url
  156. window.location.href = url
  157. }
  158. } else if (state.pay_channel == 'alipay_wap') {
  159. window.location.href = data?.expend?.pay_info
  160. } else if (state.pay_channel == 'wx_pub') {
  161. console.log(state.isYeePay, data?.expend, 'payInfo')
  162. const tempPayInfo = state.isYeePay
  163. ? JSON.parse(data.prePayTn)
  164. : data?.expend
  165. ? JSON.parse(data?.expend?.pay_info)
  166. : data
  167. state.payInfo = tempPayInfo
  168. if (typeof (window as any).WeixinJSBridge == 'undefined') {
  169. if (document.addEventListener) {
  170. document.addEventListener(
  171. 'WeixinJSBridgeReady',
  172. onBridgeReady,
  173. false
  174. )
  175. } else if ((document as any).attachEvent) {
  176. ;(document as any)
  177. .attachEvent(
  178. 'WeixinJSBridgeReady',
  179. onBridgeReady
  180. )(document as any)
  181. .attachEvent('onWeixinJSBridgeReady', onBridgeReady)
  182. }
  183. } else {
  184. onBridgeReady()
  185. }
  186. }
  187. }
  188. const onBridgeReady = () => {
  189. const payInfo = state.payInfo
  190. // let orderNo = state.orderNo
  191. ;(window as any).WeixinJSBridge.invoke(
  192. 'getBrandWCPayRequest',
  193. {
  194. appId: payInfo.appId, //公众号名称,由商户传入
  195. timeStamp: payInfo.timeStamp, //时间戳,自1970年以来的秒数
  196. nonceStr: payInfo.nonceStr, //随机串
  197. package: payInfo.package || payInfo.packageValue,
  198. signType: payInfo.signType, //微信签名方式:
  199. paySign: payInfo.paySign //微信签名
  200. },
  201. (res: any) => {
  202. // if(res.err_msg == "get_brand_wcpay_request:ok" ){
  203. // 使用以上方式判断前端返回,微信团队郑重提示:
  204. //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
  205. // } else
  206. if (
  207. res.err_msg == 'get_brand_wcpay_request:cancel' ||
  208. res.err_msg == 'get_brand_wcpay_request:fail'
  209. ) {
  210. window.location.replace(
  211. getHttpOrigin() +
  212. baseState.payBackPath +
  213. '#/tradeDetail?orderNo=' +
  214. state.orderNo
  215. )
  216. } else {
  217. // 使用以上方式判断前端返回,微信团队郑重提示:
  218. //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
  219. // alert('支付成功')
  220. window.location.replace(
  221. getHttpOrigin() +
  222. baseState.payBackPath +
  223. '#/tradeDetail?orderNo=' +
  224. state.orderNo
  225. )
  226. }
  227. }
  228. )
  229. }
  230. const getWxPay = () => {
  231. // 微信公众号支付
  232. //授权
  233. const code = getUrlCode()
  234. if (!code) {
  235. goWechatAuth(state.wxAppId)
  236. } else {
  237. state.code = code
  238. getPayment()
  239. }
  240. }
  241. onMounted(() => {
  242. init()
  243. })
  244. return () => (
  245. <div class={styles.paywxresult}>
  246. {state.browserStatus && (
  247. <>
  248. <div class={styles.container}>
  249. <CellGroup border={false}>
  250. <Cell
  251. title={'订单金额'}
  252. value={'¥ ' + moneyFormat(state.price)}
  253. ></Cell>
  254. <Cell title={'订单信息'} value={state.body}></Cell>
  255. </CellGroup>
  256. </div>
  257. <div class={styles['order-loading']}>
  258. <p>{state.pay_channel == 'wx_pub' ? '微信支付' : '支付宝支付'}</p>
  259. <Loading type="spinner" color="#01C1B5" />
  260. </div>
  261. </>
  262. )}
  263. {!state.browserStatus && (
  264. <div class={styles['error-text']}>
  265. {state.errorText && (
  266. <Icon class={styles['error-icon']} name="warning-o" />
  267. )}
  268. {state.errorText}
  269. </div>
  270. )}
  271. </div>
  272. )
  273. }
  274. })