# 建行生活H5商城完整技术实现方案 > 基于 FastAdmin + ThinkPHP 5.x + UniApp Vue3 + 建行生活开放平台 > 方案版本: v1.0 > 编制日期: 2025-01-16 ## 📋 目录 - [1. 项目概述](#1-项目概述) - [2. 技术架构设计](#2-技术架构设计) - [3. 核心功能模块](#3-核心功能模块) - [4. 数据库设计](#4-数据库设计) - [5. 接口规范](#5-接口规范) - [6. 安全机制](#6-安全机制) - [7. 开发实施计划](#7-开发实施计划) - [8. 测试方案](#8-测试方案) - [9. 部署方案](#9-部署方案) - [10. 风险评估与应对](#10-风险评估与应对) --- ## 1. 项目概述 ### 1.1 项目背景 将现有的 FastAdmin + Shopro 商城系统对接到建行生活开放平台,实现: - H5商城在建行生活APP内运行 - 使用建行支付完成交易 - 订单数据实时同步到建行平台 - 用户可在建行生活APP中查看订单 ### 1.2 技术栈 | 层级 | 技术选型 | 版本要求 | |------|---------|---------| | 前端框架 | UniApp (Vue3) | 3.0+ | | 后端框架 | FastAdmin (ThinkPHP 5.x) | 5.1+ | | 数据库 | MySQL | 5.7+ | | PHP版本 | PHP | 7.4+ | | Node.js | Node.js | 14+ | | 加密库 | OpenSSL | - | ### 1.3 已确认的建行参数 ```yaml 服务方编号: YS44000098000600 商户代码: 105910100194086 商户柜台代码: 313368474 分行代码: 441000000 UAT测试环境: http://128.192.179.60/uat_new/tp_service/txCtrl/server 生产环境: https://yunbusiness.ccb.com/tp_service/txCtrl/server 核心接口: - A3341TP01: 订单推送 - A3341TP02: 订单更新 - A3341TP03: 订单查询 - A3341TP04: 订单退款 ``` ### 1.4 关键文档依据 - ✅ `建行生活输入通讯报文v1.1.6【最新】.xlsx` - 接口参数规范 - ✅ `建行相关App服务方接入文档v2.20_20250725.html` - 接入流程 - ✅ `建行生活原生与h5交互规范接口1.3(新).html` - JSBridge规范 - ✅ `支付下单串示例.xlsx` - 支付签名验证 - ✅ `建行接口地址(真实版).md` - 接口地址确认 --- ## 2. 技术架构设计 ### 2.1 整体架构图 ``` ┌─────────────────────────────────────────────────────────────┐ │ 建行生活APP │ │ ┌──────────────────────────────────────────────────────┐ │ │ │ WebView容器 + JSBridge │ │ │ │ ┌────────────────────────────────────────────────┐ │ │ │ │ │ UniApp H5 商城前端 │ │ │ │ │ │ ┌──────────────────────────────────────────┐ │ │ │ │ │ │ │ pages/ │ sheep/ │ uni_modules│ │ │ │ │ │ │ │ - 商品页 │ - API封装 │ - JSBridge │ │ │ │ │ │ │ │ - 订单页 │ - 状态管理 │ 封装 │ │ │ │ │ │ │ │ - 支付页 │ - 工具函数 │ │ │ │ │ │ │ │ └──────────────────────────────────────────┘ │ │ │ │ │ └────────────────────────────────────────────────┘ │ │ │ └──────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────┘ │ │ HTTPS API ▼ ┌─────────────────────────────────────────────────────────────┐ │ FastAdmin + Shopro商城 (ThinkPHP 5.x) │ │ ┌──────────────────────────────────────────────────────┐ │ │ │ addons/shopro/controller/ │ │ │ │ ├─ Ccblife.php (建行用户自动登录控制器) │ │ │ │ └─ Ccbpayment.php (建行支付控制器) │ │ │ └──────────────────────────────────────────────────────┘ │ │ ┌──────────────────────────────────────────────────────┐ │ │ │ addons/shopro/library/ccblife/ │ │ │ │ ├─ CcbEncryption.php (加密解密核心类) │ │ │ │ ├─ CcbHttpClient.php (HTTP客户端类) │ │ │ │ ├─ CcbOrderService.php (订单服务类) │ │ │ │ └─ CcbPaymentService.php (支付服务类) │ │ │ └──────────────────────────────────────────────────────┘ │ │ ┌──────────────────────────────────────────────────────┐ │ │ │ 数据库 │ │ │ │ ├─ fa_shopro_order (订单表-已有) │ │ │ │ ├─ fa_ccb_payment_log (建行支付日志-新增) │ │ │ │ └─ fa_ccb_sync_log (建行同步日志-新增) │ │ │ └──────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────┘ │ │ HTTPS (加密报文) ▼ ┌─────────────────────────────────────────────────────────────┐ │ 建行服务器 │ │ ┌──────────────────────────────────────────────────────┐ │ │ │ 后台交易接口 │ │ │ │ ├─ A3341TP01 订单推送接口 │ │ │ │ ├─ A3341TP02 订单更新接口 │ │ │ │ ├─ A3341TP03 订单查询接口 │ │ │ │ └─ A3341TP04 订单退款接口 │ │ │ └──────────────────────────────────────────────────────┘ │ │ ┌──────────────────────────────────────────────────────┐ │ │ │ 收银台 │ │ │ │ - 支付页面 │ │ │ │ - 支付结果回调 │ │ │ └──────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────┘ ``` ### 2.2 数据流转图 ``` [用户] → [建行APP] → [H5商城] → [FastAdmin] → [建行服务器] ↑ ↓ ↓ ↓ └─────[支付回调]────────┴───[订单推送]────[支付验证] ``` ### 2.3 用户认证流程 (建行统一登录) **重要说明:** 弃用商城原有的登录注册功能,完全使用建行的用户体系 ```mermaid sequenceDiagram participant User as 用户 participant CCBApp as 建行生活App participant H5 as H5商城 participant Backend as FastAdmin后端 participant DB as 数据库 User->>CCBApp: 打开建行生活App CCBApp->>H5: 跳转H5商城
URL带参数: platform=ccblife&ccbParamSJ=xxx H5->>H5: onLaunch检测环境
识别为建行环境 H5->>CCBApp: 调用JSBridge getUserInfo() CCBApp-->>H5: 返回用户信息
{ccb_user_id, mobile, nickname, avatar} H5->>Backend: POST /api/ccblife/autoLogin
{"ccb_user_id": "xxx", ...} Backend->>DB: SELECT * FROM fa_user
WHERE ccb_user_id = 'xxx' alt 用户已存在 DB-->>Backend: 返回用户记录 Backend->>DB: UPDATE fa_user
SET logintime=now() Backend-->>H5: 返回Token + 用户信息
{is_new_user: false} else 用户不存在 (首次登录) Backend->>DB: INSERT INTO fa_user
(ccb_user_id, username, mobile...) DB-->>Backend: 用户创建成功 Backend-->>H5: 返回Token + 用户信息
{is_new_user: true} end H5->>H5: 保存Token到localStorage H5->>H5: 保存用户信息到Vuex/Pinia H5-->>User: 登录成功,进入商城首页 Note over H5: 商城原有的登录注册页面
在建行环境下隐藏/禁用 ``` **关键实现点:** 1. **环境识别 (App.vue onLaunch):** ```javascript // 检测是否在建行App中 const isInCCBApp = location.search.includes('platform=ccblife') || location.search.includes('platform=ccb'); if (isInCCBApp) { // 自动调用建行登录 await this.ccbAutoLogin(); } else { // 非建行环境,提示需要在建行App中打开 uni.showModal({ title: '提示', content: '请在建行生活APP中打开', showCancel: false }); } ``` 2. **自动登录方法:** ```javascript async ccbAutoLogin() { try { // 1. 解析URL参数 const urlParams = new URLSearchParams(location.search); const ccbParamSJ = urlParams.get('ccbParamSJ'); // 2. 调用JSBridge获取用户信息 const userInfo = await ccbBridge.getUserInfo(); // 3. 调用后端自动登录接口 const res = await uni.$u.http.post('/addons/shopro/ccblife/autoLogin', { ccb_user_id: userInfo.userId, // 建行用户ID (必需) ccb_param_sj: ccbParamSJ, // URL加密参数 (可选) mobile: userInfo.mobile, // 手机号 (可选) nickname: userInfo.nickname, // 昵称 (可选) avatar: userInfo.avatar // 头像 (可选) }); // 4. 保存Token uni.setStorageSync('token', res.data.token); // 5. 保存用户信息到Vuex this.$store.commit('user/setUserInfo', res.data.userInfo); // 6. 如果是新用户,可以引导 if (res.data.is_new_user) { uni.showToast({ title: '欢迎来到商城', icon: 'success' }); } } catch (error) { console.error('建行自动登录失败:', error); uni.showToast({ title: '登录失败', icon: 'none' }); } } ``` 3. **数据库用户表改造:** ```sql ALTER TABLE `fa_user` ADD COLUMN `ccb_user_id` varchar(50) DEFAULT NULL COMMENT '建行用户ID' AFTER `id`, ADD UNIQUE KEY `uk_ccb_user_id` (`ccb_user_id`); ``` 4. **商城原有登录注册页面处理:** ```javascript // pages/user/login.vue onLoad() { // 检测是否在建行环境 if (this.$ccb.isInCCBApp()) { uni.showModal({ title: '提示', content: '您已通过建行账号登录,无需再次登录', showCancel: false, success: () => { uni.reLaunch({ url: '/pages/index/index' }); } }); return; } // 非建行环境,显示原有登录页面 (如果需要支持) // 或者直接提示用户在建行App中打开 } ``` ### 2.4 关键技术点 #### 2.4.1 加密通讯机制 **请求加密流程:** ``` 1. 构造原始JSON报文 (CLD_HEADER + CLD_BODY) 2. 使用建行平台公钥进行RSA加密 3. 对密文进行BASE64编码并去除换行符 4. 使用原始报文+服务方私钥生成MD5签名 5. 组装最终报文: {cnt: 密文, mac: 签名, svcid: 服务方编号} ``` **响应解密流程:** ``` 1. 验证响应报文的MAC签名 2. 使用服务方私钥对cnt字段RSA解密 3. 解析JSON获取业务数据 4. 检查RET_CODE判断成功失败 ``` #### 2.3.2 支付串生成机制 **支付串构造流程:** ``` 1. 构造支付参数 (MERCHANTID, POSID, ORDERID, PAYMENT...) 2. 按参数名ASCII排序并拼接: key1=value1&key2=value2&... 3. 追加平台公钥: 参数串 + &PLATFORMPUB=xxx 4. 生成MD5签名: md5(参数串+平台公钥+服务方私钥) 5. RSA加密商户公钥并BASE64: ENCPUB 6. 组装最终支付串: 参数串 + &MAC=xxx + &PLATFORMID=xxx + &ENCPUB=xxx ``` **验证机制:** 根据 `支付下单串示例.xlsx`,已提供测试数据可验证签名算法正确性: - 测试签名: `f07ef63236e3bbbc1dc221b06e631f3d` #### 2.3.3 JSBridge交互机制 **调用格式:** ```javascript window.CCBMofeBridge.exec( "api分类", // baseAPI/userAPI/payAPI "api名称", // getUserInfo/startPayment JSON.stringify(params), // 参数JSON字符串 'callbackName' // 全局回调函数名 ); ``` **响应格式:** ```javascript { "status": "0", // 0-成功, 1-失败, -1-取消, -2-未开通 "data": { // 业务数据 } } ``` --- ## 3. 核心功能模块 ### 3.1 模块划分 ``` ┌─────────────────────────────────────────────────────────┐ │ 模块1: 用户认证模块 (使用建行统一登录) │ │ - 环境检测 (识别建行App环境) │ │ - 解析ccbParamSJ参数获取建行用户ID │ │ - JSBridge调用getUserInfo获取用户详细信息 │ │ - 建行用户与商城用户自动绑定/创建 │ │ - 弃用现有商城的登录注册功能 │ └─────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────┐ │ 模块2: 订单管理模块 │ │ - 订单创建 │ │ - 订单推送到建行 (A3341TP01) │ │ - 订单状态更新 (A3341TP02) │ │ - 订单查询 (A3341TP03) │ └─────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────┐ │ 模块3: 支付模块 │ │ - 支付串生成 │ │ - JSBridge调起支付 │ │ - 支付回调处理 │ │ - 支付结果验证 │ └─────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────┐ │ 模块4: 退款模块 │ │ - 退款申请 │ │ - 退款推送到建行 (A3341TP04) │ │ - 退款状态同步 │ └─────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────┐ │ 模块5: 加密通讯模块 │ │ - RSA加密/解密 │ │ - MD5签名/验签 │ │ - BASE64编码 │ │ - 报文构造与解析 │ └─────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────┐ │ 模块6: 日志与监控模块 │ │ - 支付日志记录 │ │ - 同步日志记录 │ │ - 异常监控与告警 │ │ - 数据对账 │ └─────────────────────────────────────────────────────────┘ ``` ### 3.2 核心类设计 #### 3.2.1 CcbEncryption 加密类 **文件路径:** `addons/shopro/library/ccblife/CcbEncryption.php` **职责:** - RSA加密与解密 - MD5签名生成与验证 - 报文构造与解析 - 交易流水号生成 **核心方法:** | 方法名 | 参数 | 返回值 | 说明 | |--------|------|--------|------| | `rsaEncrypt($data)` | string $data | string | 使用建行平台公钥加密 | | `rsaDecrypt($data)` | string $data | string | 使用服务方私钥解密 | | `generateSign($data)` | string $data | string | 生成MD5签名 | | `verifySign($data, $sign)` | string $data, string $sign | bool | 验证签名 | | `buildEncryptedMessage($txCode, $bodyData)` | string $txCode, array $bodyData | array | 构造完整加密报文 | | `parseResponse($response)` | string $response | array | 解析响应报文 | | `generateTransSeq()` | - | string | 生成唯一交易流水号 | **依赖:** - PHP OpenSSL扩展 - 配置文件中的密钥信息 #### 3.2.2 CcbHttpClient HTTP客户端类 **文件路径:** `addons/shopro/library/ccblife/CcbHttpClient.php` **职责:** - 发送HTTP请求到建行 - 处理HTTP响应 - 失败重试机制 - 超时控制 **核心方法:** | 方法名 | 参数 | 返回值 | 说明 | |--------|------|--------|------| | `request($txCode, $bodyData)` | string $txCode, array $bodyData | array | 发送请求并返回结果 | | `post($url, $data, $headers)` | string $url, array $data, array $headers | string | 发送POST请求 | | `parseResponse($response)` | string $response | array | 解析响应 | | `retry($callable, $maxRetries)` | callable $callable, int $maxRetries | mixed | 重试机制 | **关键配置:** - 超时时间: 30秒 - 重试次数: 3次 - 重试间隔: 1秒、2秒、5秒 #### 3.2.3 CcbOrderService 订单服务类 **文件路径:** `addons/shopro/library/ccblife/CcbOrderService.php` **职责:** - 订单推送到建行 - 订单状态更新 - 订单查询 - 订单退款 **核心方法:** | 方法名 | 参数 | 返回值 | 说明 | |--------|------|--------|------| | `pushOrder($orderData)` | array $orderData | array | 推送订单 (A3341TP01) | | `updateOrder($orderId, $status)` | string $orderId, string $status | array | 更新订单状态 (A3341TP02) | | `queryOrder($orderId)` | string $orderId | array | 查询订单 (A3341TP03) | | `refundOrder($orderId, $amount, $reason)` | string $orderId, float $amount, string $reason | array | 订单退款 (A3341TP04) | **订单推送必需字段 (根据通讯报文Excel):** ```php [ 'USER_ID' => '建行用户ID', 'ORDER_ID' => '订单号', 'ORDER_DT' => 'YmdHis格式时间', 'TOTAL_AMT' => '订单原金额', 'PAY_AMT' => '实际支付金额', 'DISCOUNT_AMT' => '优惠金额', 'ORDER_STATUS' => '0-待支付 1-已支付 2-已过期 3-失败 4-取消', 'REFUND_STATUS' => '0-无退款 1-申请 2-已退款 3-部分退款', 'MCT_NM' => '商户名称', 'CUS_ORDER_URL' => '订单详情URL', 'OCC_MCT_LOGO_URL' => '商户Logo URL', 'PAY_FLOW_ID' => '支付流水号 (对应ORDERID)', 'PAY_MRCH_ID' => '支付商户号', 'SKU_LIST' => '商品信息JSON', // ... 其他字段 ] ``` #### 3.2.4 CcbPaymentService 支付服务类 **文件路径:** `addons/shopro/library/ccblife/CcbPaymentService.php` **职责:** - 生成建行支付串 - 处理支付回调 - 验证支付结果 **核心方法:** | 方法名 | 参数 | 返回值 | 说明 | |--------|------|--------|------| | `generatePaymentString($order)` | array $order | string | 生成支付串 | | `handleCallback($callbackData)` | array $callbackData | array | 处理支付回调 | | `verifyPayment($orderId)` | string $orderId | bool | 验证支付结果 | **支付串必需参数 (根据支付下单串示例):** ```php [ 'MERCHANTID' => '商户代码', 'POSID' => '柜台代码', 'BRANCHID' => '分行代码', 'ORDERID' => '支付流水号 (唯一)', 'USER_ORDERID' => '用户订单号', 'PAYMENT' => '支付金额', 'CURCODE' => '01 (人民币)', 'TXCODE' => '520100', 'REMARK1' => '', 'REMARK2' => '服务方编号 (重要!)', 'TYPE' => '1', 'GATEWAY' => '0', 'CLIENTIP' => '客户端IP', 'THIRDAPPINFO' => 'comccbpay1234567890cloudmerchant', 'TIMEOUT' => 'YmdHis格式超时时间', ] ``` #### 3.2.5 ccb-bridge.js JSBridge封装 **文件路径:** `frontend/uni_modules/ccb-jsbridge/js_sdk/ccb-bridge.js` **职责:** - 封装JSBridge调用 - 环境检测 - Promise化异步调用 - 错误处理 **核心方法:** | 方法名 | 参数 | 返回值 | 说明 | |--------|------|--------|------| | `checkEnvironment()` | - | boolean | 检测是否在建行APP中 | | `exec(api, method, params)` | string api, string method, object params | Promise | 统一JSBridge调用 | | `getUserInfo()` | - | Promise | 获取用户信息 | | `startPayment(paymentString, orderId)` | string paymentString, string orderId | Promise | 调起支付 | | `getLocation()` | - | Promise | 获取地理位置 | | `callCamera(options)` | object options | Promise | 调用相机 | **使用示例:** ```javascript import ccbBridge from '@/uni_modules/ccb-jsbridge/js_sdk/ccb-bridge.js'; // 获取用户信息 const userInfo = await ccbBridge.getUserInfo(); // 调起支付 const result = await ccbBridge.startPayment(paymentString, orderId); if (result.status === '0') { // 支付成功 } ``` --- ## 4. 数据库设计 ### 4.1 新增表结构 #### 4.1.1 建行支付日志表 ```sql CREATE TABLE `fa_ccb_payment_log` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID', `order_id` varchar(50) NOT NULL COMMENT '商城订单ID', `order_sn` varchar(50) NOT NULL COMMENT '商城订单号', `pay_flow_id` varchar(50) NOT NULL COMMENT '支付流水号(对应建行ORDERID)', `payment_string` text COMMENT '支付串', `trans_id` varchar(100) DEFAULT NULL COMMENT '建行交易ID', `user_id` int(11) DEFAULT NULL COMMENT '用户ID', `ccb_user_id` varchar(30) DEFAULT NULL COMMENT '建行用户ID', `amount` decimal(10,2) NOT NULL COMMENT '支付金额', `status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0-待支付 1-支付成功 2-支付失败 3-已取消', `create_time` int(11) NOT NULL COMMENT '创建时间', `pay_time` int(11) DEFAULT NULL COMMENT '支付时间', `callback_data` text COMMENT '回调数据', `error_msg` varchar(500) DEFAULT NULL COMMENT '错误信息', PRIMARY KEY (`id`), UNIQUE KEY `pay_flow_id` (`pay_flow_id`), KEY `order_id` (`order_id`), KEY `order_sn` (`order_sn`), KEY `trans_id` (`trans_id`), KEY `status` (`status`), KEY `create_time` (`create_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='建行支付日志表'; ``` #### 4.1.2 建行订单同步日志表 ```sql CREATE TABLE `fa_ccb_sync_log` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID', `order_id` varchar(50) NOT NULL COMMENT '商城订单ID', `order_sn` varchar(50) NOT NULL COMMENT '商城订单号', `tx_code` varchar(20) NOT NULL COMMENT '交易代码 A3341TP01/02/03/04', `tx_seq` varchar(50) DEFAULT NULL COMMENT '交易流水号', `request_data` text COMMENT '请求数据(加密前)', `encrypted_data` text COMMENT '加密后数据', `response_data` text COMMENT '响应数据', `sync_status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0-失败 1-成功', `sync_time` int(11) NOT NULL COMMENT '同步时间', `retry_times` int(11) NOT NULL DEFAULT '0' COMMENT '重试次数', `error_msg` varchar(500) DEFAULT NULL COMMENT '错误信息', `cost_time` int(11) DEFAULT NULL COMMENT '耗时(毫秒)', PRIMARY KEY (`id`), KEY `order_id` (`order_id`), KEY `order_sn` (`order_sn`), KEY `tx_code` (`tx_code`), KEY `tx_seq` (`tx_seq`), KEY `sync_status` (`sync_status`), KEY `sync_time` (`sync_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='建行订单同步日志表'; ``` ### 4.2 已有表改造 #### 4.2.1 订单表字段新增 ```sql ALTER TABLE `fa_shopro_order` ADD COLUMN `ccb_user_id` varchar(30) DEFAULT NULL COMMENT '建行用户ID' AFTER `user_id`, ADD COLUMN `ccb_pay_flow_id` varchar(50) DEFAULT NULL COMMENT '建行支付流水号' AFTER `order_sn`, ADD COLUMN `ccb_sync_status` tinyint(1) DEFAULT '0' COMMENT '建行同步状态 0-未同步 1-已同步 2-同步失败' AFTER `pay_status`, ADD COLUMN `ccb_sync_time` int(11) DEFAULT NULL COMMENT '建行同步时间' AFTER `ccb_sync_status`, ADD INDEX `idx_ccb_user_id` (`ccb_user_id`), ADD INDEX `idx_ccb_pay_flow_id` (`ccb_pay_flow_id`), ADD INDEX `idx_ccb_sync_status` (`ccb_sync_status`); ``` --- ## 5. 接口规范 ### 5.1 前端调用后端接口 #### 5.1.1 建行用户自动登录接口 (替代原有登录注册) **说明:** - 弃用商城原有的登录注册功能 - H5在建行App内打开时,自动通过JSBridge获取建行用户信息 - 如果建行用户ID已存在则登录,不存在则自动创建商城用户并绑定 - 返回商城Token用于后续API调用 **请求:** ```http POST /addons/shopro/ccblife/autoLogin Content-Type: application/json { "ccb_user_id": "建行用户ID (必需)", "ccb_param_sj": "建行加密参数 (可选,来自URL参数)", "mobile": "手机号 (可选,来自getUserInfo)", "nickname": "昵称 (可选,来自getUserInfo)", "avatar": "头像URL (可选,来自getUserInfo)" } ``` **响应:** ```json { "code": 1, "msg": "登录成功", "data": { "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...", "user_id": 123, "is_new_user": false, "userInfo": { "id": 123, "username": "user_ccb_xxx", "nickname": "建行用户昵称", "mobile": "138****0000", "avatar": "https://...", "ccb_user_id": "建行用户ID", "create_time": "2025-01-16 12:00:00" } } } ``` **业务逻辑:** ``` 1. 接收ccb_user_id(必需) 2. 查询fa_user表中是否存在该ccb_user_id 3. 如果存在: - 更新最后登录时间 - 生成新的Token - 返回用户信息 (is_new_user=false) 4. 如果不存在: - 创建新用户记录 - username: "user_ccb_" + ccb_user_id - ccb_user_id: 建行用户ID - mobile/nickname/avatar: 来自请求参数 - 生成Token - 返回用户信息 (is_new_user=true) ``` #### 5.1.2 创建订单接口 **请求:** ```http POST /addons/shopro/order/create Authorization: Bearer {token} Content-Type: application/json { "goods_list": [ { "goods_id": 1, "sku_id": 1, "quantity": 2 } ], "address_id": 1, "remark": "备注" } ``` **响应:** ```json { "code": 1, "msg": "订单创建成功", "data": { "order_id": 123, "order_sn": "ORD202501160001", "pay_flow_id": "PAY20250116000112345678", "total_amount": 100.00, "pay_amount": 99.00 } } ``` #### 5.1.3 生成支付串接口 **请求:** ```http POST /addons/shopro/ccbpayment/createPayment Authorization: Bearer {token} Content-Type: application/json { "order_id": 123 } ``` **响应:** ```json { "code": 1, "msg": "支付串生成成功", "data": { "payment_string": "MERCHANTID=105910100194086&POSID=313368474&...", "order_id": 123, "pay_flow_id": "PAY20250116000112345678", "amount": 99.00 } } ``` #### 5.1.4 支付回调接口 **请求:** ```http POST /addons/shopro/ccbpayment/callback Authorization: Bearer {token} Content-Type: application/json { "order_id": 123, "trans_id": "建行交易ID", "pay_time": "20250116120000" } ``` **响应:** ```json { "code": 1, "msg": "支付成功", "data": { "order_id": 123, "order_sn": "ORD202501160001", "pay_status": 1 } } ``` ### 5.2 后端调用建行接口 #### 5.2.1 订单推送接口 (A3341TP01) **请求URL:** ``` POST https://yunbusiness.ccb.com/tp_service/txCtrl/server?txcode=A3341TP01 Content-Type: application/json ``` **请求体 (加密前):** ```json { "CLD_HEADER": { "CLD_TX_CHNL": "YS44000098000600", "CLD_TX_TIME": "20250116120000", "CLD_TX_CODE": "A3341TP01", "CLD_TX_SEQ": "202501161200001234567890" }, "CLD_BODY": { "USER_ID": "建行用户ID", "ORDER_ID": "ORD202501160001", "ORDER_DT": "20250116120000", "TOTAL_AMT": "100.00", "PAY_AMT": "99.00", "DISCOUNT_AMT": "1.00", "ORDER_STATUS": "1", "REFUND_STATUS": "0", "MCT_NM": "商户名称", "CUS_ORDER_URL": "https://your-domain.com/order/detail/123", "OCC_MCT_LOGO_URL": "https://your-domain.com/logo.png", "PAY_FLOW_ID": "PAY20250116000112345678", "PAY_MRCH_ID": "105910100194086", "SKU_LIST": "[{\"SKU_NAME\":\"商品名\",\"SKU_REF_PRICE\":100.00,\"SKU_NUM\":1,\"SKU_SELL_PRICE\":99.00}]" } } ``` **请求体 (加密后):** ```json { "cnt": "RSA加密后的BASE64字符串...", "mac": "MD5签名32位小写", "svcid": "YS44000098000600" } ``` **响应体 (解密后):** ```json { "CLD_HEADER": { "RET_CODE": "000000", "RET_MSG": "成功" }, "CLD_BODY": { "CCB_DISCOUNT_AMT": "0.00", "CCB_DISCOUNT_AMT_DESC": "" } } ``` #### 5.2.2 订单更新接口 (A3341TP02) **请求结构同A3341TP01,只是交易代码不同** **CLD_BODY字段:** ```json { "USER_ID": "建行用户ID", "ORDER_ID": "ORD202501160001", "ORDER_STATUS": "1", // 更新后的状态 "REFUND_STATUS": "0", "PAY_AMT": "99.00", // 如果状态变更涉及金额变化 // ... 其他需要更新的字段 } ``` --- ## 6. 安全机制 ### 6.1 加密安全 #### 6.1.1 密钥管理 **原则:** - ✅ 私钥存储在环境变量 `.env` 中,不提交到代码仓库 - ✅ 生产环境使用密钥管理服务 (如 Vault) - ✅ 定期轮换密钥 (建议每年一次) - ✅ 密钥访问权限严格控制 **配置示例:** ```bash # .env CCB_PRIVATE_KEY="MIICdQIBADANBgkqhkiG9w0BAQ..." CCB_PUBLIC_KEY="MIGfMA0GCSqGSIb3DQEBAQUAA4G..." CCB_PLATFORM_PUBLIC_KEY="MIGfMA0GCSqGSIb3DQEBAQUAA4G..." ``` **读取方式:** ```php $config = [ 'private_key' => env('CCB_PRIVATE_KEY'), 'public_key' => env('CCB_PUBLIC_KEY'), 'platform_public_key' => env('CCB_PLATFORM_PUBLIC_KEY'), ]; ``` #### 6.1.2 加密强度 - RSA密钥长度: 1024位 (建行要求) - 签名算法: MD5 (建行要求) - BASE64编码: 标准BASE64,去除换行符 #### 6.1.3 防重放攻击 **措施:** - 交易流水号唯一性: `YmdHis + 微秒 + 随机数` - 交易时间戳: 精确到秒 - 服务端验证流水号唯一性 - 请求有效期: 5分钟 ### 6.2 接口安全 #### 6.2.1 HTTPS强制 - ✅ 生产环境强制HTTPS - ✅ 证书有效期监控 - ✅ TLS 1.2+ #### 6.2.2 请求头验证 **必需请求头:** ```http Accept: application/json Content-Type: application/json ``` **缺少将导致404错误!** #### 6.2.3 签名验证 **请求签名:** ``` MD5(原始报文JSON + 服务方私钥) ``` **响应验签:** ``` MD5(解密后JSON + 服务方私钥) === 响应中的mac ``` ### 6.3 数据安全 #### 6.3.1 敏感信息脱敏 **日志记录规则:** - ❌ 禁止记录完整密钥 - ❌ 禁止记录完整支付串 - ✅ 记录加密后的报文 (可用于排查) - ✅ 手机号脱敏: 138****0000 - ✅ 身份证脱敏: 440***********1234 #### 6.3.2 SQL注入防护 **使用参数绑定:** ```php // ❌ 错误示例 $sql = "SELECT * FROM order WHERE order_id = '{$orderId}'"; // ✅ 正确示例 $order = Db::name('order')->where('order_id', $orderId)->find(); ``` #### 6.3.3 XSS防护 **前端输出转义:** ```javascript // 使用Vue的自动转义
{{ userInput }}
// 不要使用v-html除非必要 ``` --- ## 7. 开发实施计划 ### 7.1 总体时间规划 ``` 总工期: 18-23个工作日 (约4周) 第一周: 基础框架搭建 (5天) 第二周: 核心功能开发 (5天) 第三周: 业务集成与前端 (5天) 第四周: 测试与上线 (3-8天) ``` ### 7.2 详细任务分解 #### Phase 1: 环境准备与基础框架 (Day 1-2) **Day 1: 环境配置** - [ ] 配置 `.env` 环境变量 - [ ] 创建数据库表 (fa_ccb_payment_log, fa_ccb_sync_log) - [ ] 改造用户表和订单表 (新增建行相关字段) - [ ] 创建Shopro插件目录结构 - `addons/shopro/library/ccblife/` - 核心类库 - `addons/shopro/controller/Ccblife.php` - 用户登录控制器 - `addons/shopro/controller/Ccbpayment.php` - 支付控制器 - [ ] 配置文件编写 (addons/shopro/config/ccblife.php) **验收标准:** - 数据库表创建成功 - 配置文件正确读取环境变量 - 目录结构符合规范 **Day 2: 核心加密模块** - [ ] 实现 CcbEncryption.php (加密解密类) - [ ] 单元测试: RSA加密解密 - [ ] 单元测试: MD5签名验证 - [ ] 单元测试: 报文构造 - [ ] 对比支付下单串示例验证签名正确性 **验收标准:** - 生成的MD5签名与示例一致: `f07ef63236e3bbbc1dc221b06e631f3d` - RSA加密解密往返成功 - 报文格式符合建行规范 #### Phase 2: HTTP通讯与接口封装 (Day 3-4) **Day 3: HTTP客户端** - [ ] 实现 CcbHttpClient.php - [ ] 实现请求重试机制 - [ ] 实现超时控制 - [ ] 实现响应解析 - [ ] 单元测试: Mock建行接口测试 **验收标准:** - 能够正确发送加密请求 - 能够正确解析响应 - 重试机制生效 - 超时正常工作 **Day 4: 订单与支付服务** - [ ] 实现 CcbOrderService.php - [ ] 实现 CcbPaymentService.php - [ ] 实现订单推送方法 (A3341TP01) - [ ] 实现订单更新方法 (A3341TP02) - [ ] 实现支付串生成方法 - [ ] 单元测试: 各服务方法 **验收标准:** - 订单推送报文格式正确 - 支付串生成符合规范 - 所有必需字段完整 #### Phase 3: 控制器与业务逻辑 (Day 5-7) **Day 5: 后端控制器** - [ ] 实现 addons/shopro/controller/Ccblife.php - autoLogin() - 建行用户自动登录 - [ ] 实现 addons/shopro/controller/Ccbpayment.php - createPayment() - 生成支付串 - callback() - 支付回调处理 - [ ] 实现用户自动登录接口 (替代原有登录注册) - [ ] 实现生成支付串接口 - [ ] 实现支付回调接口 - [ ] 集成日志记录 **验收标准:** - 所有接口响应格式统一 - 错误处理完善 - 日志记录完整 **Day 6-7: 订单流程集成** - [ ] 订单创建后自动推送到建行 - [ ] 支付成功后更新订单状态并同步 - [ ] 退款流程对接 - [ ] 定时任务: 失败订单重试 - [ ] 定时任务: 订单状态对账 **验收标准:** - 订单创建→推送→支付→同步 全流程打通 - 异常订单有重试机制 - 对账功能正常 #### Phase 4: 前端开发 (Day 8-10) **Day 8: JSBridge封装** - [ ] 实现 ccb-bridge.js - [ ] 实现环境检测 - [ ] 实现getUserInfo方法 - [ ] 实现startPayment方法 - [ ] 实现getLocation方法 - [ ] 本地Mock测试 **验收标准:** - JSBridge调用正常 - Promise化完成 - 错误处理完善 **Day 9: 支付页面开发** - [ ] 实现 pages/payment/ccb-pay.vue - [ ] 页面布局 - [ ] 支付逻辑实现 - [ ] 支付结果处理 - [ ] Loading状态 - [ ] 错误提示 **验收标准:** - 页面UI符合设计 - 支付流程完整 - 异常处理完善 **Day 10: 订单页面适配** - [ ] 订单列表适配建行环境 - [ ] 订单详情页适配 - [ ] 支付按钮跳转 - [ ] 订单状态展示 - [ ] App.vue初始化逻辑 **验收标准:** - 建行环境下订单功能正常 - 非建行环境降级处理 - 用户体验流畅 #### Phase 5: 测试与修复 (Day 11-15) **Day 11-12: 单元测试** - [ ] 后端单元测试覆盖率>80% - [ ] 加密模块测试 - [ ] 接口调用测试 - [ ] 边界条件测试 **Day 13-14: UAT环境联调** - [ ] 订单推送接口联调 - [ ] 支付流程联调 - [ ] 订单更新接口联调 - [ ] 退款接口联调 - [ ] 异常场景测试 **Day 15: 性能与安全测试** - [ ] 并发测试 (100笔/分钟) - [ ] 压力测试 - [ ] 安全扫描 - [ ] 渗透测试 - [ ] 代码审查 **验收标准:** - 所有接口联调成功 - 性能指标达标 - 无高危漏洞 - 代码质量合格 #### Phase 6: 上线部署 (Day 16-18) **Day 16: 生产环境准备** - [ ] 配置生产环境变量 - [ ] 配置正式接口地址 - [ ] 配置正式密钥 - [ ] 配置监控告警 - [ ] 准备应急预案 - [ ] 编写运维文档 **Day 17: 灰度发布** - [ ] 1%用户灰度测试 - [ ] 监控支付成功率 - [ ] 监控订单同步率 - [ ] 监控接口响应时间 - [ ] 分析错误日志 **Day 18: 全量上线** - [ ] 扩大到10%用户 - [ ] 扩大到50%用户 - [ ] 全量发布 - [ ] 持续监控 - [ ] 总结复盘 ### 7.3 人力安排 | 角色 | 人数 | 职责 | |------|------|------| | 后端开发 | 1人 | PHP后端开发、接口对接 | | 前端开发 | 1人 | UniApp前端开发、JSBridge封装 | | 测试工程师 | 1人 | 测试用例编写、功能测试、接口测试 | | 项目经理 | 1人 | 进度把控、风险管理、对外协调 | --- ## 8. 测试方案 ### 8.1 测试环境 ``` UAT环境: - 接口地址: http://128.192.179.60/uat_new/tp_service/txCtrl/server - 服务方编号: YS44000098000600 - 测试数据: 使用测试商户号和密钥 生产环境: - 接口地址: https://yunbusiness.ccb.com/tp_service/txCtrl/server - 服务方编号: YS44000098000600 - 真实交易: 小额测试后全量 ``` ### 8.2 测试用例 #### 8.2.1 功能测试用例 **用例1: 建行用户自动登录 (替代原有登录注册)** ``` 前置条件: 在建行生活APP中打开H5 测试步骤: 1. H5加载完成,App.vue的onLaunch执行 2. 检测运行环境 (location.search是否包含platform=ccblife) 3. 解析URL参数获取ccbParamSJ 4. 调用JSBridge的getUserInfo()获取用户详细信息 5. 发送ccb_user_id等信息到后端 /addons/shopro/ccblife/autoLogin 6. 后端检查建行用户是否已存在: - 存在: 更新登录时间,返回Token - 不存在: 创建新用户,绑定ccb_user_id,返回Token 7. 前端保存Token到storage 8. 前端保存用户信息到Vuex/Pinia 预期结果: - 环境检测正确 (isInCCBApp=true) - 获取到ccb_user_id, mobile, nickname等信息 - 后端返回token - 用户自动登录成功,无需注册 - 商城原有的登录注册页面被禁用 ``` **用例2: 订单创建与推送** ``` 前置条件: 用户已登录 测试步骤: 1. 选择商品加入购物车 2. 提交订单 3. 后端创建订单 4. 推送订单到建行 (A3341TP01) 预期结果: - 订单创建成功 - 订单推送成功 (RET_CODE=000000) - 数据库记录完整 - 同步日志记录 ``` **用例3: 支付流程** ``` 前置条件: 订单已创建并推送成功 测试步骤: 1. 点击支付按钮 2. 后端生成支付串 3. 前端调用startPayment 4. 建行收银台展示 5. 用户确认支付 6. 支付成功回调 预期结果: - 支付串签名正确 - 收银台正常调起 - 支付成功 - 订单状态更新 - 推送订单状态到建行 (A3341TP02) ``` **用例4: 订单查询** ``` 前置条件: 订单已支付 测试步骤: 1. 进入订单列表 2. 点击订单详情 3. 后端查询订单 (A3341TP03) 预期结果: - 订单信息正确 - 建行侧数据一致 ``` **用例5: 订单退款** ``` 前置条件: 订单已支付 测试步骤: 1. 申请退款 2. 后端处理退款 3. 推送退款到建行 (A3341TP04) 4. 更新订单状态 预期结果: - 退款成功 - 订单状态更新 - 建行侧数据同步 ``` #### 8.2.2 异常场景测试 | 场景 | 测试方法 | 预期结果 | |------|---------|---------| | 网络超时 | 断网或延迟注入 | 触发重试机制,记录日志 | | 签名错误 | 篡改签名 | 返回签名验证失败 | | 订单重复推送 | 多次调用推送接口 | 检测重复,不重复推送 | | 支付超时 | 用户长时间未支付 | 订单过期,状态正确 | | 用户取消支付 | 在收银台取消 | 订单状态为待支付 | | 建行接口异常 | Mock 500错误 | 重试机制生效,记录日志 | | 金额不一致 | 前后端金额不同 | 校验失败,拒绝支付 | #### 8.2.3 性能测试 **测试指标:** ``` 支付并发: 100笔/分钟 订单推送: 200笔/分钟 接口响应: <3秒 成功率: >99% ``` **压测工具:** - JMeter - Locust **压测场景:** ``` 场景1: 100个用户同时下单支付 场景2: 1000笔订单批量推送 场景3: 持续压力测试30分钟 ``` #### 8.2.4 安全测试 **测试项:** - [ ] SQL注入测试 - [ ] XSS攻击测试 - [ ] CSRF防护测试 - [ ] 密钥泄露检测 - [ ] 接口鉴权测试 - [ ] 越权访问测试 - [ ] 重放攻击测试 **工具:** - OWASP ZAP - Burp Suite - 代码扫描工具 --- ## 9. 部署方案 ### 9.1 服务器要求 **生产环境配置:** ```yaml Web服务器: - 类型: Nginx 1.18+ - 数量: 2台 (主备) - CPU: 4核 - 内存: 8GB - 硬盘: 100GB SSD 应用服务器: - 类型: PHP-FPM 7.4+ - 进程数: 根据并发动态调整 - 超时: 60秒 数据库服务器: - 类型: MySQL 5.7+ - CPU: 8核 - 内存: 16GB - 硬盘: 500GB SSD - 备份: 每日全量+实时binlog ``` ### 9.2 部署步骤 #### 9.2.1 代码部署 ```bash # 1. 拉取代码 cd /www/wwwroot/fengketrade.com git pull origin main # 2. 安装依赖 composer install --no-dev --optimize-autoloader # 前端构建 (如需) cd frontend npm run build:h5 # 3. 配置环境变量 cp .env.example .env vi .env # 配置生产环境参数 # 4. 目录权限 chown -R www:www /www/wwwroot/fengketrade.com chmod -R 755 runtime/ public/uploads/ # 5. 数据库迁移 php think migrate:run # 如有迁移脚本 # 6. 清除缓存 php think clear php think optimize:config # 7. 重启服务 systemctl reload php-fpm systemctl reload nginx ``` #### 9.2.2 Nginx配置 ```nginx server { listen 80; listen 443 ssl http2; server_name fengketrade.com; ssl_certificate /path/to/cert.pem; ssl_certificate_key /path/to/key.pem; # HTTPS强制跳转 if ($scheme = http) { return 301 https://$server_name$request_uri; } root /www/wwwroot/fengketrade.com/public; index index.php index.html; # FastAdmin路由 location / { if (!-e $request_filename) { rewrite ^(.*)$ /index.php?s=$1 last; break; } } # PHP处理 location ~ \.php$ { fastcgi_pass unix:/var/run/php-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; # 增加超时时间 fastcgi_read_timeout 60s; } # 静态资源缓存 location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ { expires 30d; add_header Cache-Control "public, immutable"; } # 安全配置 location ~ /\.git { deny all; } location ~ /\.env { deny all; } # 日志 access_log /www/logs/fengketrade_access.log; error_log /www/logs/fengketrade_error.log; } ``` ### 9.3 监控配置 #### 9.3.1 应用监控 **监控指标:** ```yaml 业务指标: - 支付成功率 - 订单推送成功率 - 接口响应时间 - 错误率 系统指标: - CPU使用率 - 内存使用率 - 磁盘IO - 网络流量 ``` **告警规则:** ```yaml 严重告警 (立即处理): - 支付成功率 < 95% - 订单推送失败 > 10笔/小时 - 系统错误率 > 5% - 数据库连接失败 警告告警 (关注处理): - 支付成功率 < 98% - 接口响应时间 > 3秒 - CPU使用率 > 80% - 磁盘使用率 > 80% ``` #### 9.3.2 日志收集 **日志级别:** ``` ERROR: 错误日志 (必须处理) WARNING: 警告日志 (需要关注) INFO: 信息日志 (常规记录) DEBUG: 调试日志 (开发环境) ``` **日志内容:** ```php // 订单推送日志 [2025-01-16 12:00:00] INFO 订单推送开始 order_id=123 tx_code=A3341TP01 [2025-01-16 12:00:01] DEBUG 请求数据 request={"USER_ID":"xxx"...} [2025-01-16 12:00:02] INFO 订单推送成功 order_id=123 cost_time=1.2s // 支付日志 [2025-01-16 12:05:00] INFO 支付串生成 order_id=123 amount=99.00 [2025-01-16 12:05:01] INFO 支付调起成功 pay_flow_id=PAYxxx [2025-01-16 12:05:30] INFO 支付回调 status=success trans_id=xxx ``` ### 9.4 备份方案 #### 9.4.1 数据库备份 ```bash # 每日全量备份 (凌晨2点) 0 2 * * * /usr/local/bin/mysql_backup.sh # 备份脚本 #!/bin/bash DATE=$(date +%Y%m%d) BACKUP_DIR=/backup/mysql mkdir -p $BACKUP_DIR mysqldump -u root -p'password' \ --single-transaction \ --quick \ --lock-tables=false \ fengketrade > $BACKUP_DIR/fengketrade_$DATE.sql # 压缩 gzip $BACKUP_DIR/fengketrade_$DATE.sql # 删除7天前的备份 find $BACKUP_DIR -name "*.sql.gz" -mtime +7 -delete ``` #### 9.4.2 代码备份 ```bash # 每次发布前打tag git tag -a v1.0.0 -m "Release version 1.0.0" git push origin v1.0.0 ``` --- ## 10. 风险评估与应对 ### 10.1 技术风险 #### 风险1: 加密算法实现错误 **风险等级:** 高 **影响:** 无法与建行通讯,业务完全中断 **概率:** 中 **应对措施:** - ✅ 使用支付下单串示例验证签名正确性 - ✅ 单元测试覆盖所有加密方法 - ✅ UAT环境充分测试 - ✅ 保留Java示例代码作为参考 **验证方式:** ```php // 生成的签名必须与示例一致 $testSign = 'f07ef63236e3bbbc1dc221b06e631f3d'; $generatedSign = CcbEncryption::generateSign($testData); assert($testSign === $generatedSign); ``` #### 风险2: 接口调用失败率高 **风险等级:** 高 **影响:** 订单推送失败,支付异常 **概率:** 中 **应对措施:** - ✅ 实现失败重试机制 (最多3次) - ✅ 实现异步队列,失败订单重推 - ✅ 实现定时对账功能 - ✅ 监控告警,及时发现问题 **重试策略:** ``` 第1次失败: 立即重试 第2次失败: 1秒后重试 第3次失败: 5秒后重试 超过3次: 进入异常队列,人工处理 ``` #### 风险3: JSBridge兼容性问题 **风险等级:** 中 **影响:** 部分功能无法使用 **概率:** 低 **应对措施:** - ✅ 实现环境检测,非建行环境降级处理 - ✅ 充分测试iOS和Android - ✅ 提供Mock方案用于本地调试 - ✅ 错误提示友好 **降级方案:** ```javascript if (!ccbBridge.isInCcbLife) { uni.showModal({ title: '提示', content: '请在建行生活APP中打开', confirmText: '前往下载', success: (res) => { if (res.confirm) { // 跳转到建行生活下载页 } } }); } ``` ### 10.2 业务风险 #### 风险4: 订单金额不一致 **风险等级:** 高 **影响:** 资金风险,财务对账异常 **概率:** 低 **应对措施:** - ✅ 前后端双重金额校验 - ✅ 支付前再次校验订单金额 - ✅ 建行侧金额校验 - ✅ 定时对账发现差异 **校验逻辑:** ```php // 后端生成支付串前校验 $orderAmount = $order['total_amount']; $requestAmount = $request->post('amount'); if (bccomp($orderAmount, $requestAmount, 2) !== 0) { throw new Exception('金额不一致'); } // 支付回调后校验 $paidAmount = $callbackData['amount']; if (bccomp($orderAmount, $paidAmount, 2) !== 0) { // 异常告警 Log::error('支付金额不一致', [ 'order_id' => $orderId, 'order_amount' => $orderAmount, 'paid_amount' => $paidAmount ]); } ``` #### 风险5: 订单状态不同步 **风险等级:** 中 **影响:** 用户体验差,客诉增加 **概率:** 中 **应对措施:** - ✅ 关键节点立即同步 (支付成功、退款) - ✅ 定时任务兜底同步 - ✅ 提供手动同步功能 - ✅ 监控同步成功率 **同步策略:** ``` 实时同步: 订单创建、支付成功、发货、完成、退款 定时同步: 每小时同步一次所有未同步订单 对账同步: 每日凌晨对账,发现差异立即同步 ``` ### 10.3 安全风险 #### 风险6: 密钥泄露 **风险等级:** 严重 **影响:** 系统安全完全失效 **概率:** 低 **应对措施:** - ✅ 密钥存储在环境变量,不提交代码 - ✅ 生产环境使用密钥管理服务 - ✅ 定期轮换密钥 - ✅ 访问权限严格控制 - ✅ 代码审查检查密钥泄露 **检查方式:** ```bash # 检查是否有密钥硬编码 grep -r "MIICdQIBADANBgkqhkiG9w0BAQ" application/ grep -r "private_key.*=" application/ ``` #### 风险7: 接口被恶意调用 **风险等级:** 高 **影响:** 资源浪费,系统不稳定 **概率:** 中 **应对措施:** - ✅ 接口鉴权 (Token验证) - ✅ 频率限制 (同一用户1分钟最多10次) - ✅ IP白名单 (建行回调接口) - ✅ 异常流量告警 **限流实现:** ```php // 使用Redis实现限流 $key = "rate_limit:user:{$userId}:payment"; $count = Redis::incr($key); if ($count == 1) { Redis::expire($key, 60); // 1分钟过期 } if ($count > 10) { throw new Exception('操作过于频繁,请稍后再试'); } ``` ### 10.4 运维风险 #### 风险8: 服务器宕机 **风险等级:** 高 **影响:** 业务中断 **概率:** 低 **应对措施:** - ✅ 双机热备 - ✅ 负载均衡 - ✅ 自动故障切换 - ✅ 监控告警 - ✅ 应急预案 **应急预案:** ``` 1. 监控发现主服务器异常 2. 自动切换到备服务器 (30秒内) 3. 告警通知运维人员 4. 运维人员排查主服务器问题 5. 修复后切回主服务器 ``` #### 风险9: 数据库异常 **风险等级:** 严重 **影响:** 数据丢失,业务中断 **概率:** 低 **应对措施:** - ✅ 主从复制 - ✅ 每日全量备份 - ✅ 实时binlog备份 - ✅ 定期演练恢复 - ✅ 监控数据库状态 **恢复演练:** ```bash # 1. 停止应用 systemctl stop php-fpm # 2. 恢复数据库 mysql -u root -p fengketrade < /backup/mysql/fengketrade_20250116.sql # 3. 恢复binlog (从备份时间点到当前) mysqlbinlog --start-datetime="2025-01-16 02:00:00" \ /var/lib/mysql/mysql-bin.000001 | mysql -u root -p fengketrade # 4. 验证数据 # 5. 启动应用 systemctl start php-fpm ``` --- ## 11. 附录 ### 11.1 名词解释 | 术语 | 解释 | |------|------| | FastAdmin | 基于ThinkPHP的后台管理系统框架 | | UniApp | 跨平台应用开发框架 | | JSBridge | H5与原生APP通讯的桥接技术 | | RSA | 非对称加密算法 | | MD5 | 消息摘要算法 | | BASE64 | 编码方式 | | txcode | 交易代码,标识不同的接口 | | 服务方编号 | 建行分配的唯一标识,格式YS开头 | | 支付流水号 | 支付请求的唯一标识 | | 交易流水号 | 后台接口调用的唯一标识 | ### 11.2 参考文档 - [建行生活输入通讯报文v1.1.6【最新】.xlsx](doc/建行生活输入通讯报文v1.1.6【最新】.xlsx) - [建行相关App服务方接入文档v2.20_20250725.html](doc/建行相关App服务方接入文档v2.20_20250725.html) - [建行生活原生与h5交互规范接口1.3(新).html](doc/建行生活原生与h5交互规范接口1.3(新).html) - [支付下单串示例.xlsx](doc/支付下单串示例.xlsx) - [建行接口地址(真实版).md](doc/建行接口地址(真实版).md) ### 11.3 联系方式 **技术支持:** - 建行技术热线: 95533 - 工作时间: 工作日 9:00-18:00 **紧急联系:** - 项目经理: [联系方式] - 技术负责人: [联系方式] --- ## 文档变更记录 | 版本 | 日期 | 修改人 | 修改内容 | |------|------|--------|---------| | v1.0 | 2025-01-16 | Claude | 初版,完整技术实现方案 | --- **文档结束**