|
|
@@ -323,117 +323,41 @@ async function handleWechatJsapiPay() {
|
|
|
});
|
|
|
}
|
|
|
|
|
|
- orderInfo.value.orderNo = result.orderNo;
|
|
|
+ // 注意:post 函数返回的是 response.data,即 { code, message, data: {...} }
|
|
|
+ const responseData = result.data || result; // 兼容直接返回 data 的情况
|
|
|
+ orderInfo.value.orderNo = responseData.orderNo;
|
|
|
uni.hideLoading();
|
|
|
|
|
|
- // 使用 wx.chooseWXPay 调起支付(微信官方推荐方式)
|
|
|
- const currentResult = result; // 保存引用,避免闭包问题
|
|
|
+ // 使用 WeixinJSBridge.invoke 调起支付(微信官方推荐方式)
|
|
|
+ const currentResult = responseData; // 保存引用,避免闭包问题
|
|
|
|
|
|
- // 检查wx对象是否存在
|
|
|
- if (typeof (window as any).wx === 'undefined') {
|
|
|
- console.error('[WeChat Pay] wx对象不存在,可能未引入微信JS-SDK');
|
|
|
- uni.showToast({ title: '支付环境异常,请刷新页面重试', icon: 'none' });
|
|
|
- paying.value = false;
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // 1. 先获取JS-SDK签名并配置wx.config
|
|
|
- const currentUrl = window.location.href.split('#')[0]; // 去掉hash部分
|
|
|
- console.log('[WeChat Pay] 获取JS-SDK签名,url:', currentUrl);
|
|
|
-
|
|
|
- try {
|
|
|
- const signResult = await get<any>('/payment/wechat/jssdk-sign', { url: currentUrl });
|
|
|
-
|
|
|
- if (!signResult || !signResult.appId) {
|
|
|
- throw new Error('获取JS-SDK签名失败');
|
|
|
- }
|
|
|
+ console.log('[WeChat Pay] 准备调起 WeixinJSBridge, payParams:', JSON.stringify(currentResult.payParams));
|
|
|
|
|
|
- console.log('[WeChat Pay] JS-SDK签名获取成功,准备配置wx.config');
|
|
|
+ // 检查 WeixinJSBridge 是否存在
|
|
|
+ if (typeof (window as any).WeixinJSBridge === 'undefined') {
|
|
|
+ console.error('[WeChat Pay] WeixinJSBridge 不存在,等待注入...');
|
|
|
|
|
|
- // 配置wx.config
|
|
|
- (window as any).wx.config({
|
|
|
- debug: false, // 调试时可以改为true
|
|
|
- appId: signResult.appId,
|
|
|
- timestamp: signResult.timestamp,
|
|
|
- nonceStr: signResult.nonceStr,
|
|
|
- signature: signResult.signature,
|
|
|
- jsApiList: ['chooseWXPay'] // 需要使用的JS接口列表
|
|
|
- });
|
|
|
-
|
|
|
- // 等待wx.ready
|
|
|
- await new Promise<void>((resolve, reject) => {
|
|
|
- (window as any).wx.ready(() => {
|
|
|
- console.log('[WeChat Pay] wx.ready 成功');
|
|
|
- resolve();
|
|
|
+ // 如果 WeixinJSBridge 还未注入,监听注入事件
|
|
|
+ if (document.addEventListener) {
|
|
|
+ document.addEventListener('WeixinJSBridgeReady', () => {
|
|
|
+ console.log('[WeChat Pay] WeixinJSBridge 已注入,开始调起支付');
|
|
|
+ invokeWeixinJSBridge(currentResult);
|
|
|
+ }, false);
|
|
|
+ } else if ((document as any).attachEvent) {
|
|
|
+ (document as any).attachEvent('WeixinJSBridgeReady', () => {
|
|
|
+ console.log('[WeChat Pay] WeixinJSBridge 已注入,开始调起支付');
|
|
|
+ invokeWeixinJSBridge(currentResult);
|
|
|
});
|
|
|
-
|
|
|
- (window as any).wx.error((err: any) => {
|
|
|
- console.error('[WeChat Pay] wx.error:', err);
|
|
|
- reject(new Error('wx.config失败: ' + JSON.stringify(err)));
|
|
|
+ (document as any).attachEvent('onWeixinJSBridgeReady', () => {
|
|
|
+ console.log('[WeChat Pay] WeixinJSBridge 已注入,开始调起支付');
|
|
|
+ invokeWeixinJSBridge(currentResult);
|
|
|
});
|
|
|
- });
|
|
|
-
|
|
|
- console.log('[WeChat Pay] 开始调起wx.chooseWXPay');
|
|
|
-
|
|
|
- // 2. 使用 wx.chooseWXPay 调起支付
|
|
|
- (window as any).wx.chooseWXPay({
|
|
|
- timestamp: currentResult.payParams.timeStamp,
|
|
|
- nonceStr: currentResult.payParams.nonceStr,
|
|
|
- package: currentResult.payParams.package,
|
|
|
- signType: currentResult.payParams.signType || "RSA",
|
|
|
- paySign: currentResult.payParams.paySign,
|
|
|
- success: async (res: any) => {
|
|
|
- console.log('[WeChat Pay] wx.chooseWXPay 成功:', JSON.stringify(res));
|
|
|
- // 官方要求:必须调用查询订单API确认最终状态
|
|
|
- const orderStatus = await checkWechatOrderStatus(currentResult.orderNo);
|
|
|
- paying.value = false;
|
|
|
-
|
|
|
- if (orderStatus === 'SUCCESS') {
|
|
|
- uni.showModal({
|
|
|
- title: '支付成功',
|
|
|
- content: productType.value === 'token-pack' ? '积分包购买成功!' : '恭喜您订阅成功!',
|
|
|
- showCancel: false,
|
|
|
- success: () => uni.switchTab({ url: '/pages/mine/index' })
|
|
|
- });
|
|
|
- } else {
|
|
|
- uni.showToast({ title: '订单确认中,请稍后查看', icon: 'none' });
|
|
|
- }
|
|
|
- },
|
|
|
- fail: async (err: any) => {
|
|
|
- console.error('[WeChat Pay] wx.chooseWXPay 失败:', JSON.stringify(err));
|
|
|
- // 官方要求:必须调用查询订单API确认最终状态
|
|
|
- const orderStatus = await checkWechatOrderStatus(currentResult.orderNo);
|
|
|
- paying.value = false;
|
|
|
-
|
|
|
- if (orderStatus === 'SUCCESS') {
|
|
|
- // 桥回调失败但订单已支付(延迟回调)
|
|
|
- uni.showModal({
|
|
|
- title: '支付成功',
|
|
|
- content: productType.value === 'token-pack' ? '积分包购买成功!' : '恭喜您订阅成功!',
|
|
|
- showCancel: false,
|
|
|
- success: () => uni.switchTab({ url: '/pages/mine/index' })
|
|
|
- });
|
|
|
- } else {
|
|
|
- uni.showModal({
|
|
|
- title: '支付失败',
|
|
|
- content: `微信支付调起失败 (${err.errMsg || err.err_msg || '未知错误'}),是否使用扫码支付?`,
|
|
|
- confirmText: '扫码支付',
|
|
|
- cancelText: '取消',
|
|
|
- success: (modalRes: any) => {
|
|
|
- if (modalRes.confirm && currentResult.orderNo) {
|
|
|
- inWechat.value = false;
|
|
|
- handlePay();
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
- } catch (configError: any) {
|
|
|
- console.error('[WeChat Pay] wx.config 失败:', configError);
|
|
|
- uni.showToast({ title: '支付配置失败: ' + (configError.message || '未知错误'), icon: 'none' });
|
|
|
- paying.value = false;
|
|
|
+ }
|
|
|
+ return;
|
|
|
}
|
|
|
+
|
|
|
+ // WeixinJSBridge 已存在,直接调起
|
|
|
+ invokeWeixinJSBridge(currentResult);
|
|
|
} catch (error: any) {
|
|
|
paying.value = false;
|
|
|
uni.hideLoading();
|
|
|
@@ -448,6 +372,87 @@ async function handleWechatJsapiPay() {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+// 调用 WeixinJSBridge.invoke
|
|
|
+function invokeWeixinJSBridge(payResult: any) {
|
|
|
+ const payParams = payResult.payParams;
|
|
|
+
|
|
|
+ if (!payParams || !payParams.package) {
|
|
|
+ console.error('[WeChat Pay] payParams 异常:', payParams);
|
|
|
+ uni.showToast({ title: '支付参数异常', icon: 'none' });
|
|
|
+ paying.value = false;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log('[WeChat Pay] 调用 WeixinJSBridge.invoke, params:', JSON.stringify(payParams));
|
|
|
+
|
|
|
+ (window as any).WeixinJSBridge.invoke(
|
|
|
+ 'getBrandWCPayRequest',
|
|
|
+ {
|
|
|
+ appId: payParams.appId,
|
|
|
+ timeStamp: payParams.timeStamp,
|
|
|
+ nonceStr: payParams.nonceStr,
|
|
|
+ package: payParams.package,
|
|
|
+ signType: payParams.signType || 'RSA',
|
|
|
+ paySign: payParams.paySign,
|
|
|
+ },
|
|
|
+ async (res: any) => {
|
|
|
+ console.log('[WeChat Pay] WeixinJSBridge 回调:', JSON.stringify(res));
|
|
|
+ paying.value = false;
|
|
|
+
|
|
|
+ if (res.err_msg === 'get_brand_wcpay_request:ok') {
|
|
|
+ // 支付成功(前端返回,需调用查询API确认)
|
|
|
+ console.log('[WeChat Pay] 前端返回支付成功,查询订单状态...');
|
|
|
+ const orderStatus = await checkWechatOrderStatus(payResult.orderNo);
|
|
|
+
|
|
|
+ if (orderStatus === 'SUCCESS') {
|
|
|
+ uni.showModal({
|
|
|
+ title: '支付成功',
|
|
|
+ content: productType.value === 'token-pack' ? '积分包购买成功!' : '恭喜您订阅成功!',
|
|
|
+ showCancel: false,
|
|
|
+ success: () => uni.switchTab({ url: '/pages/mine/index' })
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ // 前端返回成功但订单未成功(延迟回调)
|
|
|
+ uni.showToast({ title: '订单确认中,请稍后查看', icon: 'none' });
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 支付失败或取消
|
|
|
+ console.log('[WeChat Pay] 支付失败或取消:', res.err_msg);
|
|
|
+
|
|
|
+ // 官方要求:必须调用查询订单API确认最终状态
|
|
|
+ const orderStatus = await checkWechatOrderStatus(payResult.orderNo);
|
|
|
+
|
|
|
+ if (orderStatus === 'SUCCESS') {
|
|
|
+ // 桥回调失败但订单已支付(延迟回调)
|
|
|
+ uni.showModal({
|
|
|
+ title: '支付成功',
|
|
|
+ content: productType.value === 'token-pack' ? '积分包购买成功!' : '恭喜您订阅成功!',
|
|
|
+ showCancel: false,
|
|
|
+ success: () => uni.switchTab({ url: '/pages/mine/index' })
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ // 用户取消或真正失败
|
|
|
+ const isCancel = res.err_msg === 'get_brand_wcpay_request:cancel';
|
|
|
+ uni.showModal({
|
|
|
+ title: isCancel ? '支付取消' : '支付失败',
|
|
|
+ content: isCancel ? '您已取消支付' : `支付失败 (${res.err_msg || '未知错误'})`,
|
|
|
+ showCancel: !isCancel,
|
|
|
+ confirmText: '重新支付',
|
|
|
+ cancelText: '取消',
|
|
|
+ success: (modalRes: any) => {
|
|
|
+ if (modalRes.confirm) {
|
|
|
+ // 重新调起支付
|
|
|
+ paying.value = false;
|
|
|
+ handleWechatJsapiPay();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+}
|
|
|
+
|
|
|
async function handlePay() {
|
|
|
// 防重处理:2秒内禁止重复点击(官方要求按钮防抖)
|
|
|
const now = Date.now();
|