Files
junhong_cmp_fiber/docs/wechat-integration/API文档.md
2026-01-30 17:25:30 +08:00

565 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 微信集成 API 文档
本文档详细说明微信 OAuth 登录和微信支付相关的 API 接口。
## 目录
- [认证说明](#认证说明)
- [错误码](#错误码)
- [API 接口](#api-接口)
- [1. 微信 OAuth 登录](#1-微信-oauth-登录)
- [2. 绑定微信账号](#2-绑定微信账号)
- [3. 微信 JSAPI 支付](#3-微信-jsapi-支付)
- [4. 微信 H5 支付](#4-微信-h5-支付)
- [5. 微信支付回调](#5-微信支付回调)
---
## 认证说明
### 公开接口
以下接口无需认证,可直接调用:
- `POST /api/c/v1/wechat/auth` - 微信 OAuth 登录
- `POST /api/callback/wechat-pay` - 微信支付回调
### 需要认证的接口
以下接口需要在请求头中携带 JWT Token
```
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```
- `POST /api/c/v1/bind-wechat` - 绑定微信账号(个人客户)
- `POST /api/h5/orders/:id/wechat-pay/jsapi` - 微信 JSAPI 支付H5认证
- `POST /api/h5/orders/:id/wechat-pay/h5` - 微信 H5 支付H5认证
---
## 错误码
微信集成相关的错误码:
| 错误码 | 说明 | HTTP 状态码 |
|--------|------|-------------|
| 1044 | 微信 OAuth 授权失败 | 400 |
| 1045 | 获取微信用户信息失败 | 400 |
| 1046 | 微信支付失败 | 400 |
| 1047 | 微信支付回调数据无效 | 400 |
| 1003 | 参数无效 | 400 |
| 1020 | 手机号已被使用 | 400 |
| 1021 | 个人客户不存在 | 404 |
| 1035 | 订单不存在 | 404 |
---
## API 接口
### 1. 微信 OAuth 登录
通过微信授权码登录或创建账号。如果用户首次登录,系统会自动创建账号。
**接口地址**
```
POST /api/c/v1/wechat/auth
```
**请求参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| code | string | ✅ | 微信授权码5分钟有效期一次性使用 |
**请求示例**
```json
{
"code": "071abc123456789def"
}
```
**响应参数**
| 参数 | 类型 | 说明 |
|------|------|------|
| code | integer | 响应码0表示成功 |
| msg | string | 响应消息 |
| data | object | 响应数据 |
| data.token | string | JWT Token用于后续请求认证 |
| data.customer_id | integer | 个人客户ID |
| data.phone | string | 手机号(未绑定时为空) |
| data.nickname | string | 昵称(微信昵称) |
| data.is_new_user | boolean | 是否新用户 |
| timestamp | string | 响应时间戳RFC3339格式 |
**响应示例**
```json
{
"code": 0,
"msg": "登录成功",
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjdXN0b21lcl9pZCI6MTIzLCJleHAiOjE3MDY2OTI4MDB9.abc123def456",
"customer_id": 123,
"phone": "138****8888",
"nickname": "微信用户",
"is_new_user": false
},
"timestamp": "2025-01-30T12:00:00+08:00"
}
```
**错误响应**
```json
{
"code": 1044,
"msg": "微信 OAuth 授权失败",
"timestamp": "2025-01-30T12:00:00+08:00"
}
```
**业务逻辑**
1. 验证授权码是否有效
2. 调用微信API获取用户 OpenID 和 UnionID
3. 查找数据库是否存在该微信用户:
- **存在**:返回已有账号的 Token
- **不存在**:创建新账号,返回新账号的 Token
4. 新用户状态为"未绑定手机号",后续需要绑定手机号才能使用完整功能
**注意事项**
- 授权码code只能使用一次重复使用会失败
- 授权码有效期为5分钟
- Token 有效期为7天
- 新用户首次登录时 `phone` 字段为空,需要引导绑定手机号
---
### 2. 绑定微信账号
将当前登录的个人客户账号绑定到微信。
**接口地址**
```
POST /api/c/v1/bind-wechat
```
**认证方式**
需要携带 JWT Token个人客户
**请求参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| code | string | ✅ | 微信授权码 |
**请求示例**
```json
{
"code": "071abc123456789def"
}
```
**响应参数**
| 参数 | 类型 | 说明 |
|------|------|------|
| code | integer | 响应码0表示成功 |
| msg | string | 响应消息 |
| timestamp | string | 响应时间戳 |
**响应示例**
```json
{
"code": 0,
"msg": "绑定成功",
"timestamp": "2025-01-30T12:00:00+08:00"
}
```
**错误响应**
```json
{
"code": 1020,
"msg": "该微信号已被其他账号绑定",
"timestamp": "2025-01-30T12:00:00+08:00"
}
```
**业务逻辑**
1. 验证授权码是否有效
2. 获取微信 OpenID 和 UnionID
3. 检查该微信号是否已被其他账号绑定
4. 更新当前账号的微信绑定信息
**注意事项**
- 一个微信号只能绑定一个账号
- 绑定后无法解绑(需联系管理员)
- 绑定成功后,可以使用微信登录
---
### 3. 微信 JSAPI 支付
创建微信 JSAPI 支付订单(微信内网页支付)。
**接口地址**
```
POST /api/h5/orders/:id/wechat-pay/jsapi
```
**认证方式**
需要携带 H5 Token。
**路径参数**
| 参数 | 类型 | 说明 |
|------|------|------|
| id | integer | 订单ID |
**请求参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| open_id | string | ✅ | 用户的微信 OpenID在公众号内获取 |
**请求示例**
```json
{
"open_id": "o6_bmjrPTlm6_2sgVt7hMZOPfL2M"
}
```
**响应参数**
| 参数 | 类型 | 说明 |
|------|------|------|
| code | integer | 响应码0表示成功 |
| msg | string | 响应消息 |
| data | object | 响应数据 |
| data.prepay_id | string | 预支付交易会话标识 |
| data.pay_config | object | 支付配置直接传给微信JSAPI |
| data.pay_config.appId | string | 公众号AppID |
| data.pay_config.timeStamp | string | 时间戳 |
| data.pay_config.nonceStr | string | 随机字符串 |
| data.pay_config.package | string | 订单详情扩展字符串 |
| data.pay_config.signType | string | 签名方式RSA |
| data.pay_config.paySign | string | 签名 |
| timestamp | string | 响应时间戳 |
**响应示例**
```json
{
"code": 0,
"msg": "支付订单创建成功",
"data": {
"prepay_id": "wx30123456789012345678901234567890",
"pay_config": {
"appId": "wxabcdef1234567890",
"timeStamp": "1706606400",
"nonceStr": "5K8264ILTKCH16CQ2502SI8ZNMTM67VS",
"package": "prepay_id=wx30123456789012345678901234567890",
"signType": "RSA",
"paySign": "oR9d8PuhnIc+YZ8cBHFCwfgpaK9gd7JS..."
}
},
"timestamp": "2025-01-30T12:00:00+08:00"
}
```
**错误响应**
```json
{
"code": 1035,
"msg": "订单不存在",
"timestamp": "2025-01-30T12:00:00+08:00"
}
```
**业务逻辑**
1. 验证订单是否存在且状态为"待支付"
2. 验证订单归属(只能支付自己的订单)
3. 调用微信支付API创建预支付订单
4. 生成支付配置(包含签名)
5. 返回支付配置给前端
**前端调用示例**
```javascript
// 获取支付配置
const res = await fetch(`/api/h5/orders/${orderId}/wechat-pay/jsapi`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${h5Token}`
},
body: JSON.stringify({ open_id: openId })
});
const result = await res.json();
// 调用微信JSAPI支付
wx.chooseWXPay({
...result.data.pay_config,
success: function(res) {
console.log('支付成功', res);
},
fail: function(res) {
console.log('支付失败', res);
}
});
```
**注意事项**
- 只能在微信内网页中使用
- OpenID 需要通过公众号 OAuth 获取
- 支付有效期为2小时
- 订单只能支付一次
---
### 4. 微信 H5 支付
创建微信 H5 支付订单(微信外浏览器支付)。
**接口地址**
```
POST /api/h5/orders/:id/wechat-pay/h5
```
**认证方式**
需要携带 H5 Token。
**路径参数**
| 参数 | 类型 | 说明 |
|------|------|------|
| id | integer | 订单ID |
**请求参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| scene_info | object | ❌ | 场景信息 |
| scene_info.payer_client_ip | string | ❌ | 用户客户端IP |
| scene_info.h5_type | string | ❌ | H5类型Wap/IOS/Android |
**请求示例**
```json
{
"scene_info": {
"payer_client_ip": "123.12.12.123",
"h5_type": "Wap"
}
}
```
**响应参数**
| 参数 | 类型 | 说明 |
|------|------|------|
| code | integer | 响应码0表示成功 |
| msg | string | 响应消息 |
| data | object | 响应数据 |
| data.h5_url | string | H5 支付跳转链接 |
| timestamp | string | 响应时间戳 |
**响应示例**
```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"
}
```
**前端调用示例**
```javascript
// 创建 H5 支付订单
const res = await fetch(`/api/h5/orders/${orderId}/wechat-pay/h5`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${h5Token}`
},
body: JSON.stringify({
scene_info: {
payer_client_ip: clientIp,
h5_type: 'Wap'
}
})
});
const result = await res.json();
// 跳转到微信 H5 支付页面
if (result.code === 0) {
const returnUrl = encodeURIComponent(`https://your-domain.com/orders/${orderId}`);
window.location.href = `${result.data.h5_url}&redirect_url=${returnUrl}`;
}
```
**注意事项**
- 适用于微信外浏览器
- 支付完成后会跳转到 `redirect_url`需URL编码
- 支付有效期为5分钟
- 需要在微信商户平台配置 H5 支付域名
---
### 5. 微信支付回调
接收微信支付的异步通知。
**接口地址**
```
POST /api/callback/wechat-pay
```
**认证方式**
无需认证(由微信签名验证)。
**请求说明**
该接口由微信支付系统调用,开发者无需主动调用。
**请求头**
| 参数 | 说明 |
|------|------|
| Wechatpay-Serial | 微信支付平台证书序列号 |
| Wechatpay-Signature | 微信签名 |
| Wechatpay-Timestamp | 微信时间戳 |
| Wechatpay-Nonce | 微信随机串 |
**请求体**
微信发送的加密数据JSON格式
**响应**
成功处理返回 HTTP 200
```json
{
"code": "SUCCESS",
"message": "成功"
}
```
失败返回 HTTP 500
```json
{
"code": "FAIL",
"message": "失败原因"
}
```
**处理流程**
1. 验证微信签名PowerWeChat 自动处理)
2. 解密通知数据
3. 提取支付结果(交易状态、金额、订单号等)
4. 更新订单状态为"已支付"
5. 触发异步任务:
- 分佣计算
- 套餐分配
- 钱包充值
6. 返回成功响应给微信
**幂等性保证**
系统会检查订单状态,避免重复处理:
- 如果订单已支付,直接返回成功
- 如果订单不存在,返回失败
- 使用数据库事务确保原子性
**重试机制**
微信会在以下情况重试:
- 商户系统未返回响应
- 返回 HTTP 状态码不是 200
- 返回结果为 FAIL
重试规则:
- 15秒后第1次重试
- 30秒后第2次重试
- 3分钟后第3次重试
- 最多重试3次
**注意事项**
- 接口必须在 **10秒内** 返回响应
- 必须返回正确的 JSON 格式
- 签名验证失败会记录日志但不影响服务
- 处理失败会自动重试,无需手动干预
---
## 测试建议
### 开发环境测试
1. **OAuth 登录测试**
- 使用微信测试号(公众号测试账号)
- 在本地配置内网穿透ngrok、frp等
- 测试授权流程和账号创建
2. **支付功能测试**
- 使用 0.01 元小额订单测试
- 验证支付流程和回调处理
- 测试完成后可通过退款功能退回
3. **回调测试**
- 使用微信支付沙箱环境(需申请)
- 或者使用 Postman 模拟回调请求
- 验证幂等性和重试机制
### 生产环境测试
1. 使用真实商户号和公众号
2. 配置正确的 HTTPS 域名
3. 小额订单测试(建议 0.01 元)
4. 监控日志确认回调正常
---
## 相关文档
- [使用指南](./使用指南.md) - 详细的配置和部署说明
- [环境变量配置](../environment-variables.md) - 所有环境变量说明
- [README](../../README.md) - 项目整体说明