微信支付(Node 版本)
下面是基于微信支付 v3(适用于小程序)的完整实现,包括:
- ✅ Node.js 后端(使用
wechatpay-node-v3官方 SDK) - ✅ uniapp + Vue3 前端模板
🔧 一、Node.js 后端(微信小程序支付)
1. 安装依赖
bash
npm install wechatpay-node-v3 axios koa koa-router koa-bodyparser2. 项目结构建议
.
├── 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 给前端使用。