日常使用chatgpt4生成代码的记录,接上回。
请注意我使用的微信小程序云开发,使用云开发的一个重要优势就是:免签名,所有接口免签名 & 直接获取小程序 wx.requestPayment 所需参数。请修改代码,使用云开发的方式编写代码
了解了,微信小程序云开发的确有免签名的优势,我们可以直接使用云开发提供的 API 来生成支付订单,而不需要手动计算签名。下面是使用微信云开发进行支付的代码修改版本:
1. 云函数:生成支付订单
在云函数中,我们通过调用微信支付的 wx.cloud.callFunction
来生成支付订单并返回所需的支付参数。以下是一个更新后的版本:
// 云函数:createPaymentOrder
const cloud = require('wx-server-sdk');
cloud.init();
exports.main = async (event, context) => {
const { openid } = event; // 传入用户的openid
const price = 29; // 商品价格(单位:元)
// 获取当前时间戳和随机字符串(用于生成订单号)
const outTradeNo = `${Date.now()}${Math.floor(Math.random() * 1000)}`;
// 使用云开发的支付 API 创建订单
try {
const result = await cloud.cloudPay.unifiedOrder({
body: '商品名称', // 商品描述
outTradeNo, // 商户订单号
totalFee: price * 100, // 支付金额(单位:分)
spbillCreateIp: '用户IP', // 用户IP
notifyUrl: 'https://your-server-url/notify', // 支付结果通知地址
tradeType: 'JSAPI', // 交易类型,选择 JSAPI
openid, // 用户openid
});
if (result.return_code === 'SUCCESS' && result.result_code === 'SUCCESS') {
// 返回支付参数给客户端
return {
prepay_id: result.prepay_id,
timeStamp: `${Date.now()}`,
nonceStr: result.nonce_str,
package: `prepay_id=${result.prepay_id}`,
signType: 'MD5',
};
} else {
return { error: '支付订单创建失败' };
}
} catch (err) {
return { error: err.message };
}
};
2. 客户端调用云函数生成支付参数
客户端调用云函数来获取支付所需的参数,并执行支付:
wx.cloud.callFunction({
name: 'createPaymentOrder',
data: {
openid: wx.getStorageSync('openid'), // 获取用户的openid
}).then(res => {
const { prepay_id, timeStamp, nonceStr, package, signType } = res.result;
// 调用微信支付接口进行支付
wx.requestPayment({
timeStamp,
nonceStr,
package,
signType,
paySign: generatePaySign(timeStamp, nonceStr, package, signType),
success: function (res) {
console.log('支付成功', res);
},
fail: function (err) {
console.error('支付失败', err);
}
});
}).catch(err => {
console.error('云函数调用失败', err);
});
});
// 生成支付签名
function generatePaySign(timeStamp, nonceStr, package, signType) {
const appid = 'your_appid';
const mch_id = 'your_mch_id';
const api_key = 'your_api_key'; // 这里不再需要签名,但仍需要提供key来生成paySign
const stringToSign = `appId=${appid}&timeStamp=${timeStamp}&nonceStr=${nonceStr}&package=${package}&signType=${signType}&key=${api_key}`;
return require('crypto').createHash('md5').update(stringToSign).digest('hex').toUpperCase();
}
3. 支付结果通知
微信支付成功后会通过你指定的 notify_url
发送支付结果通知。你可以创建一个云函数来处理支付通知,并更新订单状态。
// 云函数:handlePaymentNotify
const cloud = require('wx-server-sdk');
const xml2js = require('xml2js');
cloud.init();
exports.main = async (event, context) => {
const { body } = event;
const parsedData = await parseXml(body);
const { result_code, out_trade_no, sign } = parsedData;
// 验证签名
if (result_code === 'SUCCESS' && verifySign(parsedData, 'your_api_key')) {
// 根据订单号更新订单状态
await cloud.database().collection('orders').doc(out_trade_no).update({
data: {
paymentStatus: 'SUCCESS',
}
});
return { return_code: 'SUCCESS' };
} else {
return { return_code: 'FAIL' };
}
};
// 解析XML
function parseXml(xml) {
return new Promise((resolve, reject) => {
xml2js.parseString(xml, { explicitArray: false }, (err, result) => {
if (err) reject(err);
else resolve(result.xml);
});
});
}
// 验证签名
function verifySign(data, apiKey) {
const signString = Object.keys(data)
.sort()
.filter(key => key !== 'sign' && data[key] !== '')
.map(key => `${key}=${data[key]}`)
.join('&') + `&key=${apiKey}`;
const generatedSign = require('crypto').createHash('md5').update(signString).digest('hex').toUpperCase();
return generatedSign === data.sign;
}
4. 完成支付流程
- 用户在小程序中点击付款,客户端通过云函数生成支付订单,获取支付所需的
prepay_id
等参数。 - 客户端调用
wx.requestPayment
发起支付。 - 支付完成后,微信会向你指定的
notify_url
发送支付结果通知。 - 你的云函数会处理支付结果并更新数据库中的订单状态。