# 微信集成功能验证指南

本文档提供微信公众号 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) - 所有环境变量说明
