小程序登录与支付封装

一套可直接复用的小程序登录与支付封装:前端会话管理、后端 code2session、统一下单签名、回调验签。

场景:小程序账号体系 技术栈:微信小程序 / Node.js 来源:GitHub 参考

代码示例:登录封装(小程序端)

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;
}
// 回调验签后再标记订单已支付,防止伪造回调

操作步骤

  1. 小程序端调用 wx.login 获取临时 code,回传后端。
  2. 后端用 appid + secretcode2session 换 openid/session_key,签发自定义 token。
  3. 支付:后端统一下单拿到 payParams,前端 wx.requestPayment 拉起收银台。
  4. 回调验签后再发货:只信任 transaction_id + 金额 匹配的支付回调。

来源参考

GitHub 关键词:miniprogram-loginwechat-pay-nodewxapp-oauth(链接可替换为实际仓库地址)。