fadd
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
import un from '@uni-helper/uni-network'
|
import un from '@uni-helper/uni-network'
|
||||||
import { QNC_API } from '@/config/api'
|
import { QNC_API } from '@/config/api'
|
||||||
|
import { safeHideLoading } from '@/utils/loading'
|
||||||
|
|
||||||
/** 未单独配置登录页时,401 回到登录页 */
|
/** 未单独配置登录页时,401 回到登录页 */
|
||||||
const AUTH_FALLBACK_PAGE = '/pages/login'
|
const AUTH_FALLBACK_PAGE = '/pages/login'
|
||||||
@@ -18,12 +19,7 @@ function showRequestLoading() {
|
|||||||
function hideRequestLoading() {
|
function hideRequestLoading() {
|
||||||
if (--loadingCount <= 0) {
|
if (--loadingCount <= 0) {
|
||||||
loadingCount = 0
|
loadingCount = 0
|
||||||
try {
|
safeHideLoading()
|
||||||
uni.hideLoading()
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
// 微信小程序真机调试时,如果没有 loading 显示会报错 "toast can't be found",忽略即可
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,3 +11,11 @@ export async function postPayCheck(body, requestConfig) {
|
|||||||
const res = await http.post('/pay/check', body, requestConfig)
|
const res = await http.post('/pay/check', body, requestConfig)
|
||||||
return res.data
|
return res.data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上报虚拟支付客户端步骤/微信·Apple 提示语(写入后端日志,并触发 query_order 快照)
|
||||||
|
*/
|
||||||
|
export async function postXpayClientEvent(body, requestConfig) {
|
||||||
|
const res = await http.post('/pay/xpay/client-event', body, requestConfig)
|
||||||
|
return res.data
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
|
import { safeHideLoading } from '@/utils/loading'
|
||||||
import { fetchReportShareUrl } from '@/utils/reportH5Link'
|
import { fetchReportShareUrl } from '@/utils/reportH5Link'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -23,7 +24,7 @@ async function copyLink() {
|
|||||||
orderId: props.orderId,
|
orderId: props.orderId,
|
||||||
orderNo: props.orderNo,
|
orderNo: props.orderNo,
|
||||||
})
|
})
|
||||||
uni.hideLoading()
|
safeHideLoading()
|
||||||
await new Promise((resolve, reject) => {
|
await new Promise((resolve, reject) => {
|
||||||
uni.setClipboardData({
|
uni.setClipboardData({
|
||||||
data: url,
|
data: url,
|
||||||
@@ -34,7 +35,7 @@ async function copyLink() {
|
|||||||
uni.showToast({ title: '链接已复制,可在浏览器打开', icon: 'none', duration: 2500 })
|
uni.showToast({ title: '链接已复制,可在浏览器打开', icon: 'none', duration: 2500 })
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
uni.hideLoading()
|
safeHideLoading()
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: e?.message || '复制失败',
|
title: e?.message || '复制失败',
|
||||||
icon: 'none',
|
icon: 'none',
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
import { onLoad, onReady } from '@dcloudio/uni-app'
|
import { onLoad, onReady } from '@dcloudio/uni-app'
|
||||||
import { computed, onUnmounted, ref } from 'vue'
|
import { computed, onUnmounted, ref } from 'vue'
|
||||||
import { getProductByEn, getUserDetail, postAuthSendSmsQuery, postPayCheck, postPayPayment, postQueryService, postUploadImage } from '@/api'
|
import { getProductByEn, getUserDetail, postAuthSendSmsQuery, postPayCheck, postPayPayment, postQueryService, postUploadImage } from '@/api'
|
||||||
import { invokeWxVirtualPayment, prepareNativePayUI } from '@/utils/xpayPay'
|
import { formatXpayPayError, invokeWxVirtualPayment, logXpayPayFailure, prepareNativePayUI, reportXpayClientEvent } from '@/utils/xpayPay'
|
||||||
import { productHasSmsCode, useInquireForm } from '@/composables/useInquireForm'
|
import { productHasSmsCode, useInquireForm } from '@/composables/useInquireForm'
|
||||||
import { useBindMobile } from '@/composables/useBindMobile'
|
import { useBindMobile } from '@/composables/useBindMobile'
|
||||||
import { aesEncrypt, QUERY_PAYLOAD_AES_HEX_KEY } from '@/utils/crypto.js'
|
import { aesEncrypt, QUERY_PAYLOAD_AES_HEX_KEY } from '@/utils/crypto.js'
|
||||||
@@ -488,6 +488,12 @@ async function onConfirmPay() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (payRes?.code !== 200 || !payRes.data) {
|
if (payRes?.code !== 200 || !payRes.data) {
|
||||||
|
logXpayPayFailure('prepay', {
|
||||||
|
errMsg: payRes?.msg || '预下单失败',
|
||||||
|
errCode: payRes?.code,
|
||||||
|
}, { payBody, response: payRes })
|
||||||
|
if (payRes?.msg)
|
||||||
|
uni.showToast({ title: payRes.msg, icon: 'none', duration: 3000 })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -532,21 +538,61 @@ async function onConfirmPay() {
|
|||||||
prepareNativePayUI()
|
prepareNativePayUI()
|
||||||
await new Promise(r => setTimeout(r, 120))
|
await new Promise(r => setTimeout(r, 120))
|
||||||
|
|
||||||
await invokeWxVirtualPayment(prepay)
|
await reportXpayClientEvent({
|
||||||
|
orderNo,
|
||||||
|
stage: 'prepay_ok',
|
||||||
|
eventType: 'info',
|
||||||
|
message: '后端预下单成功,已拿到 xpay 签名参数',
|
||||||
|
extra: { order_no: orderNo },
|
||||||
|
})
|
||||||
|
|
||||||
|
await invokeWxVirtualPayment(prepay, { orderNo })
|
||||||
|
|
||||||
for (let i = 0; i < 8; i++) {
|
for (let i = 0; i < 8; i++) {
|
||||||
const checkRes = await postPayCheck({ order_no: orderNo }, { skipLoading: true })
|
const checkRes = await postPayCheck({ order_no: orderNo }, { skipLoading: true })
|
||||||
const status = checkRes?.data?.status
|
const status = checkRes?.data?.status
|
||||||
|
const wxSyncError = checkRes?.data?.wx_sync_error
|
||||||
|
const wxOrderStatus = checkRes?.data?.wx_order_status
|
||||||
|
const wxOrderDetail = checkRes?.data?.wx_order_detail
|
||||||
|
console.info('[xpay:check]', {
|
||||||
|
orderNo,
|
||||||
|
round: i + 1,
|
||||||
|
status,
|
||||||
|
code: checkRes?.code,
|
||||||
|
wxSyncError,
|
||||||
|
wxOrderStatus,
|
||||||
|
wxOrderDetail,
|
||||||
|
})
|
||||||
|
if (wxSyncError) {
|
||||||
|
console.warn('[xpay:check] 后端 query_order 微信返回', wxSyncError)
|
||||||
|
await reportXpayClientEvent({
|
||||||
|
orderNo,
|
||||||
|
stage: 'check',
|
||||||
|
eventType: 'tip',
|
||||||
|
message: wxSyncError,
|
||||||
|
extra: { wx_order_status: wxOrderStatus, wx_order_detail: wxOrderDetail, round: i + 1 },
|
||||||
|
})
|
||||||
|
}
|
||||||
if (status === 'paid') {
|
if (status === 'paid') {
|
||||||
afterPaySuccess()
|
afterPaySuccess()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (status === 'closed' || status === 'failed') {
|
if (status === 'closed' || status === 'failed') {
|
||||||
|
logXpayPayFailure('check', {
|
||||||
|
errMsg: `轮询到账失败 status=${status}`,
|
||||||
|
errCode: checkRes?.code,
|
||||||
|
}, { orderNo, checkRes, round: i + 1 })
|
||||||
uni.showToast({ title: '订单已关闭', icon: 'none' })
|
uni.showToast({ title: '订单已关闭', icon: 'none' })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if (checkRes?.code !== 200 && checkRes?.msg) {
|
||||||
|
console.warn('[xpay:check] 业务异常', { orderNo, checkRes })
|
||||||
|
}
|
||||||
await new Promise(r => setTimeout(r, 1500))
|
await new Promise(r => setTimeout(r, 1500))
|
||||||
}
|
}
|
||||||
|
logXpayPayFailure('check_timeout', {
|
||||||
|
errMsg: '支付后轮询 8 次仍未到账,请稍后在报告中查看或联系客服',
|
||||||
|
}, { orderNo })
|
||||||
uni.showToast({ title: '确认中,请稍后在报告中查看', icon: 'none' })
|
uni.showToast({ title: '确认中,请稍后在报告中查看', icon: 'none' })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -575,9 +621,16 @@ async function onConfirmPay() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
const msg = e?.errMsg || e?.message || ''
|
const formatted = e?.formatted || formatXpayPayError(e, { stage: 'pay' })
|
||||||
if (msg && !/cancel/i.test(msg))
|
if (!formatted.isCancel) {
|
||||||
uni.showToast({ title: String(msg).replace('requestVirtualPayment:fail ', ''), icon: 'none' })
|
if (!e?.formatted)
|
||||||
|
logXpayPayFailure('pay', e, { stage: 'pay' })
|
||||||
|
uni.showToast({
|
||||||
|
title: formatted.display.slice(0, 80),
|
||||||
|
icon: 'none',
|
||||||
|
duration: 4000,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
paying.value = false
|
paying.value = false
|
||||||
|
|||||||
10
src/utils/loading.js
Normal file
10
src/utils/loading.js
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
/**
|
||||||
|
* 安全关闭 loading。
|
||||||
|
* 微信小程序在无 loading 时调用 hideLoading 会以 Promise reject 报
|
||||||
|
* hideLoading:fail toast can't be found,须用 fail 回调吞掉。
|
||||||
|
*/
|
||||||
|
export function safeHideLoading() {
|
||||||
|
uni.hideLoading({
|
||||||
|
fail() {},
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1,23 +1,266 @@
|
|||||||
|
import { safeHideLoading } from '@/utils/loading'
|
||||||
|
import { postXpayClientEvent } from '@/api/pay'
|
||||||
|
|
||||||
|
const reportConfig = { skipLoading: true, skipBizToast: true }
|
||||||
|
|
||||||
|
/** 微信 requestVirtualPayment 常见 errCode → 排查提示(含 iOS) */
|
||||||
|
const XPAY_ERR_HINTS = {
|
||||||
|
'-1': '支付失败,请稍后重试',
|
||||||
|
'-2': '用户取消支付',
|
||||||
|
'-4': '风控拦截,请联系客服或更换账号/设备重试',
|
||||||
|
'-15001': '参数错误,详见 errMsg(如道具未发布、金额不符、iOS 未开通等)',
|
||||||
|
'-15002': '商户单号重复,请重新发起查询再支付',
|
||||||
|
'-15003': '微信系统错误,多为 signData/env/道具配置不匹配',
|
||||||
|
'-15005': '用户态签名 signature 错误,请重新登录小程序后再试',
|
||||||
|
'-15006': '支付签名 paySig 错误,检查后端 Env 与 AppKey 是否配套',
|
||||||
|
'-15007': 'session_key 过期,请关闭小程序重新进入',
|
||||||
|
'-15010': '道具 productId 未在现网发布或未生效',
|
||||||
|
'-15011': 'env 必须为 0(现网);iOS 不支持沙箱 env=1',
|
||||||
|
'-15013': '道具价格 goodsPrice 与后台配置不一致',
|
||||||
|
'-15014': '道具/代币刚发布,约 10 分钟后生效',
|
||||||
|
'-15016': 'signData 格式错误',
|
||||||
|
'-15017': '商户涉嫌违规,收款受限(查微信商户平台)',
|
||||||
|
'-15019': '商户受限,查微信商户平台/商家助手',
|
||||||
|
'-15020': '操作过快,请稍后再试',
|
||||||
|
'701001': '当前设备/微信版本不支持 iOS 虚拟支付(需 iOS15+、微信 8.0.68+)',
|
||||||
|
'701002': '需先完成微信支付实名认证',
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 将 wx fail 对象完整序列化(含 errno/errCode 等不可枚举字段) */
|
||||||
|
function serializeWxPayErr(err) {
|
||||||
|
if (!err || typeof err !== 'object')
|
||||||
|
return err
|
||||||
|
const o = {}
|
||||||
|
for (const k of Object.keys(err))
|
||||||
|
o[k] = err[k]
|
||||||
|
if (err.errMsg != null)
|
||||||
|
o.errMsg = err.errMsg
|
||||||
|
if (err.errCode != null)
|
||||||
|
o.errCode = err.errCode
|
||||||
|
if (err.errno != null)
|
||||||
|
o.errno = err.errno
|
||||||
|
try {
|
||||||
|
return JSON.stringify(o)
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
return String(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 读取设备与微信环境(便于区分 iOS / Android)
|
||||||
|
*/
|
||||||
|
export function getXpayDeviceContext() {
|
||||||
|
try {
|
||||||
|
const info = uni.getSystemInfoSync?.() || wx?.getSystemInfoSync?.() || {}
|
||||||
|
const account = wx?.getAccountInfoSync?.() || {}
|
||||||
|
return {
|
||||||
|
platform: info.platform || '',
|
||||||
|
system: info.system || '',
|
||||||
|
version: info.version || '',
|
||||||
|
SDKVersion: info.SDKVersion || '',
|
||||||
|
model: info.model || '',
|
||||||
|
envVersion: account.miniProgram?.envVersion || '',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseSignDataSummary(signData) {
|
||||||
|
if (!signData || typeof signData !== 'string')
|
||||||
|
return null
|
||||||
|
try {
|
||||||
|
const o = JSON.parse(signData)
|
||||||
|
return {
|
||||||
|
env: o.env,
|
||||||
|
offerId: o.offerId,
|
||||||
|
productId: o.productId,
|
||||||
|
goodsPrice: o.goodsPrice,
|
||||||
|
outTradeNo: o.outTradeNo,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
return { raw: signData.slice(0, 120) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化虚拟支付失败信息(控制台 + Toast 文案)
|
||||||
|
* @param {Record<string, unknown>} err wx fail 回调或 Error
|
||||||
|
* @param {{ stage?: string, orderNo?: string, prepay?: object }} [ctx]
|
||||||
|
*/
|
||||||
|
export function formatXpayPayError(err, ctx = {}) {
|
||||||
|
const errMsg = String(err?.errMsg || err?.message || err?.msg || '未知错误')
|
||||||
|
const errCode = err?.errCode ?? err?.errno ?? err?.code
|
||||||
|
const codeKey = errCode != null ? String(errCode) : ''
|
||||||
|
const tail = errMsg.replace(/^requestVirtualPayment:fail\s*/i, '').trim()
|
||||||
|
const hint = XPAY_ERR_HINTS[codeKey] || ''
|
||||||
|
const device = getXpayDeviceContext()
|
||||||
|
const isIOS = device.platform === 'ios' || /ios/i.test(device.system || '')
|
||||||
|
const signSummary = ctx.prepay?.signData
|
||||||
|
? parseSignDataSummary(ctx.prepay.signData)
|
||||||
|
: null
|
||||||
|
|
||||||
|
let iosNote = ''
|
||||||
|
if (isIOS) {
|
||||||
|
if (signSummary?.env === 1)
|
||||||
|
iosNote = '【iOS】signData.env=1 沙箱,iOS 必须用 env=0 + 现网 AppKey'
|
||||||
|
else if (/App Store|暂无法完成充值|Apple/i.test(errMsg))
|
||||||
|
iosNote = '【iOS/Apple】此为 Apple IAP 侧报错,非后端接口;常见原因:Apple 服务波动、账号地区/支付方式、沙箱 env、MP 未开 iOS 支付'
|
||||||
|
else if (/尚未开启|701001|not support/i.test(errMsg))
|
||||||
|
iosNote = '【iOS】请在 MP 后台「虚拟支付」开通 Apple/IAP 支付,并配置小程序简称'
|
||||||
|
else if (signSummary?.goodsPrice != null && signSummary.goodsPrice < 100)
|
||||||
|
iosNote = '【iOS】最低支付金额 1 元(100 分),当前 goodsPrice 可能过低'
|
||||||
|
}
|
||||||
|
|
||||||
|
const parts = [tail || errMsg]
|
||||||
|
if (codeKey)
|
||||||
|
parts.push(`[${codeKey}]`)
|
||||||
|
if (hint)
|
||||||
|
parts.push(hint)
|
||||||
|
if (iosNote)
|
||||||
|
parts.push(iosNote)
|
||||||
|
|
||||||
|
return {
|
||||||
|
display: parts.join(' '),
|
||||||
|
errMsg,
|
||||||
|
errCode: codeKey,
|
||||||
|
hint,
|
||||||
|
iosNote,
|
||||||
|
isIOS,
|
||||||
|
isCancel: /cancel/i.test(errMsg),
|
||||||
|
device,
|
||||||
|
signSummary,
|
||||||
|
stage: ctx.stage || '',
|
||||||
|
orderNo: ctx.orderNo || '',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打印完整 xpay 失败日志(开发者工具 Console / 真机调试 vConsole)
|
||||||
|
*/
|
||||||
|
export function logXpayPayFailure(stage, err, extra = {}) {
|
||||||
|
const formatted = formatXpayPayError(err, extra)
|
||||||
|
const tag = `[xpay:${stage}]`
|
||||||
|
console.error(tag, {
|
||||||
|
...formatted,
|
||||||
|
wxErrSerialized: serializeWxPayErr(err?.raw || err),
|
||||||
|
raw: err,
|
||||||
|
...extra,
|
||||||
|
})
|
||||||
|
return formatted
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 从 wx fail 对象提取用户可见提示(含 App Store 话术,非 HTTP 异常) */
|
||||||
|
function extractWxClientMessage(err) {
|
||||||
|
const errMsg = String(err?.errMsg || err?.message || '')
|
||||||
|
return errMsg.replace(/^requestVirtualPayment:fail\s*/i, '').trim() || errMsg
|
||||||
|
}
|
||||||
|
|
||||||
|
function classifyWxClientEvent(err) {
|
||||||
|
const message = extractWxClientMessage(err)
|
||||||
|
if (/cancel/i.test(message))
|
||||||
|
return { event_type: 'info', message }
|
||||||
|
if (/App Store|暂无法完成充值|Apple/i.test(message))
|
||||||
|
return { event_type: 'tip', message }
|
||||||
|
return { event_type: 'fail', message }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上报虚拟支付步骤到后端(写入服务端 [xpay:client-event] 日志,fail/tip 时后端会 query_order)
|
||||||
|
*/
|
||||||
|
export async function reportXpayClientEvent(payload) {
|
||||||
|
try {
|
||||||
|
const body = {
|
||||||
|
order_no: payload.orderNo || '',
|
||||||
|
stage: payload.stage || 'unknown',
|
||||||
|
event_type: payload.eventType || 'info',
|
||||||
|
message: payload.message || '',
|
||||||
|
err_msg: payload.errMsg || '',
|
||||||
|
err_code: payload.errCode != null ? Number(payload.errCode) : undefined,
|
||||||
|
errno: payload.errno != null ? Number(payload.errno) : undefined,
|
||||||
|
sign_data: payload.signData ? JSON.stringify(payload.signData) : '',
|
||||||
|
device: payload.device ? JSON.stringify(payload.device) : JSON.stringify(getXpayDeviceContext()),
|
||||||
|
extra: payload.extra ? JSON.stringify(payload.extra) : '',
|
||||||
|
}
|
||||||
|
const res = await postXpayClientEvent(body, reportConfig)
|
||||||
|
const data = res?.data
|
||||||
|
console.info('[xpay:server-log]', { request: body, response: data })
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
console.warn('[xpay:server-log] 上报失败', e)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 调起微信小程序虚拟支付(xpay)
|
* 调起微信小程序虚拟支付(xpay)
|
||||||
* @param {{ mode: string, signData: string, paySig: string, signature: string }} prepay
|
* @param {{ mode: string, signData: string, paySig: string, signature: string, provider?: string }} prepay
|
||||||
|
* @param {{ orderNo?: string }} [options]
|
||||||
*/
|
*/
|
||||||
export function invokeWxVirtualPayment(prepay) {
|
export function invokeWxVirtualPayment(prepay, options = {}) {
|
||||||
|
const orderNo = options.orderNo || ''
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
// #ifdef MP-WEIXIN
|
// #ifdef MP-WEIXIN
|
||||||
if (typeof wx?.requestVirtualPayment !== 'function') {
|
if (typeof wx?.requestVirtualPayment !== 'function') {
|
||||||
reject(new Error('当前环境不支持虚拟支付,请使用微信真机预览'))
|
const e = { errMsg: '当前环境不支持虚拟支付,请使用微信真机预览', errCode: -1 }
|
||||||
|
logXpayPayFailure('unsupported', e, { orderNo, prepay: { provider: prepay?.provider } })
|
||||||
|
reject(e)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const device = getXpayDeviceContext()
|
||||||
|
const signSummary = parseSignDataSummary(prepay.signData)
|
||||||
|
console.info('[xpay:invoke]', { orderNo, mode: prepay.mode, device, signData: signSummary })
|
||||||
|
|
||||||
|
reportXpayClientEvent({
|
||||||
|
orderNo,
|
||||||
|
stage: 'invoke',
|
||||||
|
eventType: 'info',
|
||||||
|
message: '即将调起 wx.requestVirtualPayment',
|
||||||
|
signData: signSummary,
|
||||||
|
device,
|
||||||
|
})
|
||||||
|
|
||||||
wx.requestVirtualPayment({
|
wx.requestVirtualPayment({
|
||||||
mode: prepay.mode,
|
mode: prepay.mode,
|
||||||
signData: prepay.signData,
|
signData: prepay.signData,
|
||||||
paySig: prepay.paySig,
|
paySig: prepay.paySig,
|
||||||
signature: prepay.signature,
|
signature: prepay.signature,
|
||||||
success: resolve,
|
success(res) {
|
||||||
fail: reject,
|
console.info('[xpay:success]', { orderNo, res })
|
||||||
|
reportXpayClientEvent({
|
||||||
|
orderNo,
|
||||||
|
stage: 'success',
|
||||||
|
eventType: 'success',
|
||||||
|
message: 'wx.requestVirtualPayment success',
|
||||||
|
signData: signSummary,
|
||||||
|
device,
|
||||||
|
extra: res,
|
||||||
|
})
|
||||||
|
resolve(res)
|
||||||
|
},
|
||||||
|
fail(err) {
|
||||||
|
const formatted = logXpayPayFailure('requestVirtualPayment', err, { orderNo, prepay })
|
||||||
|
const classified = classifyWxClientEvent(err)
|
||||||
|
reportXpayClientEvent({
|
||||||
|
orderNo,
|
||||||
|
stage: 'fail',
|
||||||
|
eventType: classified.event_type,
|
||||||
|
message: classified.message,
|
||||||
|
errMsg: err?.errMsg,
|
||||||
|
errCode: err?.errCode,
|
||||||
|
errno: err?.errno,
|
||||||
|
signData: signSummary,
|
||||||
|
device,
|
||||||
|
extra: { formatted, raw: serializeWxPayErr(err) },
|
||||||
|
})
|
||||||
|
reject({ ...err, formatted })
|
||||||
|
},
|
||||||
})
|
})
|
||||||
console.log('invokeWxVirtualPayment', prepay)
|
|
||||||
// #endif
|
// #endif
|
||||||
// #ifndef MP-WEIXIN
|
// #ifndef MP-WEIXIN
|
||||||
reject(new Error('仅支持微信小程序虚拟支付'))
|
reject(new Error('仅支持微信小程序虚拟支付'))
|
||||||
@@ -27,10 +270,5 @@ export function invokeWxVirtualPayment(prepay) {
|
|||||||
|
|
||||||
/** 关闭可能遮挡原生支付弹窗的 loading / 自定义蒙层 */
|
/** 关闭可能遮挡原生支付弹窗的 loading / 自定义蒙层 */
|
||||||
export function prepareNativePayUI() {
|
export function prepareNativePayUI() {
|
||||||
try {
|
safeHideLoading()
|
||||||
uni.hideLoading()
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
/* ignore */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user