fix: 封装微信支付
All checks were successful
构建并部署前端到生产环境 / build-and-deploy (push) Successful in 46s

This commit is contained in:
sexygoat
2026-04-16 10:28:02 +08:00
parent 6b066e35da
commit c06d543af3
5 changed files with 149 additions and 284 deletions

View File

@@ -222,7 +222,6 @@
.content-wrapper {
width: 100%;
max-width: 600rpx;
}
.content {

View File

@@ -177,6 +177,7 @@
import {
useUserStore
} from '@/store/index.js';
import { wechatH5Pay, handlePaymentError, showPaymentToast } from '@/utils/payment.js';
const userStore = useUserStore();
@@ -347,87 +348,21 @@
}
// 第三步:调起微信支付
// #ifdef H5
if (typeof WeixinJSBridge === 'undefined') {
uni.showToast({
title: '请在微信中打开',
icon: 'none'
});
return;
try {
await wechatH5Pay(rechargeData.pay_config);
// 支付成功
showPaymentToast(true, '充值成功');
setTimeout(() => {
loadWalletDetail();
rechargePage.value = 1;
rechargeNoMore.value = false;
loadRechargeList();
}, 1500);
} catch (error) {
// 支付失败或取消
handlePaymentError(error);
}
WeixinJSBridge.invoke('getBrandWCPayRequest', {
appId: rechargeData.pay_config.app_id,
timeStamp: rechargeData.pay_config.timestamp,
nonceStr: rechargeData.pay_config.nonce_str,
package: rechargeData.pay_config.package,
signType: rechargeData.pay_config.sign_type,
paySign: rechargeData.pay_config.pay_sign
}, function(res) {
if (res.err_msg === 'get_brand_wcpay_request:ok') {
console.log('支付成功', res);
uni.showToast({
title: '充值成功',
icon: 'success'
});
setTimeout(() => {
loadWalletDetail();
rechargePage.value = 1;
rechargeNoMore.value = false;
loadRechargeList();
}, 1500);
} else if (res.err_msg === 'get_brand_wcpay_request:cancel') {
uni.showToast({
title: '已取消支付',
icon: 'none'
});
} else {
console.error('支付失败', res);
uni.showToast({
title: '支付失败',
icon: 'none'
});
}
});
// #endif
// #ifndef H5
uni.requestPayment({
timeStamp: rechargeData.pay_config.timestamp,
nonceStr: rechargeData.pay_config.nonce_str,
package: rechargeData.pay_config.package,
signType: rechargeData.pay_config.sign_type,
paySign: rechargeData.pay_config.pay_sign,
success: (res) => {
console.log('支付成功', res);
uni.showToast({
title: '充值成功',
icon: 'success'
});
setTimeout(() => {
loadWalletDetail();
rechargePage.value = 1;
rechargeNoMore.value = false;
loadRechargeList();
}, 1500);
},
fail: (err) => {
console.error('支付失败', err);
if (err.errMsg && (err.errMsg.includes('cancel') || err.errMsg.includes('用户取消'))) {
uni.showToast({
title: '已取消支付',
icon: 'none'
});
} else {
uni.showToast({
title: '支付失败',
icon: 'none'
});
}
}
});
// #endif
} catch (e) {
uni.hideLoading();
console.error('充值失败', e);
@@ -563,83 +498,21 @@
}
// 调起微信支付
// #ifdef H5
if (typeof WeixinJSBridge === 'undefined') {
uni.showToast({
title: '请在微信中打开',
icon: 'none'
});
return;
try {
await wechatH5Pay(rechargeData.pay_config);
// 支付成功
showPaymentToast(true, '充值成功');
setTimeout(() => {
loadWalletDetail();
rechargePage.value = 1;
rechargeNoMore.value = false;
loadRechargeList();
}, 1500);
} catch (error) {
// 支付失败或取消
handlePaymentError(error);
}
WeixinJSBridge.invoke('getBrandWCPayRequest', {
appId: rechargeData.pay_config.app_id,
timeStamp: rechargeData.pay_config.timestamp,
nonceStr: rechargeData.pay_config.nonce_str,
package: rechargeData.pay_config.package,
signType: rechargeData.pay_config.sign_type,
paySign: rechargeData.pay_config.pay_sign
}, function(res) {
if (res.err_msg === 'get_brand_wcpay_request:ok') {
uni.showToast({
title: '充值成功',
icon: 'success'
});
setTimeout(() => {
loadWalletDetail();
rechargePage.value = 1;
rechargeNoMore.value = false;
loadRechargeList();
}, 1500);
} else if (res.err_msg === 'get_brand_wcpay_request:cancel') {
uni.showToast({
title: '已取消支付',
icon: 'none'
});
} else {
uni.showToast({
title: '支付失败',
icon: 'none'
});
}
});
// #endif
// #ifndef H5
uni.requestPayment({
timeStamp: rechargeData.pay_config.timestamp,
nonceStr: rechargeData.pay_config.nonce_str,
package: rechargeData.pay_config.package,
signType: rechargeData.pay_config.sign_type,
paySign: rechargeData.pay_config.pay_sign,
success: (res) => {
uni.showToast({
title: '充值成功',
icon: 'success'
});
setTimeout(() => {
loadWalletDetail();
rechargePage.value = 1;
rechargeNoMore.value = false;
loadRechargeList();
}, 1500);
},
fail: (err) => {
if (err.errMsg && (err.errMsg.includes('cancel') || err.errMsg.includes('用户取消'))) {
uni.showToast({
title: '已取消支付',
icon: 'none'
});
} else {
uni.showToast({
title: '支付失败',
icon: 'none'
});
}
}
});
// #endif
} catch (e) {
uni.hideLoading();
console.error('获取支付配置失败', e);

View File

@@ -80,6 +80,7 @@
import {
useUserStore
} from '@/store/index.js';
import { wechatH5Pay, handlePaymentError, showPaymentToast } from '@/utils/payment.js';
const userStore = useUserStore();
@@ -197,81 +198,21 @@
return;
}
// #ifdef H5
if (typeof WeixinJSBridge === 'undefined') {
uni.showToast({
title: '请在微信中打开',
icon: 'none'
});
return;
// 调起微信支付
try {
await wechatH5Pay(payData.pay_config);
// 支付成功
showPaymentToast(true, '支付成功');
setTimeout(() => {
page.value = 1;
noMore.value = false;
loadOrderList();
}, 1500);
} catch (error) {
// 支付失败或取消
handlePaymentError(error);
}
WeixinJSBridge.invoke('getBrandWCPayRequest', {
appId: payData.pay_config.app_id,
timeStamp: payData.pay_config.timestamp,
nonceStr: payData.pay_config.nonce_str,
package: payData.pay_config.package,
signType: payData.pay_config.sign_type,
paySign: payData.pay_config.pay_sign
}, function(res) {
if (res.err_msg === 'get_brand_wcpay_request:ok') {
uni.showToast({
title: '支付成功',
icon: 'success'
});
setTimeout(() => {
page.value = 1;
noMore.value = false;
loadOrderList();
}, 1500);
} else if (res.err_msg === 'get_brand_wcpay_request:cancel') {
uni.showToast({
title: '已取消支付',
icon: 'none'
});
} else {
uni.showToast({
title: '支付失败',
icon: 'none'
});
}
});
// #endif
// #ifndef H5
uni.requestPayment({
timeStamp: payData.pay_config.timestamp,
nonceStr: payData.pay_config.nonce_str,
package: payData.pay_config.package,
signType: payData.pay_config.sign_type,
paySign: payData.pay_config.pay_sign,
success: () => {
uni.showToast({
title: '支付成功',
icon: 'success'
});
setTimeout(() => {
page.value = 1;
noMore.value = false;
loadOrderList();
}, 1500);
},
fail: (err) => {
if (err.errMsg && (err.errMsg.includes('cancel') || err.errMsg.includes('用户取消'))) {
uni.showToast({
title: '已取消支付',
icon: 'none'
});
} else {
uni.showToast({
title: '支付失败',
icon: 'none'
});
}
}
});
// #endif
} catch (e) {
uni.hideLoading();
console.error('支付失败', e);

View File

@@ -81,6 +81,7 @@
import { ref, reactive, onMounted } from 'vue';
import { assetApi, orderApi, walletApi } from '@/api/index.js';
import { useUserStore } from '@/store/index.js';
import { wechatH5Pay, handlePaymentError, showPaymentToast } from '@/utils/payment.js';
const userStore = useUserStore();
@@ -276,63 +277,18 @@
};
const handleWechatPay = async (payConfig, isForceRecharge = false) => {
// 验证参数
if (!payConfig.package || !payConfig.package.startsWith('prepay_id=')) {
uni.showToast({ title: '支付参数无效', icon: 'none' });
return;
try {
await wechatH5Pay(payConfig);
// 支付成功
const successMsg = isForceRecharge ? '充值成功,套餐将自动购买' : '支付成功';
showPaymentToast(true, successMsg);
setTimeout(() => {
loadWalletBalance();
}, 1500);
} catch (error) {
// 支付失败或取消
handlePaymentError(error);
}
// #ifdef H5
if (typeof WeixinJSBridge === 'undefined') {
uni.showToast({ title: '请在微信中打开', icon: 'none' });
return;
}
WeixinJSBridge.invoke('getBrandWCPayRequest', {
appId: payConfig.app_id,
timeStamp: payConfig.timestamp,
nonceStr: payConfig.nonce_str,
package: payConfig.package,
signType: payConfig.sign_type,
paySign: payConfig.pay_sign
}, function(res) {
if (res.err_msg === 'get_brand_wcpay_request:ok') {
const successMsg = isForceRecharge ? '充值成功,套餐将自动购买' : '支付成功';
uni.showToast({ title: successMsg, icon: 'success', duration: 2000 });
setTimeout(() => {
loadWalletBalance();
}, 1500);
} else if (res.err_msg === 'get_brand_wcpay_request:cancel') {
uni.showToast({ title: '已取消支付', icon: 'none' });
} else {
uni.showToast({ title: '支付失败', icon: 'none' });
}
});
// #endif
// #ifndef H5
uni.requestPayment({
timeStamp: payConfig.timestamp,
nonceStr: payConfig.nonce_str,
package: payConfig.package,
signType: payConfig.sign_type,
paySign: payConfig.pay_sign,
success: (res) => {
const successMsg = isForceRecharge ? '充值成功,套餐将自动购买' : '支付成功';
uni.showToast({ title: successMsg, icon: 'success', duration: 2000 });
setTimeout(() => {
loadWalletBalance();
}, 1500);
},
fail: (err) => {
if (err.errMsg && (err.errMsg.includes('cancel') || err.errMsg.includes('用户取消'))) {
uni.showToast({ title: '已取消支付', icon: 'none' });
} else {
uni.showToast({ title: '支付失败', icon: 'none' });
}
}
});
// #endif
};
onMounted(() => {

96
utils/payment.js Normal file
View File

@@ -0,0 +1,96 @@
/**
* 微信H5支付工具
* 统一处理微信JSAPI支付逻辑
*/
/**
* 调起微信H5支付
* @param {Object} payConfig - 支付配置对象
* @param {string} payConfig.app_id - 微信公众号appid
* @param {string} payConfig.timestamp - 时间戳
* @param {string} payConfig.nonce_str - 随机字符串
* @param {string} payConfig.package - 预支付交易会话标识
* @param {string} payConfig.sign_type - 签名方式
* @param {string} payConfig.pay_sign - 签名
* @returns {Promise} 支付结果
*/
export function wechatH5Pay(payConfig) {
return new Promise((resolve, reject) => {
// 验证支付配置
if (!payConfig || !payConfig.package) {
reject(new Error('支付参数无效'));
return;
}
// 验证 package 格式
if (!payConfig.package.startsWith('prepay_id=')) {
reject(new Error('支付参数无效'));
return;
}
// 检查是否在微信环境中
if (typeof WeixinJSBridge === 'undefined') {
reject(new Error('请在微信中打开'));
return;
}
// 调起微信支付
WeixinJSBridge.invoke('getBrandWCPayRequest', {
appId: payConfig.app_id,
timeStamp: payConfig.timestamp,
nonceStr: payConfig.nonce_str,
package: payConfig.package,
signType: payConfig.sign_type,
paySign: payConfig.pay_sign
}, function(res) {
if (res.err_msg === 'get_brand_wcpay_request:ok') {
// 支付成功
resolve({
success: true,
message: '支付成功'
});
} else if (res.err_msg === 'get_brand_wcpay_request:cancel') {
// 用户取消支付
reject({
cancelled: true,
message: '已取消支付'
});
} else {
// 支付失败
reject({
success: false,
message: '支付失败',
error: res
});
}
});
});
}
/**
* 显示支付结果提示
* @param {boolean} success - 是否成功
* @param {string} message - 提示消息
*/
export function showPaymentToast(success, message) {
uni.showToast({
title: message || (success ? '支付成功' : '支付失败'),
icon: success ? 'success' : 'none',
duration: 2000
});
}
/**
* 处理支付错误
* @param {Error|Object} error - 错误对象
*/
export function handlePaymentError(error) {
if (error.cancelled) {
// 用户主动取消,提示取消
showPaymentToast(false, '已取消支付');
} else {
// 其他错误
const message = error.message || '支付失败';
showPaymentToast(false, message);
}
}