1. 微信支付概述
随着移动互联网时代的到来,微信支付已经成为人们日常支付中最为广泛使用的一种支付方式。对于微信小程序来说,实现微信支付是一项必不可少的开发需求。微信支付主要通过微信支付接口实现支付功能,本文将为大家详细讲解微信小程序中如何实现微信支付。
2. 创建支付订单
在使用微信支付前,我们需要先创建一个支付订单。我们将使用微信提供的统一下单API来创建订单。该API将返回一个预支付交易会话标识(prepay_id),我们将以此为基础完成后续的支付。下面是创建订单的代码。
2.1 获取支付的参数
首先,我们需要用到的是微信提供的API地址以及小程序生成的支付参数。代码如下所示:
const url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
const openid = wx.getStorageSync('openid');//从本地缓存中获取openid
const params = {
appid: 'xxxxx',//小程序appid
mch_id: 'xxxxx',//商户号
nonce_str: 'xxxxx',//随机字符串
sign_type: 'MD5',//签名类型
body: "支付测试",//商品描述
out_trade_no: "xxxxxx",//商户订单号
total_fee: 100,//支付金额,单位为分
spbill_create_ip: "xxxxxx",//终端的IP地址
notify_url: "http://xxxxx.com/payCallback",//通知地址
trade_type: "JSAPI",//交易类型
openid: openid,//用户的openid
};
// 将参数按照A-Z排序
let signStr = Object.keys(params).sort().map(function(key){
return key + '=' + params[key];
}).join('&') + '&key=【您的商户支付密钥】'; // 商户支付密钥,也需要放到最后面参与签名
params.sign = md5(signStr).toUpperCase(); // 将签名字符串进行md5加密
const PAY_PARAMS = obj2xml(params);//将参数转为xml格式,为后面请求微信支付接口做准备。
上面的代码中,我们用到了微信提供的API地址和小程序生成的支付参数。其中,appid为小程序的appid,mch_id为商户号,body为支付描述,out_trade_no为商户订单号,total_fee为支付金额,即用户需要支付的金额,单位为分。notify_url为支付回调地址。在获取到支付参数之后,我们使用md5算法对签名字符串加密,再将签名加入到请求参数中。
3. 调起微信支付
在小程序中,我们可以通过wx.request方法来发起微信支付请求,并将请求结果回调到我们的页面中。在请求成功后,我们将获得prepay_id,用于后续调起小程序支付。代码如下:
// 请求微信支付接口,获取预付单信息
wx.request({
url: url, //统一下单API地址
data: PAY_PARAMS, //请求参数
method: 'POST', //请求类型
header: { 'content-type': 'application/xml' }, //数据格式
success: function (res) {
const result = xml2obj(res.data);
console.log('微信支付完成', result);
const timeStamp = Math.floor(Date.now() / 1000);//时间戳
const paySignData = {
appId: 'xxxxx',//小程序appid
timeStamp: timeStamp.toString(),
nonceStr: 'xxxxx',//随机字符串
signType: 'MD5',//签名类型
package: 'prepay_id=' + result.prepay_id,
};
// 将参数按照A-Z排序
let signStr = Object.keys(paySignData).sort().map(function(key){
return key + '=' + paySignData[key];
}).join('&') + '&key=【您的商户支付密钥】'; // 商户支付密钥,也需要放到最后面参与签名
paySignData.paySign = md5(signStr).toUpperCase(); // 将签名字符串进行md5加密
wx.requestPayment({
timeStamp: paySignData.timeStamp,
nonceStr: paySignData.nonceStr,
package: paySignData.package,
signType: paySignData.signType,
paySign: paySignData.paySign,
success: function (res) {
console.log('微信支付成功', res)
},
fail: function (res) {
console.log('微信支付失败', res)
}
});
},
fail: function (res) {
console.log('微信支付失败', res)
},
});
在调用微信支付接口前,先通过wx.request方法向微信支付平台发起统一下单请求,获取到预支付交易会话标识prepay_id。在获取到prepay_id之后,我们将使用时间戳、随机字符串、签名类型、prepay_id等参数,再次生成一个签名字符串,并将此字符串作为参数调起wx.requestPayment方法,完成微信支付。
4. 支付结果处理
完成微信支付后,我们需要通过微信支付平台的回调函数,来获取到支付的结果,并根据支付的结果来更新我们的订单状态。我们需要在小程序的后台服务上处理这个回调请求。
4.1 配置小程序支付回调地址
我们需要在微信商户后台配置小程序接收微信支付回调的URL地址。在接收到微信支付结果后,微信支付平台将把支付结果返回到我们配置的URL地址。具体配置方式可参考微信商户平台的文档。
4.2 处理微信支付结果
当微信支付平台将支付结果返回给我们的小程序时,我们需要对这些结果进行处理,并根据结果来更新订单状态。在小程序后台服务中,我们可以通过下面的代码来处理微信支付结果。
router.post('/payCallback', async (ctx, next) => {
const reqBody = ctx.request.body;
const reqInfo = reqBody.xml;
console.log('微信支付结果回调', reqInfo);
//微信支付成功回调
if (reqInfo.return_code[0] === 'SUCCESS' && reqInfo.result_code[0] === 'SUCCESS') {
//微信支付订单号
const transaction_id = reqInfo.transaction_id[0];
//商户订单号
const out_trade_no = reqInfo.out_trade_no[0];
//支付成功时间
const pay_time = reqInfo.time_end[0];
//处理订单状态
const db = await getDB();
const collection = await db.collection('order');
try {
await collection.updateOne({ o_no: out_trade_no }, {
$set: { o_status: ORDER_STATUS.PAYED, pay_time: pay_time, transaction_id: transaction_id }
});
} finally {
db.close();
}
ctx.response.body = '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>'
} else {
ctx.response.body = '<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[支付失败]]></return_msg></xml>'
}
});
在微信支付平台将支付结果返回给小程序后,我们通过reqInfo来获取到了支付相关的信息,包括支付状态、支付订单号和支付成功的时间等信息。我们通过订单号来从数据库中获取到对应的订单,并将订单状态,支付成功时间和微信支付单号更新到数据库中,同时向微信支付平台返回一个回复信息,告知微信支付平台我们已经收到了回调。
5. 总结
在本文中,我们详细讲解了微信小程序中如何实现微信支付,包括创建订单,调起微信支付,以及处理微信支付结果等方面。微信支付是一项非常实用的功能,对于小程序开发来说,实现微信支付功能也将成为对小程序完整性的一种考量。希望本文的讲解能对大家在小程序中实现微信支付提供帮助。