# 建行生活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 -u -p -e "SELECT VERSION();" ``` ### 2. 配置文件检查 确保已创建配置文件:`/application/extra/ccblife.php` ```php '***', // 商户代码 '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 = ; -- 如需重测,重置订单状态 UPDATE fa_shopro_order SET status = 'unpaid', pay_status = 'unpaid' WHERE 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 = ; ``` --- ### 问题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. 🔄 获得配置后执行阶段二测试 **如有问题,请查看"常见问题排查"章节或联系开发人员。**