从零开始的微信支付 JSAPI 支付接入教程,包含完整的订单管理、支付、退款、回调处理等功能。适合独立开发者快速上手微信支付开发。
一个基于 Go + Gin 的微信支付 JSAPI 支付完整示例项目,支持最新的微信支付公钥模式(2023年后新商户),包含微信网页授权、下单、支付、回调处理等完整流程。
- JSAPI 支付:完整的微信内网页支付流程
- 微信授权:自动获取用户 OpenID(snsapi_base 静默授权)
- 公钥模式:支持 2023 年后新商户的微信支付公钥验签
- 回调处理:支付结果通知验证与处理
- 订单查询:支持主动查询订单状态
| 组件 | 版本 | 说明 |
|---|---|---|
| Go | 1.21+ | 后端语言 |
| Gin | v1.9.1 | Web 框架 |
| WeChat Pay Go SDK | v0.2.21 | 微信支付官方 SDK |
| godotenv | v1.5.1 | 环境变量管理 |
- Go 1.21+ 环境
- 微信支付商户号(支持公钥模式)
- 微信公众号/服务号(已认证)
- 外网可访问的域名
git clone https://github.com/yourusername/wechatpay-jsapi-demo.git
cd wechatpay-jsapi-democp .env.example .env
# 编辑 .env 文件,填入你的配置将你的测试部署域名更新到 .env 的 BASE_URL 和 NOTIFY_URL
同时需要在微信公众平台和商户后台配置该域名
将以下证书文件放入 certs/ 目录:
| 文件 | 说明 | 获取位置 |
|---|---|---|
apiclient_key.pem |
商户 API 私钥 | 微信支付商户平台 → API 安全 → 申请 API 证书 |
wechatpay_pub_key.pem |
微信支付公钥 | 微信支付商户平台 → API 安全 → 微信支付公钥 |
# 安装依赖
go mod tidy
# 开发运行
go run .
# 或构建运行
go build -o wechatpay-demo
./wechatpay-demo服务默认运行在 http://localhost:8080
wechatpay-jsapi-demo/
├── .env.example # 环境变量示例
├── .gitignore # Git 忽略配置
├── go.mod # Go 模块定义
├── go.sum # Go 依赖校验
├── main.go # 应用入口
├── README.md # 项目文档
├── certs/ # 证书目录(不提交到 Git)
│ ├── apiclient_key.pem # 商户私钥
│ └── wechatpay_pub_key.pem # 微信支付公钥
├── config/
│ └── config.go # 配置加载与验证
├── handlers/
│ ├── auth.go # 微信网页授权(获取 OpenID)
│ └── payment.go # 支付相关接口
└── templates/
├── index.html # 商品列表页
├── pay.html # 支付确认页
└── success.html # 支付成功页
编辑 .env 文件,确保以下配置正确:
# ========== 基础配置 ==========
SERVER_PORT=8080
BASE_URL=https://your-domain.com # 外网可访问的 HTTPS 地址
# ========== 微信支付配置 ==========
MCH_ID=1900000000 # 商户号(10位数字)
MCH_API_V3_KEY=YourAPIv3KeyHere # APIv3 密钥(32位)
MCH_CERT_SERIAL_NO=XXXXXXXXXXXXXXXX # 商户证书序列号
MCH_PRIVATE_KEY_PATH=./certs/apiclient_key.pem
# ========== 微信支付公钥配置(新商户必填)==========
WECHAT_PAY_PUBLIC_KEY_ID=PUB_KEY_ID_xxx # 公钥 ID
WECHAT_PAY_PUBLIC_KEY_PATH=./certs/wechatpay_pub_key.pem
# ========== 微信公众号配置 ==========
APP_ID=wx0000000000000000 # 公众号 AppID
APP_SECRET=YourAppSecretHere # 公众号 AppSecret
# ========== 支付配置 ==========
NOTIFY_URL=https://your-domain.com/api/pay/notify # 支付结果通知地址
ORDER_EXPIRE_MINUTES=30 # 订单超时时间(分钟)| 平台 | 配置项 | 值 |
|---|---|---|
| 微信支付商户平台 | JSAPI 支付授权目录 | https://your-domain.com/ |
| 微信支付商户平台 | 支付结果通知 URL | https://your-domain.com/api/pay/notify |
| 微信支付商户平台 | 微信支付公钥 | 下载公钥文件和 ID |
| 微信公众平台 | JS 接口安全域名 | your-domain.com |
| 微信公众平台 | 网页授权域名 | your-domain.com |
用户访问首页
↓
选择商品(0.01元)
↓
点击购买 → 检查 OpenID Cookie
↓
未授权 → 跳转微信授权 → 获取 Code → 换取 OpenID → 存储 Cookie
↓
已授权 → 进入支付确认页(显示 ¥0.01)
↓
点击支付 → 后端创建订单(1分)→ 调用微信预下单
↓
返回 prepay_id 和调起参数 → 前端调起微信支付
↓
用户输入密码 → 支付成功
↓
微信异步通知 → 后端验签 → 更新订单状态
↓
返回支付成功页
| 接口 | 路径 | 说明 |
|---|---|---|
| 商品页 | GET / |
展示商品列表 |
| 授权入口 | GET /auth |
跳转微信授权 |
| 授权回调 | GET /auth/callback |
处理授权回调,获取 OpenID |
| 支付页 | GET /pay |
支付确认页面 |
| 创建订单 | POST /api/pay/create |
创建支付订单,返回调起参数 |
| 支付回调 | POST /api/pay/notify |
微信支付结果通知 |
| 查询订单 | GET /api/order/query |
主动查询订单状态 |
原因:微信授权回调域名配置不正确
解决:
- 检查微信公众平台 → 设置与开发 → 接口权限 → 网页授权获取用户基本信息 → 修改
- 确保配置的域名与
BASE_URL完全一致(不含https://和端口号)
检查清单:
- 商户号已开通 JSAPI 支付产品
- 商户号与 AppID 已绑定(商户平台 → 产品中心 → AppID 账号管理)
- 支付授权目录已配置(商户平台 → 产品中心 → JSAPI 支付 → 支付授权目录)
- 必须使用微信内置浏览器访问
原因:使用了错误的验签方式
解决:
- 2023 年前申请的商户号:使用平台证书模式(
WithWechatPayAutoAuthCipher) - 2023 年后申请的商户号:使用公钥模式(
WithWechatPayPublicKeyAuthCipher)
本项目默认使用公钥模式,如需切换请修改 main.go。
推荐方案:
# 1. 启动 ngrok
ngrok http 8080
# 2. 复制 https 地址(如 https://abc123.ngrok-free.app)
# 3. 更新 .env
BASE_URL=https://abc123.ngrok-free.app
NOTIFY_URL=https://abc123.ngrok-free.app/api/pay/notify
# 4. 更新微信后台配置(JS 接口安全域名、网页授权域名、支付授权目录)
# 5. 链接发到微信后,点击链接在微信中访问测试- HTTPS 强制:生产环境必须全站 HTTPS
- 密钥保护:永远不要将
.env和certs/提交到 Git - 签名验证:回调通知必须验签(本项目已实现)
- 金额校验:本项目为了方便直接前端传递,生成环境不能信任前端参数需后端根据商品信息自行获取金额
- 幂等性处理:同一笔订单的多次回调只处理一次
- 敏感信息加密:如需传输敏感信息,使用微信支付公钥加密
// 已实现的防护措施:
// 1. 回调验签使用 RSANotifyHandler
handler, err := notify.NewRSANotifyHandler(mchAPIv3Key, verifier)
// 2. 订单号唯一性检查(需配合数据库实现)
// 3. 金额范围验证(> 0)
// 4. OpenID 合法性验证(非空检查)注意:本项目仅供学习参考,生产环境使用请根据实际情况完善错误处理、日志记录、数据库操作等。