# 微信集成功能验证指南 本文档提供微信公众号 OAuth 认证和微信支付功能的完整验证流程。 ## 目录 - [前置准备](#前置准备) - [配置验证](#配置验证) - [功能测试](#功能测试) - [1. 微信 OAuth 登录](#1-微信-oauth-登录) - [2. 微信账号绑定](#2-微信账号绑定) - [3. 微信 JSAPI 支付](#3-微信-jsapi-支付) - [4. 微信 H5 支付](#4-微信-h5-支付) - [5. 支付回调验证](#5-支付回调验证) - [常见问题排查](#常见问题排查) --- ## 前置准备 ### 1. 微信配置准备 确保已获取以下信息: **公众号配置**: - [ ] AppID - [ ] AppSecret - [ ] OAuth 回调域名已配置(在公众号后台) **支付配置**: - [ ] 商户号 - [ ] APIv3 密钥(32位) - [ ] 商户证书文件(apiclient_cert.pem) - [ ] 商户私钥文件(apiclient_key.pem) - [ ] 证书序列号 - [ ] 支付回调 URL 已配置(在商户平台) ### 2. 环境准备 ```bash # 创建证书目录 mkdir -p /app/certs # 复制证书文件 cp apiclient_cert.pem /app/certs/ cp apiclient_key.pem /app/certs/ # 设置文件权限 chmod 600 /app/certs/* # 加载环境变量 source .env.local ``` ### 3. 启动服务 ```bash # 编译并启动 go run cmd/api/main.go # 或使用 Docker docker-compose up -d api ``` --- ## 配置验证 ### 自动验证脚本 运行配置验证脚本: ```bash # 加载环境变量 source .env.local # 运行验证脚本 bash scripts/verify-wechat.sh ``` **预期输出**(所有检查通过): ``` ======================================== 微信配置验证脚本 ======================================== 1. 检查微信公众号配置 ---------------------------------------- ✓ JUNHONG_WECHAT_OFFICIAL_ACCOUNT_APP_ID ✓ JUNHONG_WECHAT_OFFICIAL_ACCOUNT_APP_SECRET ✓ JUNHONG_WECHAT_OFFICIAL_ACCOUNT_TOKEN ✓ JUNHONG_WECHAT_OFFICIAL_ACCOUNT_AES_KEY ✓ JUNHONG_WECHAT_OFFICIAL_ACCOUNT_OAUTH_REDIRECT_URL 2. 检查微信支付配置 ---------------------------------------- ✓ JUNHONG_WECHAT_PAYMENT_APP_ID ✓ JUNHONG_WECHAT_PAYMENT_MCH_ID ✓ JUNHONG_WECHAT_PAYMENT_API_V3_KEY ✓ JUNHONG_WECHAT_PAYMENT_CERT_PATH ✓ JUNHONG_WECHAT_PAYMENT_KEY_PATH ✓ JUNHONG_WECHAT_PAYMENT_SERIAL_NO ✓ JUNHONG_WECHAT_PAYMENT_NOTIFY_URL 3. 检查证书文件 ---------------------------------------- ✓ 文件存在: /app/certs/apiclient_cert.pem ✓ 文件存在: /app/certs/apiclient_key.pem 4. 验证配置格式 ---------------------------------------- ✓ 支付回调 URL 使用 HTTPS 5. 检查证书有效性(可选) ---------------------------------------- ✓ 证书有效期至: Jan 30 12:00:00 2026 GMT ✓ 证书序列号匹配 ======================================== 验证结果 ======================================== 错误: 0 警告: 0 ✅ 配置验证通过,所有配置正确 ``` ### 查看服务启动日志 ```bash # 查看实时日志 tail -f logs/app.log # 或使用 Docker docker logs -f junhong-api ``` **预期日志**(成功初始化): ```json { "level": "info", "ts": "2025-01-30T12:00:00.000+0800", "msg": "微信公众号服务初始化成功" } { "level": "info", "ts": "2025-01-30T12:00:00.001+0800", "msg": "微信支付服务初始化成功" } { "level": "info", "ts": "2025-01-30T12:00:00.002+0800", "msg": "服务启动成功", "address": ":3000" } ``` **错误日志**(配置问题): ```json { "level": "fatal", "ts": "2025-01-30T12:00:00.000+0800", "msg": "微信配置不完整或无效", "error": "证书文件不存在: /app/certs/apiclient_cert.pem" } ``` --- ## 功能测试 ### 1. 微信 OAuth 登录 #### 前端测试步骤 **步骤 1:构造授权 URL** ```javascript const appId = 'wxabcdef1234567890'; const redirectUri = encodeURIComponent('https://your-domain.com/wechat-callback'); const state = Math.random().toString(36).substring(7); const authUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${redirectUri}&response_type=code&scope=snsapi_userinfo&state=${state}#wechat_redirect`; // 跳转到微信授权页面 window.location.href = authUrl; ``` **步骤 2:处理回调** 在回调页面(`https://your-domain.com/wechat-callback`): ```javascript // 获取 URL 参数中的 code const urlParams = new URLSearchParams(window.location.search); const code = urlParams.get('code'); const state = urlParams.get('state'); if (!code) { alert('授权失败:未获取到授权码'); return; } // 调用后端 OAuth 登录接口 fetch('https://api.your-domain.com/api/c/v1/wechat/auth', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ code }) }) .then(res => res.json()) .then(data => { if (data.code === 0) { console.log('登录成功', data.data); localStorage.setItem('token', data.data.token); // 跳转到主页 window.location.href = '/'; } else { alert(`登录失败: ${data.msg}`); } }) .catch(err => { console.error('请求失败', err); alert('登录失败,请重试'); }); ``` #### 后端日志验证 ```bash # 查看 OAuth 请求日志 tail -f logs/app.log | grep -i oauth ``` **成功日志**: ```json { "level": "debug", "ts": "2025-01-30T12:00:00.000+0800", "msg": "微信 OAuth 授权成功", "open_id": "o6_bmjrPTlm6_2sgVt7hMZOPfL2M", "union_id": "oGfRjwX..." } { "level": "info", "ts": "2025-01-30T12:00:00.001+0800", "msg": "个人客户创建成功", "customer_id": 123 } ``` **失败日志**: ```json { "level": "error", "ts": "2025-01-30T12:00:00.000+0800", "msg": "微信 OAuth 授权失败", "code": "071abc123...", "error": "invalid code" } ``` #### 使用 curl 测试 ```bash # 替换为真实的授权码(5分钟有效) CODE="071abc123456789def" curl -X POST http://localhost:3000/api/c/v1/wechat/auth \ -H "Content-Type: application/json" \ -d "{\"code\":\"$CODE\"}" ``` **成功响应**: ```json { "code": 0, "msg": "登录成功", "data": { "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "customer_id": 123, "phone": "", "nickname": "微信用户", "is_new_user": true }, "timestamp": "2025-01-30T12:00:00+08:00" } ``` --- ### 2. 微信账号绑定 #### 前提条件 - 已有个人客户账号 - 已获取 JWT Token #### 测试步骤 ```bash # 替换为真实的 Token 和授权码 TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." CODE="071abc123456789def" curl -X POST http://localhost:3000/api/c/v1/bind-wechat \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d "{\"code\":\"$CODE\"}" ``` **成功响应**: ```json { "code": 0, "msg": "绑定成功", "timestamp": "2025-01-30T12:00:00+08:00" } ``` **失败响应**(微信号已被绑定): ```json { "code": 1020, "msg": "该微信号已被其他账号绑定", "timestamp": "2025-01-30T12:00:00+08:00" } ``` --- ### 3. 微信 JSAPI 支付 #### 前提条件 - 已创建订单(状态为"待支付") - 在微信内网页中调用 - 已获取用户 OpenID #### 测试步骤 **步骤 1:创建支付订单** ```bash # 替换为真实的 Token、订单ID 和 OpenID H5_TOKEN="your_h5_token_here" ORDER_ID=1 OPEN_ID="o6_bmjrPTlm6_2sgVt7hMZOPfL2M" curl -X POST "http://localhost:3000/api/h5/orders/$ORDER_ID/wechat-pay/jsapi" \ -H "Authorization: Bearer $H5_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"open_id\":\"$OPEN_ID\"}" ``` **成功响应**: ```json { "code": 0, "msg": "支付订单创建成功", "data": { "prepay_id": "wx30123456789012345678901234567890", "pay_config": { "appId": "wxabcdef1234567890", "timeStamp": "1706606400", "nonceStr": "5K8264ILTKCH16CQ2502SI8ZNMTM67VS", "package": "prepay_id=wx30123456789012345678901234567890", "signType": "RSA", "paySign": "oR9d8PuhnIc+YZ8cBHFCwfgpaK9gd..." } }, "timestamp": "2025-01-30T12:00:00+08:00" } ``` **步骤 2:前端唤起支付** ```javascript // 获取支付配置后,调用微信 JSAPI wx.chooseWXPay({ ...payConfig, success: function(res) { console.log('支付成功', res); alert('支付成功'); // 跳转到订单详情页 window.location.href = `/orders/${orderId}`; }, fail: function(res) { console.error('支付失败', res); alert('支付失败:' + res.err_msg); } }); ``` #### 后端日志验证 ```bash # 查看支付请求日志 tail -f logs/app.log | grep -i jsapi ``` **成功日志**: ```json { "level": "info", "ts": "2025-01-30T12:00:00.000+0800", "msg": "创建 JSAPI 支付订单成功", "order_no": "ORDER_20250130_001", "prepay_id": "wx30123456789012345678901234567890" } ``` --- ### 4. 微信 H5 支付 #### 前提条件 - 已创建订单(状态为"待支付") - 在浏览器中调用(微信外) #### 测试步骤 **步骤 1:创建 H5 支付订单** ```bash # 替换为真实的 Token 和订单ID H5_TOKEN="your_h5_token_here" ORDER_ID=1 curl -X POST "http://localhost:3000/api/h5/orders/$ORDER_ID/wechat-pay/h5" \ -H "Authorization: Bearer $H5_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "scene_info": { "payer_client_ip": "123.12.12.123", "h5_type": "Wap" } }' ``` **成功响应**: ```json { "code": 0, "msg": "H5 支付订单创建成功", "data": { "h5_url": "https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx30123456789012345678901234567890&package=3583359058" }, "timestamp": "2025-01-30T12:00:00+08:00" } ``` **步骤 2:前端跳转支付** ```javascript // 跳转到微信 H5 支付页面 const returnUrl = encodeURIComponent(`https://your-domain.com/orders/${orderId}`); window.location.href = `${h5Url}&redirect_url=${returnUrl}`; ``` #### 后端日志验证 ```bash # 查看 H5 支付日志 tail -f logs/app.log | grep -i "h5" ``` **成功日志**: ```json { "level": "info", "ts": "2025-01-30T12:00:00.000+0800", "msg": "创建 H5 支付订单成功", "order_no": "ORDER_20250130_001", "h5_url": "https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?..." } ``` --- ### 5. 支付回调验证 #### 验证方法1:查看日志 支付成功后,微信会自动调用回调接口。查看日志验证: ```bash # 查看支付回调日志 tail -f logs/app.log | grep -i "支付通知" ``` **成功日志**: ```json { "level": "info", "ts": "2025-01-30T12:00:00.000+0800", "msg": "支付通知处理成功", "out_trade_no": "ORDER_20250130_001", "transaction_id": "4200001234202501301234567890" } ``` #### 验证方法2:查询订单状态 ```bash # 查询订单状态(使用数据库或 API) curl -X GET "http://localhost:3000/api/h5/orders/$ORDER_ID" \ -H "Authorization: Bearer $H5_TOKEN" ``` **预期响应**(订单已支付): ```json { "code": 0, "data": { "id": 1, "order_no": "ORDER_20250130_001", "status": "paid", "total_amount": 100, "paid_amount": 100, "paid_at": "2025-01-30T12:00:00+08:00", "payment_method": "wechat" } } ``` #### 验证方法3:使用 Postman 模拟回调 **注意**:真实环境中由微信服务器调用,本地测试需要跳过签名验证。 ```bash # 模拟支付回调(仅测试环境) curl -X POST http://localhost:3000/api/callback/wechat-pay \ -H "Content-Type: application/json" \ -d '{ "id": "test_id", "create_time": "2025-01-30T12:00:00+08:00", "resource_type": "encrypt-resource", "event_type": "TRANSACTION.SUCCESS", "summary": "支付成功", "resource": { "ciphertext": "...", "nonce": "...", "associated_data": "..." } }' ``` --- ## 常见问题排查 ### 1. 配置验证失败 **问题**:脚本报错 "缺失必填配置" **解决方法**: ```bash # 检查环境变量是否加载 env | grep JUNHONG_WECHAT # 重新加载环境变量 source .env.local # 重新运行验证脚本 bash scripts/verify-wechat.sh ``` ### 2. 服务启动失败 **问题**:日志显示 "微信配置不完整或无效" **解决方法**: 1. 查看详细错误日志 2. 检查证书文件路径是否正确 3. 验证证书文件权限(600 或 644) 4. 确认 APIv3 密钥长度为 32 位 ### 3. OAuth 授权失败 **问题**:返回错误码 1044 **可能原因**: - 授权码已过期(5分钟有效期) - 授权码已被使用过 - AppID 或 AppSecret 配置错误 - 回调域名未在公众号后台配置 **解决方法**: 1. 重新发起授权流程获取新 code 2. 检查公众号配置 3. 查看详细日志:`tail -f logs/app.log | grep -i oauth` ### 4. 支付订单创建失败 **问题**:返回错误码 1046 **可能原因**: - 商户号配置错误 - 证书文件无效或过期 - APIv3 密钥错误 - 订单金额为0或负数 **解决方法**: 1. 验证商户号和密钥 2. 检查证书有效期:`openssl x509 -in /app/certs/apiclient_cert.pem -noout -dates` 3. 确认证书序列号匹配 4. 查看详细日志:`tail -f logs/app.log | grep -i payment` ### 5. 支付回调签名验证失败 **问题**:日志显示 "支付回调签名验证失败" **可能原因**: - 证书配置错误 - 证书序列号不匹配 - 证书已过期 **解决方法**: 1. 重新下载最新的商户证书 2. 更新证书序列号配置 3. 确保证书文件路径正确 4. 验证证书:`bash scripts/verify-wechat.sh` ### 6. 启用调试日志 如需查看详细的 HTTP 请求日志: ```bash # 设置环境变量 export JUNHONG_WECHAT_PAYMENT_HTTP_DEBUG=true # 重启服务 go run cmd/api/main.go # 查看调试日志 tail -f logs/app.log | grep -i wechat ``` --- ## 验证清单 完成以下清单后,微信集成功能验证完成: - [ ] 配置验证脚本通过(0 错误) - [ ] 服务启动成功,微信服务初始化日志正常 - [ ] 微信 OAuth 登录成功,返回 Token - [ ] 微信账号绑定成功 - [ ] JSAPI 支付订单创建成功,返回支付配置 - [ ] H5 支付订单创建成功,返回支付 URL - [ ] 支付回调处理成功,订单状态更新为"已支付" - [ ] 日志中无错误或警告信息 --- ## 相关文档 - [使用指南](./使用指南.md) - 详细的配置和部署说明 - [API 文档](./API文档.md) - 接口说明和示例 - [环境变量配置](../environment-variables.md) - 所有环境变量说明