Node.js 微信支付接入指南:从配置到支付结果处理的全流程
在Node.js中接入微信支付,主要涉及使用微信支付API来处理支付请求、订单查询和退款等操作。本文将详细介绍如何在Node.js服务器上实现微信支付功能的全过程。
1. 注册并配置微信支付商户账号
首先,你需要在微信支付平台注册成为微信支付商户,并获取以下必要的信息:
- API密钥
- 商户号(MCHID)
- APPID
在获取这些信息后,还需要设置支付通知的回调URL,以便微信在支付完成后通知你的服务器。
2. 安装必要的Node.js库
为了简化HTTPS请求和XML处理,可以使用以下Node.js库:
- axios:用于发送HTTP请求。
- xml2js:用于解析和构建XML。
在你的项目中,使用npm安装这些依赖:
npm install axios xml2js
3. 创建支付请求
微信支付通过HTTPS POST请求发送加密后的XML数据。以下是构建订单信息并创建支付请求的示例代码。
const axios = require('axios');
const xml2js = require('xml2js');
// 示例函数:发送支付请求
async function createPayment(orderInfo) {
const xmlBuilder = new xml2js.Builder();
// 构造支付请求的XML
const xml = xmlBuilder.buildObject({
xml: {
appid: '你的APPID',
mch_id: '你的商户号',
nonce_str: '随机字符串',
sign: '使用API密钥生成的签名',
body: '商品描述',
out_trade_no: orderInfo.orderId, // 商户订单号
total_fee: orderInfo.amount, // 订单总金额,单位为分
spbill_create_ip: orderInfo.ip, // 用户的实际IP
notify_url: 'https://yourdomain.com/wechat/notify', // 支付结果通知回调地址
trade_type: 'JSAPI', // 支付类型:JSAPI、NATIVE、APP等
openid: orderInfo.openid, // 用户的OpenID(JSAPI支付必填)
}
});
try {
// 发送POST请求到微信支付统一下单接口
const response = await axios.post('https://api.mch.weixin.qq.com/pay/unifiedorder', xml, {
headers: { 'Content-Type': 'text/xml' },
});
// 解析微信支付返回的XML
const resXml = await new Promise((resolve, reject) => {
xml2js.parseString(response.data, (err, result) => {
if (err) reject(err);
resolve(result);
});
});
// 处理响应结果
if (resXml.xml.return_code === 'SUCCESS' && resXml.xml.result_code === 'SUCCESS') {
console.log('支付成功,prepay_id:', resXml.xml.prepay_id[0]);
return resXml.xml.prepay_id[0];
} else {
console.error('支付失败:', resXml.xml.err_code_des[0]);
return null;
}
} catch (error) {
console.error('请求失败:', error);
return null;
}
}
说明:
- nonce_str:随机字符串,用于防止重复请求。
- sign:基于API密钥生成的签名,确保数据的完整性。
- trade_type:支付类型,JSAPI 用于小程序和公众号支付。
此函数根据订单信息生成支付请求并提交到微信支付的统一下单接口。如果成功,会返回 prepay_id
,该值将在后续支付操作中使用。
4. 处理支付结果通知
当用户支付完成后,微信支付会向你设置的 notify_url
发送支付结果通知。你需要在该回调接口中验证通知的真实性,并根据结果更新订单状态。
示例回调处理代码:
const crypto = require('crypto');
// 示例:验证微信支付通知并处理
async function handlePaymentNotification(req, res) {
const xmlData = req.body; // 微信支付会发送XML格式的数据
xml2js.parseString(xmlData, async (err, result) => {
if (err) {
res.status(400).send('Invalid XML');
return;
}
const notification = result.xml;
// 验证签名
const sign = generateSign(notification, '你的API密钥');
if (sign !== notification.sign[0]) {
res.status(400).send('Invalid signature');
return;
}
// 处理支付结果
if (notification.return_code[0] === 'SUCCESS' && notification.result_code[0] === 'SUCCESS') {
// 支付成功,更新订单状态
console.log('支付成功:', notification.out_trade_no[0]);
res.send('<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>');
} else {
console.log('支付失败:', notification.err_code_des[0]);
res.send('<xml><return_code><![CDATA[FAIL]]></return_code></xml>');
}
});
}
// 签名生成函数
function generateSign(params, key) {
const stringToSign = Object.keys(params)
.filter(key => key !== 'sign' && params[key])
.sort()
.map(key => `${key}=${params[key]}`)
.join('&') + `&key=${key}`;
return crypto.createHash('md5').update(stringToSign).digest('hex').toUpperCase();
}
要点:
- 签名验证:确保支付结果的真实性。使用
generateSign
函数计算签名,确保与微信支付通知中的签名匹配。 - 订单状态更新:确认支付成功后,更新数据库中的订单状态。
5. 注意事项
1. 安全性
妥善保管API密钥、商户号等敏感信息,避免泄露。
2. 错误处理
微信支付API调用可能会出现网络错误或参数错误,需适当处理异常。
3. 调用频率限制
微信支付API有频率限制,请确保在业务中合理控制请求频率。
4. 文档资源
详细的API说明可参考微信支付官方文档。