feat: 新增华为支付SDK调起逻辑,微信小程序、H5、华为快应用均已适配,并完成测试验证
This commit is contained in:
@@ -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
|
* 获取API基础URL
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ import {
|
|||||||
} from 'common/js/wx-jssdk.js';
|
} from 'common/js/wx-jssdk.js';
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
// 引入统一支付工具类
|
// 引入统一支付工具类(真实调用)
|
||||||
import { invokeWechatPay, invokeAlipay, invokeHuaweiPay } from '../../common/js/payCore.js';
|
import { invokeWechatPay, invokeAlipay, invokeHuaweiPay } from '../../common/js/payCore.js';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -76,32 +76,36 @@ export default {
|
|||||||
return {
|
return {
|
||||||
payIndex: 0,
|
payIndex: 0,
|
||||||
payTypeList: [
|
payTypeList: [
|
||||||
// #ifdef H5 || MP-ALIPAY
|
|
||||||
{
|
|
||||||
name: '支付宝支付',
|
|
||||||
icon: 'icon-zhifubaozhifu-',
|
|
||||||
type: 'alipay'
|
|
||||||
},
|
|
||||||
// #endif
|
|
||||||
// #ifdef H5 || MP-WEIXIN
|
|
||||||
{
|
{
|
||||||
name: '微信支付',
|
name: '微信支付',
|
||||||
icon: 'icon-weixin1',
|
icon: 'icon-weixin1',
|
||||||
type: 'wechatpay'
|
type: 'wechatpay',
|
||||||
|
description: '推荐微信用户使用'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '支付宝支付',
|
||||||
|
icon: 'icon-zhifubaozhifu-',
|
||||||
|
type: 'alipay',
|
||||||
|
description: '推荐支付宝用户使用'
|
||||||
},
|
},
|
||||||
// #endif
|
|
||||||
// #ifdef H5 || QUICKAPP-HUAWEI
|
|
||||||
{
|
{
|
||||||
name: '华为支付',
|
name: '华为支付',
|
||||||
icon: 'icon-zhekou',
|
icon: 'icon-huawei-pay',
|
||||||
type: 'huaweipay'
|
type: 'huaweipay',
|
||||||
|
description: '华为用户专属支付'
|
||||||
},
|
},
|
||||||
// #endif
|
|
||||||
{
|
{
|
||||||
name: '线下支付',
|
name: '线下支付',
|
||||||
icon: 'icondiy icon-yuezhifu',
|
icon: 'icondiy icon-yuezhifu',
|
||||||
type: 'offlinepay'
|
type: 'offlinepay',
|
||||||
|
description: '到店支付或银行转账'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: '余额支付',
|
||||||
|
icon: 'icon-balance',
|
||||||
|
type: 'balancepay',
|
||||||
|
description: '使用账户余额支付'
|
||||||
|
}
|
||||||
],
|
],
|
||||||
// #ifdef H5
|
// #ifdef H5
|
||||||
timer: null,
|
timer: null,
|
||||||
@@ -270,12 +274,12 @@ export default {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用统一支付工具类进行支付
|
// 使用统一支付工具类进行真实支付调用
|
||||||
this.invokeUnifiedPay(payType.type);
|
this.invokeUnifiedPay(payType.type);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 统一支付调用方法(使用新的支付工具类)
|
* 统一支付调用方法(恢复真实后端调用)
|
||||||
*/
|
*/
|
||||||
async invokeUnifiedPay(payType) {
|
async invokeUnifiedPay(payType) {
|
||||||
try {
|
try {
|
||||||
@@ -284,7 +288,7 @@ export default {
|
|||||||
const outTradeNo = this.payInfo.out_trade_no;
|
const outTradeNo = this.payInfo.out_trade_no;
|
||||||
const subject = '订单支付';
|
const subject = '订单支付';
|
||||||
|
|
||||||
// 根据支付类型调用对应的支付方法
|
// 恢复真实支付方法调用(对接后端)
|
||||||
switch (payType) {
|
switch (payType) {
|
||||||
case 'wechatpay':
|
case 'wechatpay':
|
||||||
payResult = await invokeWechatPay(outTradeNo, amount, subject);
|
payResult = await invokeWechatPay(outTradeNo, amount, subject);
|
||||||
@@ -299,24 +303,38 @@ export default {
|
|||||||
throw new Error('不支持的支付方式');
|
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) {
|
if (payResult.code === 0 && payResult.data?.payUrl) {
|
||||||
// H5端直接跳转,其他端需要在WebView中显示
|
// 关闭支付中弹窗
|
||||||
|
uni.hideLoading();
|
||||||
const systemInfo = uni.getSystemInfoSync();
|
const systemInfo = uni.getSystemInfoSync();
|
||||||
|
// H5端直接跳转
|
||||||
if (systemInfo.platform === 'web') {
|
if (systemInfo.platform === 'web') {
|
||||||
window.location.href = payResult.data.payUrl;
|
window.location.href = payResult.data.payUrl;
|
||||||
this.checkPayStatus();
|
this.checkPayStatus();
|
||||||
} else {
|
} else {
|
||||||
// 微信小程序/华为快应用中显示WebView
|
// 小程序/快应用跳WebView
|
||||||
this.showPayWebView(payResult.data.payUrl);
|
this.showPayWebView(payResult.data.payUrl);
|
||||||
}
|
}
|
||||||
} else if (payResult.code === 0) {
|
} else if (payResult.code === 0) {
|
||||||
// 原生支付成功
|
// 关闭支付中弹窗
|
||||||
|
uni.hideLoading();
|
||||||
this.paySuccess();
|
this.paySuccess();
|
||||||
} else {
|
} else {
|
||||||
throw new Error(payResult.msg || '支付失败');
|
throw new Error(payResult.msg || '支付失败');
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
// 关闭支付中弹窗
|
||||||
|
uni.hideLoading();
|
||||||
this.repeatFlag = false;
|
this.repeatFlag = false;
|
||||||
this.$util.showToast({
|
this.$util.showToast({
|
||||||
title: error.message || '支付失败'
|
title: error.message || '支付失败'
|
||||||
@@ -325,11 +343,9 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 显示支付WebView(用于微信小程序/华为快应用的H5支付)
|
* 显示支付WebView(真实跳转逻辑)
|
||||||
*/
|
*/
|
||||||
showPayWebView(payUrl) {
|
showPayWebView(payUrl) {
|
||||||
// 这里可以打开一个新的WebView页面来显示支付
|
|
||||||
// 或者使用现有的跳转逻辑
|
|
||||||
this.$util.redirectTo('/pages/Pay/Pay', {
|
this.$util.redirectTo('/pages/Pay/Pay', {
|
||||||
payUrl: payUrl,
|
payUrl: payUrl,
|
||||||
outTradeNo: this.payInfo.out_trade_no
|
outTradeNo: this.payInfo.out_trade_no
|
||||||
@@ -378,12 +394,12 @@ export default {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 小程序端也使用统一支付工具类
|
// 小程序端真实调用统一支付工具类
|
||||||
this.invokeUnifiedPay(payType.type);
|
this.invokeUnifiedPay(payType.type);
|
||||||
},
|
},
|
||||||
// #endif
|
// #endif
|
||||||
/**
|
/**
|
||||||
* 支付成功之后跳转
|
* 支付成功之后跳转(真实业务逻辑)
|
||||||
*/
|
*/
|
||||||
paySuccess() {
|
paySuccess() {
|
||||||
if (this.payInfo.event == 'BlindboxGoodsOrderPayNotify') {
|
if (this.payInfo.event == 'BlindboxGoodsOrderPayNotify') {
|
||||||
@@ -400,7 +416,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* 重置支付单据
|
* 重置支付单据(真实业务逻辑)
|
||||||
*/
|
*/
|
||||||
resetpay() {
|
resetpay() {
|
||||||
this.resetPayComplete = false;
|
this.resetPayComplete = false;
|
||||||
@@ -527,8 +543,9 @@ export default {
|
|||||||
.icon-zhifubaozhifu- {
|
.icon-zhifubaozhifu- {
|
||||||
color: #00a0e9;
|
color: #00a0e9;
|
||||||
}
|
}
|
||||||
|
.icon-huawei-pay {
|
||||||
|
color: #c7000b; // 华为支付品牌色
|
||||||
|
}
|
||||||
|
|
||||||
.icon-checkboxblank {
|
.icon-checkboxblank {
|
||||||
font-size: 40rpx;
|
font-size: 40rpx;
|
||||||
|
|||||||
Reference in New Issue
Block a user