diff --git a/common/js/payUtils.js b/common/js/payUtils.js index ddc7789..9e858c1 100644 --- a/common/js/payUtils.js +++ b/common/js/payUtils.js @@ -190,7 +190,149 @@ export function checkPayStatus(outTradeNo) { } }); } +/** + * 华为支付调用封装(适配全端:微信小程序/H5/华为快应用) + * @param {String} outTradeNo 前端生成的唯一订单号 + * @param {Number} amount 支付金额(单位:元,保留2位小数) + * @param {String} subject 订单标题 + * @returns {Promise} 支付结果(含H5支付链接/原生支付状态) + */ +export function invokeHuaweiPay(outTradeNo, amount, subject) { + return new Promise(async (resolve, reject) => { + try { + // ===== 1. 模拟后端返回合法凭证(跳过真实接口调用)===== + // 注释掉真实请求后端的代码,直接模拟返回正确格式的凭证 + // const orderRes = await uni.request({ + // url: getApiUrl() + '/api/pay/huawei/createOrder', + // method: 'POST', + // data: { + // out_trade_no: outTradeNo, + // total_amount: amount, + // subject: subject, + // pay_type: 'huaweipay' + // } + // }); + // 模拟后端返回的合法数据(重点:code=0,有orderInfo和payUrl) + const orderRes = { + data: { + code: 0, + msg: '生成华为支付订单成功', + data: { + orderInfo: 'test_order_info_123456', // 模拟华为原生SDK需要的参数 + payUrl: 'https://pay.huawei.com/cashier/test' // 模拟H5支付链接 + } + } + }; + // ===================================================== + // ===== 2. 加日志:打印模拟的凭证,看是否拿到数据 ===== + console.log('【华为支付测试】模拟后端返回的凭证:', orderRes.data); + + // 3. 校验后端返回结果 + if (orderRes.data.code !== 0) { + reject(new Error(orderRes.data.msg || '生成华为支付订单失败')); + return; + } + + // 4. 区分运行端处理 + const accountInfo = uni.getAccountInfoSync(); + const systemInfo = uni.getSystemInfoSync(); + const isWechatMini = accountInfo?.miniProgram?.appId?.includes('wx'); // 微信小程序 + const isHuaweiQuickApp = systemInfo.platform === 'quickapp-huawei'; // 华为快应用 + + if (isHuaweiQuickApp) { + // ===== 3. 加日志:标记进入华为快应用逻辑 ===== + console.log('【华为支付测试】进入华为快应用逻辑,尝试调起原生SDK'); + + // 3.1 华为快应用:优先原生SDK调起,失败则降级H5 + if (orderRes.data.data.orderInfo) { // 后端返回华为支付SDK所需的orderInfo + try { + const huaweiPay = require('@service.pay.huawei'); // 华为快应用支付SDK + console.log('【华为支付测试】开始调用华为原生支付SDK'); + huaweiPay.pay({ + orderInfo: orderRes.data.data.orderInfo, // 后端返回的原生支付参数 + success: (res) => { + console.log('【华为支付测试】原生SDK调起成功', res); + resolve({ + code: 0, + msg: '华为支付原生控件唤起成功', + data: {} + }); + }, + fail: (err) => { + console.log('【华为支付测试】原生SDK调起失败,降级到H5', err); + // 原生唤起失败,降级返回H5链接 + if (orderRes.data.data.payUrl) { + resolve({ + code: 0, + msg: '原生支付失败,跳转H5支付', + data: { payUrl: orderRes.data.data.payUrl } + }); + } else { + reject(new Error(`华为支付失败:${err.message || '无H5支付链接'}`)); + } + } + }); + } catch (sdkErr) { + console.log('【华为支付测试】SDK加载失败,降级到H5', sdkErr); + // SDK加载失败,直接返回H5链接 + if (orderRes.data.data.payUrl) { + resolve({ + code: 0, + msg: 'SDK加载失败,跳转H5支付', + data: { payUrl: orderRes.data.data.payUrl } + }); + } else { + reject(new Error('华为支付SDK异常且无H5链接')); + } + } + } else if (orderRes.data.data.payUrl) { + console.log('【华为支付测试】无原生参数,直接返回H5链接'); + // 无原生参数,直接返回H5链接 + resolve({ + code: 0, + msg: '跳转华为支付H5页面', + data: { payUrl: orderRes.data.data.payUrl } + }); + } else { + reject(new Error('缺少华为支付参数(原生/H5)')); + } + } else if (isWechatMini) { + // ===== 4. 加日志:标记进入微信小程序逻辑 ===== + console.log('【华为支付测试】进入微信小程序逻辑,返回H5链接'); + + // 3.2 微信小程序:返回H5链接(适配web-view) + if (!orderRes.data.data.payUrl) { + reject(new Error('未获取到华为支付H5跳转链接')); + return; + } + resolve({ + code: 0, + msg: '跳转华为支付H5页面', + data: { payUrl: orderRes.data.data.payUrl } + }); + } else { + // ===== 5. 加日志:标记进入H5端逻辑 ===== + console.log('【华为支付测试】进入H5端逻辑,直接跳转'); + + // 3.3 H5端:直接跳转 + if (!orderRes.data.data.payUrl) { + reject(new Error('未获取到华为支付跳转链接')); + return; + } + window.location.href = orderRes.data.data.payUrl; + resolve({ + code: 0, + msg: '跳转华为支付页面成功', + data: {} + }); + } + } catch (err) { + console.error('【华为支付测试】整体异常:', err); + reject(new Error(`华为支付异常:${err.message || '网络请求失败'}`)); + } + }); +} /** * 获取API基础URL */ diff --git a/components/payment/payment.vue b/components/payment/payment.vue index fc2bd7d..e62cb67 100644 --- a/components/payment/payment.vue +++ b/components/payment/payment.vue @@ -56,7 +56,7 @@ import { } from 'common/js/wx-jssdk.js'; // #endif -// 引入统一支付工具类 +// 引入统一支付工具类(真实调用) import { invokeWechatPay, invokeAlipay, invokeHuaweiPay } from '../../common/js/payCore.js'; export default { @@ -76,32 +76,36 @@ export default { return { payIndex: 0, payTypeList: [ - // #ifdef H5 || MP-ALIPAY - { - name: '支付宝支付', - icon: 'icon-zhifubaozhifu-', - type: 'alipay' - }, - // #endif - // #ifdef H5 || MP-WEIXIN { name: '微信支付', icon: 'icon-weixin1', - type: 'wechatpay' + type: 'wechatpay', + description: '推荐微信用户使用' + }, + { + name: '支付宝支付', + icon: 'icon-zhifubaozhifu-', + type: 'alipay', + description: '推荐支付宝用户使用' }, - // #endif - // #ifdef H5 || QUICKAPP-HUAWEI { name: '华为支付', - icon: 'icon-zhekou', - type: 'huaweipay' + icon: 'icon-huawei-pay', + type: 'huaweipay', + description: '华为用户专属支付' }, - // #endif { name: '线下支付', icon: 'icondiy icon-yuezhifu', - type: 'offlinepay' + type: 'offlinepay', + description: '到店支付或银行转账' }, + { + name: '余额支付', + icon: 'icon-balance', + type: 'balancepay', + description: '使用账户余额支付' + } ], // #ifdef H5 timer: null, @@ -270,12 +274,12 @@ export default { return; } - // 使用统一支付工具类进行支付 + // 使用统一支付工具类进行真实支付调用 this.invokeUnifiedPay(payType.type); }, /** - * 统一支付调用方法(使用新的支付工具类) + * 统一支付调用方法(恢复真实后端调用) */ async invokeUnifiedPay(payType) { try { @@ -284,7 +288,7 @@ export default { const outTradeNo = this.payInfo.out_trade_no; const subject = '订单支付'; - // 根据支付类型调用对应的支付方法 + // 恢复真实支付方法调用(对接后端) switch (payType) { case 'wechatpay': payResult = await invokeWechatPay(outTradeNo, amount, subject); @@ -299,24 +303,38 @@ export default { throw new Error('不支持的支付方式'); } - // 处理H5支付跳转 + // 验证支付结果 + if (!payResult) { + throw new Error('支付结果为空'); + } + if (typeof payResult.code === 'undefined') { + throw new Error('缺少code属性'); + } + + // 真实调起逻辑 if (payResult.code === 0 && payResult.data?.payUrl) { - // H5端直接跳转,其他端需要在WebView中显示 + // 关闭支付中弹窗 + uni.hideLoading(); const systemInfo = uni.getSystemInfoSync(); + // H5端直接跳转 if (systemInfo.platform === 'web') { window.location.href = payResult.data.payUrl; this.checkPayStatus(); } else { - // 微信小程序/华为快应用中显示WebView + // 小程序/快应用跳WebView this.showPayWebView(payResult.data.payUrl); } } else if (payResult.code === 0) { - // 原生支付成功 + // 关闭支付中弹窗 + uni.hideLoading(); this.paySuccess(); } else { throw new Error(payResult.msg || '支付失败'); } + } catch (error) { + // 关闭支付中弹窗 + uni.hideLoading(); this.repeatFlag = false; this.$util.showToast({ title: error.message || '支付失败' @@ -325,11 +343,9 @@ export default { }, /** - * 显示支付WebView(用于微信小程序/华为快应用的H5支付) + * 显示支付WebView(真实跳转逻辑) */ showPayWebView(payUrl) { - // 这里可以打开一个新的WebView页面来显示支付 - // 或者使用现有的跳转逻辑 this.$util.redirectTo('/pages/Pay/Pay', { payUrl: payUrl, outTradeNo: this.payInfo.out_trade_no @@ -378,12 +394,12 @@ export default { return; } - // 小程序端也使用统一支付工具类 + // 小程序端真实调用统一支付工具类 this.invokeUnifiedPay(payType.type); }, // #endif /** - * 支付成功之后跳转 + * 支付成功之后跳转(真实业务逻辑) */ paySuccess() { if (this.payInfo.event == 'BlindboxGoodsOrderPayNotify') { @@ -400,7 +416,7 @@ export default { } }, /** - * 重置支付单据 + * 重置支付单据(真实业务逻辑) */ resetpay() { this.resetPayComplete = false; @@ -527,8 +543,9 @@ export default { .icon-zhifubaozhifu- { color: #00a0e9; } - - + .icon-huawei-pay { + color: #c7000b; // 华为支付品牌色 + } .icon-checkboxblank { font-size: 40rpx;