微信支付作为中国最流行的移动支付,已成为众多企业在线业务的首选支付方式。对于使用 serverless 架构的应用来说,如何在不使用传统的服务器架构的情况下集成微信支付,是一个备受关注的问题。本文将为大家介绍在 Serverless 应用中集成微信支付的最佳实践,以及如何在 AWS Lambda 的环境中实现该功能。
一、微信支付的相关知识
在介绍 Serverless 应用中使用微信支付的最佳实践之前,我们先对微信支付的相关知识进行简单介绍。
1. 微信支付的支付类型及流程
微信支付的支付类型有两种:JSAPI 和 Native。其中 JSAPI 适用于网页和公众号支付,Native 适用于 APP 支付。
微信支付的流程如下:
- 用户选择需要购买的商品,点击支付按钮后跳转至微信支付界面。
- 用户输入支付密码,确认支付。
- 微信支付系统将支付结果返回给商户后台。
- 商户后台根据支付结果更新订单状态,完成交易。
2. 微信支付的开发流程及接口文档
微信支付的开发流程如下:
- 微信支付商户号注册及开通 API 权限。
- 生成公众号、APP、H5 等支付的 appid。
- 根据业务要求选择支付类型,实现支付的前端调用及后端验证。
- 根据 API 文档集成微信支付接口。
微信支付的接口文档详见:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
二、Serverless 应用中使用微信支付的最佳实践
在 Serverless 应用中使用微信支付,一般需要遵循以下最佳实践:
1. 使用云函数
在前端应用中调用微信支付 API 时,可以将支付参数传递给后台的云函数,由云函数完成微信支付的接口调用及结果验证等操作。这样可以避免前端直接接触微信支付的 API 密钥等敏感信息,确保支付的安全性。
2. 配置前端拦截器
在前端代码中,可以配置一个拦截器,在用户点击支付按钮时对订单信息进行验证,确保订单信息的真实性与完整性。一旦发现订单信息有问题,可直接提示用户重新处理订单,避免交易风险。
3. 配置后端提醒机制
在微信支付中,由于网络原因,支付结果的回调可能会有所延迟。因此,建议在云函数中增加提醒机制,定时推送支付结果给商户管理后台。这样可以及时跟踪支付状态,确保交易的完整性。
4. 避免重复支付
为避免用户重复支付,可以在逻辑控制上进行优化。比如,对于一个已支付的订单,在用户点击支付按钮时,应提示用户该订单已完成支付,无需重复支付。在商户后台,也可通过订单号的去重操作,避免用户无意中发起重复的支付请求。
5. 支付结果的处理
在支付结果返回后,应在云函数中对支付结果进行验证,确保支付状态的一致性。同时,应及时更新订单状态,并将支付结果返回给前端,以便前端展示交易结果信息。
三、在 AWS Lambda 环境中实现微信支付
下面以 AWS Lambda 环境为例,介绍如何在 Serverless 应用中集成微信支付。
1. 创建云函数
在 AWS Lambda 环境中,可以选择使用 Node.js 开发云函数。在开发过程中,需要将微信支付的配置参数写入环境变量以避免敏感信息泄露。对于多个微信支付场景,可以创建不同的云函数来实现。
2. 集成微信支付 API
Node.js 开发环境提供了丰富的网络请求库,可以轻松地实现微信支付 API 的调用。在集成过程中,需要注意网络请求的安全性,并对微信支付结果及异常情况进行处理。
示例代码:
// www.javascriptcn.com code example
const request = require('request');
const crypto = require('crypto');
const appId = process.env.WECHAT_APP_ID;
const mchId = process.env.WECHAT_MCH_ID;
const key = process.env.WECHAT_PAY_KEY;
exports.handler = (event, context, callback) => {
// 在这里实现微信支付 API 的调用
};3. 实现业务逻辑
在云函数中实现业务逻辑时,需要注意订单信息的验证、支付结果的通知以及重复支付的处理等问题。可以根据具体业务需求,结合微信支付 API 的特性进行实现。
示例代码:
// www.javascriptcn.com code example
const request = require('request');
const crypto = require('crypto');
const appId = process.env.WECHAT_APP_ID;
const mchId = process.env.WECHAT_MCH_ID;
const key = process.env.WECHAT_PAY_KEY;
exports.handler = (event, context, callback) => {
// 验证订单信息
const order = event.order;
if (!order || !order.orderId || !order.amount || !order.desc || !order.clientIp) {
callback(new Error('订单信息不完整'));
return;
}
// 生成随机字符串和时间戳
const nonceStr = crypto.randomBytes(16).toString('hex');
const timestamp = Math.round(new Date().getTime() / 1000);
// 构建请求参数
const signParams = {
appid: appId,
mch_id: mchId,
nonce_str: nonceStr,
body: order.desc,
out_trade_no: order.orderId,
total_fee: order.amount,
spbill_create_ip: order.clientIp,
notify_url: 'https://your.domain.com/pay/callback' // 支付结果回调地址
};
const signStr = Object.keys(signParams)
.filter(key => signParams[key] !== undefined)
.sort()
.map(key => `${key}=${signParams[key]}`)
.join('&') + `&key=${key}`;
const sign = crypto.createHash('md5').update(signStr).digest('hex').toUpperCase();
const payParams = Object.assign({}, signParams, { sign, time_stamp: timestamp });
// 构建支付请求
request.post({
url: 'https://api.mch.weixin.qq.com/pay/unifiedorder',
body: `<xml>
<appid>${payParams.appid}</appid>
<body>${payParams.body}</body>
<mch_id>${payParams.mch_id}</mch_id>
<nonce_str>${payParams.nonce_str}</nonce_str>
<notify_url>${payParams.notify_url}</notify_url>
<out_trade_no>${payParams.out_trade_no}</out_trade_no>
<spbill_create_ip>${payParams.spbill_create_ip}</spbill_create_ip>
<total_fee>${payParams.total_fee}</total_fee>
<sign>${payParams.sign}</sign>
<time_stamp>${payParams.time_stamp}</time_stamp>
<trade_type>JSAPI</trade_type>
<openid>${event.user.openid}</openid>
</xml>`
}, (err, response, body) => {
if (err) {
callback(err);
return;
}
// 解析支付结果
parseString(body, (err, result) => {
if (err || !result.xml || result.xml.return_code[0] !== 'SUCCESS') {
callback(new Error('支付失败'));
return;
}
// 返回支付结果
const prepayId = result.xml.prepay_id[0];
const nonceStr = crypto.randomBytes(16).toString('hex');
const timestamp = Math.round(new Date().getTime() / 1000);
const requestParams = {
appId,
timeStamp: timestamp,
nonceStr,
package: `prepay_id=${prepayId}`,
signType: 'MD5'
};
const requestStr = Object.keys(requestParams)
.filter(key => requestParams[key] !== undefined)
.sort()
.map(key => `${key}=${requestParams[key]}`)
.join('&') + `&key=${key}`;
const sign = crypto.createHash('md5').update(requestStr).digest('hex').toUpperCase();
const wechatPayParams = Object.assign({}, requestParams, { paySign: sign });
callback(null, wechatPayParams);
});
});
};四、结语
以上就是在 Serverless 应用中使用微信支付的最佳实践以及如何在 AWS Lambda 的环境中实现微信支付的介绍。通过合理的架构设计与技术实现,可以确保微信支付的安全性和交易的完整性,为企业的在线业务提供更加优质的支付服务。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67cfeb7ae46428fe9ec3a349