fengketrade/doc/ccblife_test_guide.md
2025-10-20 15:29:15 +08:00

745 lines
18 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.

# 建行生活H5商城对接 - 测试指南
> 文档版本: v1.0
> 更新时间: 2025-01-18
> 作者: Billy
---
## 📋 目录
1. [测试概述](#测试概述)
2. [测试环境准备](#测试环境准备)
3. [自动化测试流程](#自动化测试流程)
4. [手动测试流程](#手动测试流程)
5. [常见问题排查](#常见问题排查)
6. [测试检查清单](#测试检查清单)
---
## 测试概述
本测试方案分为两个阶段:
### 🤖 阶段一:模拟测试(当前可用)
**目的**: 在没有建行加密数据的情况下,验证系统核心逻辑是否正确
**范围**:
- ✅ 环境配置检查
- ✅ 数据库表结构验证
- ✅ 用户和订单创建
- ✅ 支付串生成逻辑
- ✅ 支付流水号规则
- ✅ 订单状态更新逻辑
- ✅ 字段映射正确性
**不包含**:
- ❌ 真实RSA加密/解密
- ❌ 真实建行API调用
- ❌ 建行回调签名验证
- ❌ JSBridge通信
### 🌐 阶段二:真实环境测试(需建行配置)
**前提**: 已获得建行提供的测试/生产环境配置
**范围**:
- ✅ 完整RSA加密流程
- ✅ 建行API接口调用
- ✅ 订单同步到建行
- ✅ 建行收银台支付
- ✅ 支付回调验证
- ✅ 异步通知验证
---
## 测试环境准备
### 1. 系统要求
```bash
# 检查PHP版本需要 >= 7.0
php -v
# 检查必需扩展
php -m | grep -E 'openssl|pdo|json|mbstring'
# 检查数据库连接
mysql -h <host> -u <user> -p<password> -e "SELECT VERSION();"
```
### 2. 配置文件检查
确保已创建配置文件:`/application/extra/ccblife.php`
```php
<?php
return [
// 基础配置
'merchant_id' => '***', // 商户代码
'pos_id' => '***', // 柜台代码
'branch_id' => '***', // 分行代码
'service_id' => '***', // 服务方编号
// 密钥配置
'private_key' => '***', // 服务方私钥1024位
'merchant_public_key' => '***', // 商户公钥1024位
// API地址测试环境
'api_url' => 'http://test.ccb.com/api',
'cashier_url' => 'comccbpay://pay',
// 回调地址
'callback_url' => 'https://your-domain.com/addons/shopro/ccbpayment/callback',
'notify_url' => 'https://your-domain.com/addons/shopro/ccbpayment/notify',
];
```
### 3. 数据库表检查
确保已执行以下SQL如未执行
```sql
-- 订单表添加建行支付流水号字段
ALTER TABLE `fa_shopro_order`
ADD COLUMN `ccb_pay_flow_id` VARCHAR(50) NULL DEFAULT NULL COMMENT '建行支付流水号'
AFTER `order_sn`;
-- 用户表添加建行用户ID字段
ALTER TABLE `fa_user`
ADD COLUMN `ccb_user_id` VARCHAR(50) NULL DEFAULT NULL COMMENT '建行用户ID'
AFTER `mobile`;
-- 支付日志表已在install.sql中
-- fa_ccb_payment_log
-- 同步日志表已在install.sql中
-- fa_ccb_sync_log
```
---
## 自动化测试流程
### 运行自动化测试脚本
```bash
cd /Users/billy/Code/fengketrade.com
# 运行完整测试套件
php addons/shopro/test/ccblife_test.php
```
### 预期输出示例
```
========================================
建行生活H5商城对接 - 自动化测试
========================================
测试时间: 2025-01-18 14:30:00
========================================
【环境检查】
✓ PHP版本检查 (7.4.33 >= 7.0)
✓ 检查OpenSSL扩展
✓ 检查PDO扩展
✓ 检查JSON扩展
✓ 检查文件: CcbPaymentService.php
✓ 检查文件: CcbOrderService.php
✓ 检查文件: CcbRSA.php
✓ 检查文件: CcbMD5.php
✓ 检查文件: CcbEncryption.php
【配置文件检查】
✓ 配置文件存在
✓ 商户ID配置
✓ POS ID配置
✓ 分行代码配置
✓ 服务方编号配置
✓ 服务方私钥配置
✓ 商户公钥配置
【数据库表检查】
✓ 检查表: fa_ccb_payment_log
✓ 检查表: fa_ccb_sync_log
✓ 检查表: fa_shopro_order
✓ 检查表: fa_user
✓ 检查订单表ccb_pay_flow_id字段
【创建测试用户】
✓ 用户创建成功 (ID: 123)
【创建测试订单】
✓ 订单创建成功 (ID: 456, SN: SO20250118143000001)
【支付串生成测试】
✓ 支付串生成状态
✓ 支付串不为空
✓ 支付流水号不为空
✓ MAC签名不为空
✓ 支付流水号长度正确 (23位)
✓ 支付流水号前缀正确 (PAY)
✓ 订单表支付流水号已更新
✓ 支付日志已记录
支付串长度: 512 字节
支付流水号: PAY20250118143000123456
MAC签名: a1b2c3d4e5f6...
【支付回调测试】
✓ 回调处理成功
✓ 回调消息正确
✓ 订单状态已更新为已支付
✓ 支付方式正确 (offline代表建行)
✓ 支付时间已记录
✓ 交易单号正确
订单状态: paid
支付时间: 2025-01-18 14:30:05
【异步通知测试】
通知处理结果: fail
✓ 通知处理逻辑测试完成
【订单同步测试】
✓ 订单字段 ORD_NUM 存在
✓ 订单字段 PAY_AMT 存在
✓ 订单字段 ORD_TIME 存在
✓ 订单字段 PAY_TIME 存在
✓ 订单字段 ORD_STATUS 存在
✓ 订单字段 REFUND_STATUS 存在
✓ 订单号正确
✓ 支付金额正确
订单号: SO20250118143000001
支付金额: 100.00
订单状态: 02
【清理测试数据】
✓ 删除测试订单 (ID: 456)
✓ 删除支付日志
✓ 删除测试用户 (ID: 123)
========================================
测试报告
========================================
✓ 通过 环境检查
所有环境检查通过
✓ 通过 配置文件检查
所有配置项完整
✓ 通过 数据库表检查
所有表结构完整
✓ 通过 创建测试用户
用户ID: 123
✓ 通过 创建测试订单
订单ID: 456
✓ 通过 支付串生成测试
支付流水号: PAY20250118143000123456
✓ 通过 支付回调测试
支付回调处理成功
✓ 通过 异步通知测试
通知处理逻辑测试完成
✓ 通过 订单同步测试
订单数据构建正确
✓ 通过 清理测试数据
所有测试数据已清理
========================================
总计: 10 项测试
通过: 10 项
失败: 0 项
耗时: 1.23 秒
========================================
🎉 所有测试通过!系统运行正常。
```
---
## 手动测试流程
### 测试1: 前端环境检测
**目的**: 验证建行生活APP环境识别
**步骤**:
1. 在建行生活APP内打开H5商城链接待建行提供测试链接
2. 打开浏览器控制台
3. 查看输出:
```javascript
// 预期输出
[CcbLife] 初始化完成, 是否在建行App内: true
[CcbLife] JSBridge 已就绪
```
**验证点**:
- `isInCcbApp` 应为 `true`
- `isReady` 应为 `true`
- User-Agent 包含 'ccblife' 或 'ccb'
---
### 测试2: 用户自动登录
**目的**: 验证建行用户自动登录流程
**前提**:
- 测试1通过
- 已在建行APP内打开H5商城
**步骤**:
1. 清除商城登录态:`localStorage.clear()`
2. 刷新页面
3. 观察控制台输出
**预期输出**:
```
[CcbLife] 自动登录成功
```
**验证点**:
- `localStorage.getItem('token')` 不为空
- `localStorage.getItem('userInfo')` 包含用户信息
- 数据库 `fa_user` 表中 `ccb_user_id` 已绑定
---
### 测试3: 创建订单
**目的**: 验证订单创建流程
**步骤**:
1. 选择商品加入购物车
2. 进入结算页
3. 填写收货地址
4. 提交订单
**验证点**:
- 订单创建成功返回订单ID和订单号
- 数据库 `fa_shopro_order` 表中订单状态为 `unpaid`
- `ccb_pay_flow_id` 字段为空
---
### 测试4: 生成支付串
**目的**: 验证支付串生成逻辑
**接口**: `POST /addons/shopro/ccbpayment/pay`
**请求参数**:
```json
{
"order_id": 123
}
```
**预期响应**:
```json
{
"code": 1,
"msg": "支付串生成成功",
"data": {
"payment_string": "MERCHANTID=...&POSID=...&MAC=...",
"payment_url": "comccbpay://pay?MERCHANTID=...&MAC=...",
"mac": "a1b2c3d4e5f6...",
"order_id": 123,
"order_sn": "SO20250118001",
"pay_flow_id": "PAY20250118143000123456",
"amount": "100.00"
}
}
```
**验证点**:
1. `payment_string` 包含所有必需参数
2. `pay_flow_id` 格式正确PAY + 14位时间戳 + 6位随机数
3. `mac` 签名不为空
4. 数据库订单表 `ccb_pay_flow_id` 已更新
5. `fa_ccb_payment_log` 表中已记录支付请求
**关键参数检查**:
```javascript
// 从 payment_string 中提取参数
const params = new URLSearchParams(payment_string);
console.log('ORDERID:', params.get('ORDERID')); // 应等于 pay_flow_id
console.log('USER_ORDERID:', params.get('USER_ORDERID')); // 应等于 order_sn
console.log('PAYMENT:', params.get('PAYMENT')); // 应等于订单实际支付金额
console.log('MAC:', params.get('MAC')); // MD5签名
console.log('PLATFORMID:', params.get('PLATFORMID')); // 服务方编号
```
---
### 测试5: 调起支付(需建行环境)
**目的**: 验证JSBridge调起建行收银台
**前提**:
- 测试1-4全部通过
- 已在建行APP内
**步骤**:
1. 点击"去支付"按钮
2. 前端调用 `CcbLifePlatform.payment()`
**前端代码示例**:
```javascript
// sheep/platform/provider/ccblife/index.js
const paymentResult = await CcbLifePlatform.payment({
payment_string: '支付串内容'
});
console.log('支付结果:', paymentResult);
```
**iOS预期行为**:
- 跳转到 `comccbpay://pay?支付参数`
- 打开建行收银台
**Android预期行为**:
- 调用 `window.mbspay.payment()`
- 打开建行收银台
**验证点**:
- 收银台显示正确的订单金额
- 收银台显示正确的商品信息
---
### 测试6: 支付回调(需建行环境)
**目的**: 验证支付完成后的同步回调
**触发方式**:
- 在建行收银台完成支付(或取消支付)
- 建行会重定向到 `callback_url`
**回调URL示例**:
```
https://your-domain.com/addons/shopro/ccbpayment/callback?ccbParamSJ=加密参数
```
**预期流程**:
1. 解密 `ccbParamSJ` 参数
2. 获取支付结果参数
3. 根据 `SUCCESS=Y/N` 判断支付成功或失败
4. 更新订单状态
**支付成功验证点**:
- 订单状态 → `paid`
- 支付时间 `paid_time` 已记录(毫秒时间戳)
- 支付方式 `pay_type``offline`
- 交易单号 `transaction_id` → 支付流水号
- 页面跳转到订单详情或支付成功页
**支付失败验证点**:
- 订单状态保持 `unpaid`
- 页面显示失败原因
---
### 测试7: 异步通知(需建行环境)
**目的**: 验证建行异步通知处理
**触发方式**:
- 支付成功后建行会POST请求到 `notify_url`
**接口**: `POST /addons/shopro/ccbpayment/notify`
**建行会发送的参数**(示例):
```
POST数据:
ORDERID=PAY20250118143000123456
&USER_ORDERID=SO20250118001
&POSID=100001
&PAYMENT=100.00
&SUCCESS=Y
&SIGN=签名值
```
**预期处理逻辑**:
1. 验证签名 `SIGN`
2. 验证 `POSID` 是否匹配
3. 根据 `USER_ORDERID``ccb_pay_flow_id` 查询订单
4. 更新订单状态
5. 返回 `SUCCESS``FAIL`
**验证点**:
- 响应体必须返回字符串 `SUCCESS``FAIL`
- 订单状态正确更新
- 日志 `runtime/log/` 中记录通知详情
**测试异步通知的方法**模拟建行POST请求:
```bash
curl -X POST 'https://your-domain.com/addons/shopro/ccbpayment/notify' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'ORDERID=PAY20250118143000123456&USER_ORDERID=SO20250118001&POSID=100001&PAYMENT=100.00&SUCCESS=Y&SIGN=mock_sign'
```
---
### 测试8: 订单同步到建行(需建行环境)
**目的**: 验证支付成功后订单推送到建行
**触发时机**:
- 支付回调成功后自动触发
- 或手动调用同步接口
**手动触发方式**:
```php
$orderService = new \addons\shopro\library\ccblife\CcbOrderService();
$result = $orderService->pushOrder($orderId);
var_dump($result);
```
**验证点**:
1. API请求成功HTTP 200
2. 返回 `CLD_HEAD.ERR_CODE === '0'`
3. `fa_ccb_sync_log` 表中记录同步成功
4. 订单同步状态更新
**失败处理**:
- 如果同步失败,日志中记录错误原因
- 支持重试机制(通过定时任务)
---
## 常见问题排查
### 问题1: 支付串生成失败
**错误信息**: "订单状态不正确"
**原因**: 订单已支付或已关闭
**解决**:
```sql
-- 检查订单状态
SELECT id, order_sn, status, pay_status FROM fa_shopro_order WHERE id = <order_id>;
-- 如需重测,重置订单状态
UPDATE fa_shopro_order SET status = 'unpaid', pay_status = 'unpaid' WHERE id = <order_id>;
```
---
### 问题2: 支付串签名错误
**错误信息**: "签名验证失败"
**排查步骤**:
1. 检查配置文件中私钥是否正确
2. 检查参数是否按ASCII排序
3. 检查MD5签名是否为小写
**验证签名算法**:
```php
// 测试代码
$params = [/* 支付参数 */];
ksort($params);
$signString = http_build_query($params);
$mac = md5($signString . config('ccblife.private_key'));
echo "签名字符串: {$signString}\n";
echo "MAC签名: {$mac}\n";
```
---
### 问题3: 订单查询失败
**错误信息**: "订单不存在"
**原因**:
- 使用了错误的订单号字段
- ORDERID支付流水号和 USER_ORDERID商户订单号混淆
**排查**:
```sql
-- 检查订单数据
SELECT
id,
order_sn, -- 商户订单号
ccb_pay_flow_id, -- 建行支付流水号
status
FROM fa_shopro_order
WHERE order_sn = 'SO20250118001' -- 使用商户订单号查询
OR ccb_pay_flow_id = 'PAY20250118143000123456'; -- 使用支付流水号查询
```
---
### 问题4: 订单状态未更新
**可能原因**:
1. 字段名错误(`paytime` vs `paid_time`
2. 时间戳单位错误(秒 vs 毫秒)
3. `pay_type` 枚举值不存在
**验证**:
```sql
-- 检查订单表字段
SHOW COLUMNS FROM fa_shopro_order LIKE 'paid_time';
-- 检查pay_type枚举值
SHOW COLUMNS FROM fa_shopro_order LIKE 'pay_type';
-- 查看订单更新时间
SELECT
id,
paid_time, -- 应为毫秒时间戳
FROM_UNIXTIME(paid_time/1000) as paid_datetime,
pay_type, -- 应为 'offline'
status
FROM fa_shopro_order
WHERE id = <order_id>;
```
---
### 问题5: RSA加密失败
**错误信息**: "RSA加密失败" 或 "key size too small"
**原因**:
- 密钥格式不正确
- 密钥长度不是1024位
- 数据块大小超过117字节
**验证密钥**:
```bash
# 检查私钥
echo "<私钥内容>" | openssl rsa -text -noout
# 检查公钥
echo "<公钥内容>" | openssl rsa -pubin -text -noout
# 查看密钥长度
# 应显示: Private-Key: (1024 bit)
```
**修复**:
1. 确保密钥包含完整的 `-----BEGIN``-----END` 标记
2. 数据分块处理每块不超过117字节
3. 使用正确的填充模式 `OPENSSL_PKCS1_PADDING`
---
## 测试检查清单
### ✅ 阶段一:模拟测试(可立即执行)
- [ ] 运行自动化测试脚本,所有测试通过
- [ ] 配置文件已正确配置
- [ ] 数据库表结构完整
- [ ] 订单表 `ccb_pay_flow_id` 字段存在
- [ ] 用户表 `ccb_user_id` 字段存在
- [ ] 支付日志表 `fa_ccb_payment_log` 存在
- [ ] 同步日志表 `fa_ccb_sync_log` 存在
- [ ] 支付串生成逻辑正确
- [ ] 支付流水号格式正确PAY+14位+6位
- [ ] 订单字段映射正确paid_time、total_fee等
### ✅ 阶段二:真实环境测试(需建行配置)
- [ ] 已获得建行测试环境配置
- [ ] RSA密钥对配置正确1024位
- [ ] API地址配置正确
- [ ] 回调地址已配置且可访问
- [ ] 在建行APP内能正确识别环境
- [ ] JSBridge初始化成功
- [ ] 用户自动登录成功
- [ ] ccb_user_id正确绑定
- [ ] 支付串加密正确ENCPUB字段
- [ ] 建行收银台能正确打开
- [ ] 支付回调能正确接收和处理
- [ ] 异步通知能正确接收和处理
- [ ] 签名验证通过
- [ ] 订单状态正确更新
- [ ] 订单同步到建行成功
- [ ] 重复通知幂等性处理正确
- [ ] 小额支付测试通过0.01元)
- [ ] 正常金额支付测试通过
- [ ] 支付取消测试通过
- [ ] 支付超时测试通过
---
## 附录
### A. 支付流水号规则
```
格式: PAY + YmdHis(14位) + 随机数(6位)
示例: PAY20250118143000123456
长度: 23位固定长度
组成:
- PAY: 固定前缀(3位)
- 20250118143000: 时间戳 yyMMddHHmmss (14位)
- 123456: 随机数 (6位)
```
### B. 重要字段映射表
| Shopro字段 | 建行字段 | 说明 | 示例 |
|------------|----------|------|------|
| order_sn | USER_ORDERID | 商户订单号 | SO20250118001 |
| ccb_pay_flow_id | ORDERID | 建行支付流水号 | PAY20250118143000123456 |
| total_fee | PAYMENT / PAY_AMT | 实际支付金额 | 100.00 |
| discount_fee | - | 优惠金额 | 5.00 |
| paid_time | PAY_TIME | 支付时间(毫秒) | 1737183000000 |
| createtime | ORD_TIME | 订单创建时间(秒) | 20250118143000 |
| status | ORD_STATUS | 订单状态 | paid → 02 |
| pay_type | - | 支付方式 | offline代表建行 |
| transaction_id | ORDERID | 交易单号 | PAY20250118143000123456 |
### C. 订单状态映射
| Shopro状态 | 建行状态码 | 说明 |
|-----------|-----------|------|
| unpaid | 01 | 未支付 |
| paid | 02 | 已支付 |
| closed | 03 | 已关闭 |
| cancelled | 04 | 已取消 |
### D. 日志文件位置
```
建行支付日志:
- runtime/log/202501/18.log
关键日志标识:
- [建行支付] 支付串生成
- [建行支付] 生成支付串失败
- [建行回调] 收到同步回调
- [建行通知] 收到异步通知
- [建行订单同步] 推送订单
```
---
## 总结
本测试指南提供了完整的测试方案,分为两个阶段:
1. **模拟测试阶段**(当前可用)
- 运行自动化测试脚本即可验证核心逻辑
- 无需建行真实配置
- 适合开发阶段自测
2. **真实环境测试阶段**(需建行配置)
- 需要建行提供测试环境
- 包含完整的支付流程
- 适合联调和上线前测试
**下一步行动**:
1. ✅ 立即运行自动化测试脚本
2. ⏸️ 等待建行提供测试环境配置
3. 🔄 获得配置后执行阶段二测试
**如有问题,请查看"常见问题排查"章节或联系开发人员。**