fengketrade/doc/ccblife_test_guide.md

745 lines
18 KiB
Markdown
Raw Normal View History

2025-10-20 15:29:15 +08:00
# 建行生活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. 🔄 获得配置后执行阶段二测试
**如有问题,请查看"常见问题排查"章节或联系开发人员。**