Files
yusheng-h5/until/wxpay.js

267 lines
7.1 KiB
JavaScript
Raw Normal View History

2026-01-08 16:06:53 +08:00
// utils/wxpay.js
const API_BASE_URL = 'https://yourdomain.com/api';
class WxPay {
constructor() {
this.isWeixin = this.checkWeixin();
this.openid = uni.getStorageSync('wx_openid') || '';
}
// 检查是否在微信环境
checkWeixin() {
const ua = navigator.userAgent.toLowerCase();
return ua.indexOf('micromessenger') !== -1;
}
// 获取 URL 参数
getQueryParam(name) {
const reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i');
const r = window.location.search.substr(1).match(reg);
if (r != null) return decodeURIComponent(r[2]);
return null;
}
// 微信授权获取 code
async wxAuth() {
if (!this.isWeixin) {
uni.showToast({ title: '请在微信中打开', icon: 'none' });
return null;
}
const code = this.getQueryParam('code');
if (!code) {
// 跳转微信授权
const currentUrl = encodeURIComponent(window.location.href.split('#')[0]);
const authUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${this.appId}&redirect_uri=${currentUrl}&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect`;
window.location.href = authUrl;
return null;
}
return code;
}
// 通过 code 获取 openid
async getOpenId(code) {
try {
const response = await uni.request({
url: `${API_BASE_URL}/wx/auth`,
method: 'GET',
data: { code }
});
if (response[1].data.code === 0) {
const { openid } = response[1].data.data;
this.openid = openid;
uni.setStorageSync('wx_openid', openid);
return openid;
}
return null;
} catch (error) {
console.error('获取openid失败:', error);
return null;
}
}
// 初始化微信 JS-SDK
async initWxJsSDK() {
if (!this.isWeixin) return false;
try {
// 获取当前页面 URL去掉 # 后面的部分)
const currentUrl = window.location.href.split('#')[0];
const response = await uni.request({
url: `${API_BASE_URL}/jssdk/config`,
method: 'GET',
data: { url: encodeURIComponent(currentUrl) }
});
if (response[1].data.code === 0) {
const config = response[1].data.data;
// 引入微信 JS-SDK
await this.loadWxJsSDK();
// 配置微信 JS-SDK
wx.config({
debug: false, // 开启调试模式
appId: config.appId,
timestamp: config.timestamp,
nonceStr: config.nonceStr,
signature: config.signature,
jsApiList: [
'chooseWXPay',
'onMenuShareTimeline',
'onMenuShareAppMessage',
'scanQRCode'
]
});
return new Promise((resolve) => {
wx.ready(() => {
console.log('微信 JS-SDK 初始化成功');
resolve(true);
});
wx.error((err) => {
console.error('微信 JS-SDK 初始化失败:', err);
uni.showToast({ title: '微信初始化失败', icon: 'none' });
resolve(false);
});
});
}
return false;
} catch (error) {
console.error('初始化JS-SDK失败:', error);
return false;
}
}
// 动态加载微信 JS-SDK
loadWxJsSDK() {
return new Promise((resolve, reject) => {
if (typeof wx !== 'undefined') {
resolve();
return;
}
const script = document.createElement('script');
script.src = 'https://res.wx.qq.com/open/js/jweixin-1.6.0.js';
script.onload = resolve;
script.onerror = reject;
document.head.appendChild(script);
});
}
// 创建支付订单
async createPayment(orderData) {
try {
// 确保有 openid
if (!this.openid) {
const code = await this.wxAuth();
if (code) {
await this.getOpenId(code);
}
}
if (!this.openid) {
throw new Error('获取用户信息失败');
}
const response = await uni.request({
url: `${API_BASE_URL}/wxpay/unifiedorder`,
method: 'POST',
header: { 'Content-Type': 'application/json' },
data: {
openid: this.openid,
body: orderData.body || '账户充值',
total_fee: orderData.amount,
out_trade_no: orderData.orderNo,
attach: orderData.attach || ''
}
});
if (response[1].data.code === 0) {
return response[1].data.data;
} else {
throw new Error(response[1].data.msg || '创建订单失败');
}
} catch (error) {
console.error('创建支付订单失败:', error);
throw error;
}
}
// 发起微信支付
async launchPayment(payData) {
return new Promise((resolve, reject) => {
wx.chooseWXPay({
timestamp: payData.timeStamp,
nonceStr: payData.nonceStr,
package: payData.package,
signType: payData.signType,
paySign: payData.paySign,
success: (res) => {
if (res.errMsg === 'chooseWXPay:ok') {
resolve({ success: true, message: '支付成功' });
} else {
reject(new Error('支付失败: ' + res.errMsg));
}
},
fail: (err) => {
reject(new Error('支付失败: ' + JSON.stringify(err)));
},
cancel: () => {
reject(new Error('用户取消支付'));
}
});
});
}
// 完整的支付流程
async pay(amount, orderNo, attach = '') {
try {
// 1. 检查环境
if (!this.isWeixin) {
uni.showToast({ title: '请在微信中打开', icon: 'none' });
return { success: false, message: '非微信环境' };
}
// 2. 初始化 JS-SDK
const initSuccess = await this.initWxJsSDK();
if (!initSuccess) {
return { success: false, message: '微信初始化失败' };
}
// 3. 创建支付订单
const payData = await this.createPayment({
amount: amount,
orderNo: orderNo,
attach: attach
});
// 4. 发起支付
const result = await this.launchPayment(payData);
// 5. 验证支付结果
if (result.success) {
// 支付成功,可以查询订单确认
await this.verifyPayment(orderNo);
return { success: true, message: '支付成功' };
}
return result;
} catch (error) {
console.error('支付流程错误:', error);
return {
success: false,
message: error.message || '支付失败'
};
}
}
// 验证支付结果
async verifyPayment(orderNo) {
try {
const response = await uni.request({
url: `${API_BASE_URL}/wxpay/query`,
method: 'GET',
data: { out_trade_no: orderNo }
});
if (response[1].data.code === 0) {
const orderData = response[1].data.data;
if (orderData.trade_state === 'SUCCESS') {
return true;
}
}
return false;
} catch (error) {
console.error('验证支付结果失败:', error);
return false;
}
}
}
export default new WxPay();