自行准备好商户api和app密钥,需要公众号为服务号类型,还要有绑定小程序,这里使用的是小程序支付
官网链接 https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_8_0.shtml
本文支付逻辑:前端先调用微信login接口拿到code,接着调用后端get_openId接口拿到openid,然后再生成预支付信息获取预支付id,再然后创建前端拉起支付需要的支付参数,最后返回支付参数给前端,前端再通过wx.requestPayment方法拉起微信支付页面,再最后用户确定并完成了支付
一、做好前端界面
点击开始支付就调用微信登录接口,我这里由于是测试支付就直接拉起支付弹窗。
wx.login({
success: res => {
wx.request({
url: 'https://www.xxx.asia/node/weapp/pay/login',
method: 'POST',
data: {
code: res.code,
order: {
price: 1, //单位 分。只能是分
description: "Image形象店-深圳腾大-QQ公仔"
}
},
success: (res1) => {
wx.requestPayment({
timeStamp: res1.data.data.timestamp,
nonceStr: res1.data.data.nonce_str,
package: res1.data.data.package,
signType: res1.data.data.signType,
paySign: res1.data.data.paySign,
success() {
wx.showModal({
title: '提示',
content: '支付成功!',
showCancel: false,
});
},
fail(err) {
console.log('fail:' + JSON.stringify(err));
}
});
}
})
}
})
二、后端代码
1、首先建立好一个普通的node后端服务
app.listen(3245, () => {
console.log(
"服务在http://localhost:3245",
"时间:" + new Date().toLocaleString()
);
});
2、获取openid的接口
// 根据微信code获取 openid
async function getOpenId(code = "") {
try {
const res = await instance({
url: `https://api.weixin.qq.com/sns/jscode2session?appid=xxx&secret=xxx&js_code=${code}&grant_type=authorization_code`,
method: "get",
});
return res.data.openid;
} catch (error) {
return error.response.request.data;
}
}
3、获取支付信息获取交易会话标识 预支付id prepay_id
async getPrepayInfo() {
let timestamp = Math.floor(new Date().getTime() / 1000);
let nonce_str = generateNonceStr(32);
let wxOrderInfo = {
mchid: "xxx",
appid: "xxx",
notify_url: "https://www.xxx.asia/weapp/pay/isSuccess", // 回调地址(必须是公网地址) 这里需要我们自行实现用来接收支付结果信息
out_trade_no: nonce_str, // 上面创建的订单的订单号 我们自己自定义的
description: this.order.description, // 商品描述
amount: {
total: this.order.price, // 单位为分
currency: "CNY",
},
payer: {
openid: this.openid, // 用户的openid
},
};
let signature = this.createOrderSign(timestamp, nonce_str, wxOrderInfo);
let Authorization = `WECHATPAY2-SHA256-RSA2048 mchid="商户号mchid",nonce_str="${nonce_str}",timestamp="${timestamp}",signature="${signature}",serial_no="商户API证书序列号"`;
this.prepay_id = await getPrepayId(wxOrderInfo, Authorization);
}
1、generateNonceStr代码
// 生成随机字符串
function generateNonceStr(len) {
let data = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678";
let str = "";
for (let i = 0; i < len; i++) {
str += data.charAt(Math.floor(Math.random() * data.length));
}
return str;
}
2、createOrderSign代码
createOrderSign(timestamp, nonce_str, wxOrderInfo) {
// 签名串
let signStr = `POST\n/v3/pay/transactions/jsapi\n${timestamp}\n${nonce_str}\n${JSON.stringify(
wxOrderInfo
)}\n`;
// 读取API证书文件内容 apiclient_key.pem的内容
let cert = fs.readFileSync("./utils/cert/apiclient_key.pem", "utf-8");
// 创建使用 RSA 算法和 SHA-256 散列算法的签名对象
let sign = crypto.createSign("RSA-SHA256");
// 对签名串进行加密处理
sign.update(signStr);
return sign.sign(cert, "base64");
}
3、getPrepayId代码
async function getPrepayId(wxOrderInfo = {}, Authorization = "") {
try {
const res = await instance({
url: "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi",
method: "post",
data: wxOrderInfo,
headers: {
Authorization,
Accept: "application/json",
"Content-Type": "application/json",
},
});
return res.data.prepay_id;
} catch (error) {
return error.response.request.data;
}
}
4、生成拉起支付需要的支付参数
createPaySign() {
let timeStamp = Math.floor(new Date().getTime() / 1000).toString();
let nonceStr = generateNonceStr(32);
let signStr = `${appid}\n${timeStamp}\n${nonceStr}\nprepay_id=${this.prepay_id}\n`;
let cert = fs.readFileSync("./utils/cert/apiclient_key.pem", "utf-8");
let sign = crypto.createSign("RSA-SHA256");
sign.update(signStr);
this.paySign = {
paySign: sign.sign(cert, "base64"),
timestamp: timeStamp,
nonce_str: nonceStr,
signType: "RSA",
package: "prepay_id=" + this.prepay_id,
};
}
5、返回支付参数给前端
app.post("/weapp/pay/login", jsonParser, async (req, res) => {
// 接收的前端数据
const { code, order } = req.body;
const openid = await getOpenId(code);
const weappPayApi_v3 = new WeappPayApi_v3(openid, order);
await weappPayApi_v3.getPrepayInfo();
weappPayApi_v3.createPaySign();
res.send({ data: weappPayApi_v3.paySign, success: true });
});
6、完成!如果需要demo代码可以点击下面的链接
https://download.csdn.net/download/lcc2001/89335765