小程序登录与支付封装
一套可直接复用的小程序登录与支付封装:前端会话管理、后端 code2session、统一下单签名、回调验签。
代码示例:登录封装(小程序端)
js
// utils/auth.js —— 微信小程序登录态封装
const request = require("./request");
function login() {
return new Promise((resolve, reject) => {
wx.login({
success: (res) => {
if (!res.code) return reject(new Error("login failed"));
// 把临时 code 交给后端换 openid + session_key
request.post("/api/auth/code2session", { code: res.code })
.then((data) => {
wx.setStorageSync("token", data.token);
resolve(data);
})
.catch(reject);
},
fail: reject
});
});
}
function checkSession() {
// 检查会话是否过期,过期则静默重新登录
wx.checkSession({
fail: () => login()
});
}
module.exports = { login, checkSession };
js
// 后端 routes/auth.js —— Node.js + Express
const axios = require("axios");
const crypto = require("crypto");
const jwt = require("jsonwebtoken");
const APPID = process.env.WX_APPID;
const SECRET = process.env.WX_SECRET;
router.post("/code2session", async (req, res) => {
const { code } = req.body;
const url = `https://api.weixin.qq.com/sns/jscode2session` +
`?appid=${APPID}&secret=${SECRET}&js_code=${code}&grant_type=authorization_code`;
const { data } = await axios.get(url);
if (!data.openid) return res.status(400).json({ error: "code expired" });
// 签发业务 token(勿把 session_key 下发前端)
const token = jwt.sign({ openid: data.openid }, process.env.JWT_SECRET, {
expiresIn: "7d"
});
res.json({ token });
});
js
// 后端支付下单(统一下单 + 签名)
function buildPayParams(openid, orderId, totalFee, body) {
const params = {
appid: APPID,
mch_id: MCH_ID,
nonce_str: crypto.randomBytes(8).toString("hex"),
body,
out_trade_no: orderId,
total_fee: totalFee, // 单位:分
spbill_create_ip: "127.0.0.1",
notify_url: NOTIFY_URL,
trade_type: "JSAPI",
openid
};
// 按 key 升序拼接 + 商户密钥,MD5 签名
const signStr = Object.keys(params).sort()
.map(k => `${k}=${params[k]}`).join("&") + `&key=${MCH_KEY}`;
params.sign = crypto.createHash("md5").update(signStr).digest("hex");
return params;
}
// 回调验签后再标记订单已支付,防止伪造回调
操作步骤
- 小程序端调用
wx.login获取临时 code,回传后端。 - 后端用
appid + secret调code2session换 openid/session_key,签发自定义 token。 - 支付:后端统一下单拿到
payParams,前端wx.requestPayment拉起收银台。 - 回调验签后再发货:只信任
transaction_id + 金额匹配的支付回调。
来源参考
GitHub 关键词:miniprogram-login、wechat-pay-node、wxapp-oauth(链接可替换为实际仓库地址)。