Skip to content

微信支付(Node 版本)

下面是基于微信支付 v3(适用于小程序)的完整实现,包括:

  • ✅ Node.js 后端(使用 wechatpay-node-v3 官方 SDK)
  • ✅ uniapp + Vue3 前端模板

🔧 一、Node.js 后端(微信小程序支付)

1. 安装依赖

bash
npm install wechatpay-node-v3 axios koa koa-router koa-bodyparser

2. 项目结构建议

.
├── app.js                // Koa 启动文件
├── routes/pay.js         // 支付路由
├── utils/wechat.js       // 微信支付相关封装
├── cert/
│   ├── apiclient_key.pem     // 商户私钥
│   └── apiclient_cert.pem    // 商户证书(可选)

3. 微信支付工具类 utils/wechat.js

js
const fs = require("fs");
const { WechatPay } = require("wechatpay-node-v3");

const pay = new WechatPay({
  appid: "你的小程序AppID",
  mchid: "你的商户号",
  privateKey: fs.readFileSync("./cert/apiclient_key.pem"),
  certs: {
    序列号: fs.readFileSync("./cert/平台证书.pem"), // 可选,如果做验签用
  },
});

module.exports = pay;

4. 支付接口 routes/pay.js

js
const Router = require("koa-router");
const pay = require("../utils/wechat");
const crypto = require("crypto");

const router = new Router();

router.post("/wxpay/createOrder", async (ctx) => {
  const { openid, amount, description } = ctx.request.body;

  const outTradeNo = "ORDER" + Date.now();

  const result = await pay.transactions_jsapi({
    description,
    out_trade_no: outTradeNo,
    notify_url: "https://yourdomain.com/wxpay/notify",
    amount: {
      total: amount, // 单位:分
      currency: "CNY",
    },
    payer: {
      openid,
    },
  });

  const prepay_id = result.prepay_id;
  const timeStamp = Math.floor(Date.now() / 1000).toString();
  const nonceStr = crypto.randomBytes(16).toString("hex");
  const packageStr = `prepay_id=${prepay_id}`;
  const signType = "RSA";

  const message = `${ctx.appid}\n${timeStamp}\n${nonceStr}\n${packageStr}\n`;
  const sign = crypto.createSign("RSA-SHA256");
  sign.update(message);
  const paySign = sign.sign(
    fs.readFileSync("./cert/apiclient_key.pem"),
    "base64"
  );

  ctx.body = {
    timeStamp,
    nonceStr,
    packageStr,
    signType,
    paySign,
  };
});

module.exports = router;

5. 启动 Koa 应用 app.js

js
const Koa = require("koa");
const bodyParser = require("koa-bodyparser");
const payRouter = require("./routes/pay");

const app = new Koa();
app.use(bodyParser());
app.use(payRouter.routes());

app.listen(3000, () => {
  console.log("Server running on http://localhost:3000");
});

📱 二、uniapp + Vue3 前端模板

1. 页面结构 pages/pay.vue

vue
<template>
  <view class="container">
    <button @click="doPay">微信支付</button>
  </view>
</template>

<script setup>
import { ref } from "vue";

const doPay = async () => {
  // 1. 获取code
  const loginRes = await uni.login();
  const code = loginRes.code;

  // 2. 用 code 换 openid(假设后端封装了)
  const openidRes = await uni.request({
    url: "https://your.api.com/user/openid",
    method: "POST",
    data: { code },
  });
  const openid = openidRes.data.openid;

  // 3. 创建订单并支付
  const res = await uni.request({
    url: "https://your.api.com/wxpay/createOrder",
    method: "POST",
    data: {
      openid,
      amount: 1,
      description: "测试商品",
    },
  });

  const { timeStamp, nonceStr, packageStr, signType, paySign } = res.data;

  uni.requestPayment({
    provider: "wxpay",
    timeStamp,
    nonceStr,
    package: packageStr,
    signType,
    paySign,
    success: function (res) {
      uni.showToast({ title: "支付成功" });
    },
    fail: function (err) {
      uni.showToast({ title: "支付失败", icon: "error" });
      console.error(err);
    },
  });
};
</script>

🔐 三、安全注意事项

  • 商户私钥、API 证书千万不要泄露
  • 使用 HTTPS 接收微信支付回调(notify_url
  • 订单应在数据库中创建并维护状态
  • 回调时需验证签名再处理业务

🧩 四、补充:获取 openid 接口(可选)

后端通过 wx.login() 拿到 code 后请求:

js
https://api.weixin.qq.com/sns/jscode2session?appid=xxx&secret=xxx&js_code=code&grant_type=authorization_code

你可以将其封装在一个 /user/openid 接口里,返回 openid 给前端使用。