# 祈盟SDK - Go重构优化分析 > 不是简单搬代码,而是借重构机会解决历史债务 --- ## 一、现有代码核心问题 ### 1. common.php 全局函数地狱(1988行,90+函数) 这是项目最大的技术债。所有工具函数堆在一个文件里,没有分类、没有接口约束。 #### 1.1 HTTP请求函数重复(5+个) | 函数名 | 行数 | 功能 | |--------|------|------| | `getCurlContent` | 366 | 原始curl,支持POST | | `getCurl` | 1252 | GET请求封装 | | `curl` | 1282 | 通用curl封装 | | `apipost` | 1214 | POST请求封装 | | `getHttp` | 1652 | 通用HTTP,支持GET/POST | | `getHttpGet` | 1702 | GET请求,带JSON支持 | | `getHttpException` | 1722 | POST请求,带header | | `curlHeader` | 1439 | 带header的curl | | `timingCurl` | 1386 | 超时curl | **问题**: 9个函数做同一件事,各自有不同的参数风格、错误处理方式、超时设置。调用方随机选用。 **Go重构建议**: 统一为一个 `HttpClient` 结构体,提供 `Get` / `Post` / `PostJSON` 方法,统一超时、重试、日志。 #### 1.2 数据脱敏函数重复(6个) ``` stringObfuscation() - 通用字符串脱敏 idcardObfuscation() - 身份证脱敏 passwordObfuscation() - 密码脱敏 mobileObfuscation() - 手机号脱敏 usernameObfuscation() - 用户名脱敏 mailObfuscation() - 邮箱脱敏 ``` **问题**: 6个函数逻辑几乎相同,只是保留位数不同。 **Go重构建议**: 一个 `Mask(s string, keepStart, keepEnd int)` 函数搞定,或用 `MaskMobile` / `MaskIDCard` 等语义化方法包装。 #### 1.3 渠道查询函数重复(8+个) ```php get_top_channel() // 查顶级渠道 - while循环逐级查parent_id get_union_channel() // 查联盟渠道 - 几乎相同的while循环 get_channel_level() // 查渠道等级 get_top_second_channel_name() // 查顶级二级渠道名 - 又一个while循环 get_top_second_channel_name_v2() // v2优化版 - 注释说"原版N次SQL优化为2次" get_channel_top_by_aggregate() // 聚合渠道顶级 get_channel_name() // 查渠道名 get_complex_channel_name() // 查聚合渠道名 ``` **问题**: - 同一张表 `nw_channel`,8个函数各查一遍 - `get_top_second_channel_name_v2` 注释已经说明原版有性能问题(N次SQL),但原版没删 - 每个函数都独立查DB+缓存,缓存策略不统一 **Go重构建议**: 一个 `ChannelService`,提供 `GetAncestors(channelId)` 返回完整祖先链,所有上层查询都从这个方法派生。缓存统一管理。 #### 1.4 安全问题 ```php // 硬编码加密密钥(第1269-1278行) function opensslEncrypt($data) { $key = 'ukN3KYVdI2sPtjpL'; // 硬编码! return base64_encode(openssl_encrypt($data, 'AES-128-ECB', $key, 0)); } // 调试函数遗留生产环境(第1241行) function dd() { echo Db::getLastSql(); die; } // die()暴露内部信息 die('订单生成失败'.$e->getMessage()); die('签名校验失败 ' . $thisSign); die('用于验签的参数还未设置'); ``` **Go重构建议**: - 密钥走配置/环境变量 - 移除所有调试函数 - 错误信息统一返回码,不暴露内部细节 --- ### 2. 聚合渠道回调:19个控制器文件,代码复制粘贴 `application/complex/controller/` 下有19个渠道文件: ``` Aidou.php, Fengteng.php, Huwei.php, Juside.php, Qixin.php, Shunyouanr.php, Shunyouios.php, Simo.php, Simoquick.php, Vyou.php, Xiaozhi.php, Xigu.php, Xkhyn.php, Yiniu.php, Ziyou.php, Zoulboom.php, Dii.php, Aoyou.php, Complex.php(基类) ``` 每个子类的 `pay()` 方法结构完全相同: 1. 接收POST参数(字段名不同) 2. 调用 `$this->checkOrder()` 验证订单 3. 获取验签参数 4. 签名校验(算法不同) 5. 事务写库 + 通知CP **唯一的差异**: - POST参数字段名(`orderid` vs `m_order_no` vs `cp_orderno`) - 签名算法(md5拼接 vs 自定义sign方法) **Go重构建议**: **策略模式** ```go type ChannelAdapter interface { ParseParams(r *http.Request) (*PayNotify, error) VerifySign(params map[string]string, appkey string) bool } // 注册表 var adapters = map[string]ChannelAdapter{ "aidou": &AidouAdapter{}, "fengteng": &FengtengAdapter{}, // ... } // 统一回调处理 func HandlePayNotify(channel string, w http.ResponseWriter, r *http.Request) { adapter := adapters[channel] params, _ := adapter.ParseParams(r) // ... 统一的验单、签名、写库、通知逻辑 } ``` --- ### 3. 接口版本混乱 | 问题 | 示例 | |------|------| | v1/v2并存无规律 | `/v1.login/index.html`(v1) vs `/v2.user/userinfo`(v2) | | 弃用接口未清理 | `/v2.game_notify/index_v2` 注释"准备弃用" | | 已弃用仍在线 | `/v2.complex_authentication/query` 标记"(弃用)" | | 路径风格混乱 | 有`.html`后缀 vs 无后缀;有`/index.html` vs 直接方法名 | | 命名大小写混用 | `/v2.Captcha/getCaptcha` vs `/v2.forget/resetPwdSendCode` | **Go重构建议**: - 统一API路径风格: `/api/v1/users/login`(RESTful) - 弃用接口直接删除,不带到新系统 - 路径全小写,用 `-` 分隔 --- ### 4. Service层代码管理混乱 ``` GamePayService.php GamePayService_bak.php ← 备份文件 MemberCoinService.php MemberCoinService_bak.php ← 备份文件 ``` **问题**: 用 `_bak` 做版本管理,说明: - 没有使用 Git 分支/标签 - 不确定哪个是最新版 - 重构时需要对比两个文件确认 **Go重构建议**: 直接丢弃 `_bak` 文件,只参考当前版本。如果当前版本有明显问题,基于业务需求重写。 --- ### 5. 151个Model - 存在大量废弃 **快速验证方法**: 检查每个model是否还有控制器在引用。 **Go重构建议**: 不要1:1迁移model。先梳理核心数据表,只迁移有业务流量的表对应的model。 --- ### 6. 其他问题 | 问题 | 说明 | Go建议 | |------|------|--------| | `die()` 做错误处理 | 19个渠道控制器都用 `die()` 终止 | 用 error 返回 + 统一错误响应 | | `unserialize()` 反序列化 | 从DB取参数后直接 `unserialize` | 用 JSON 存储,避免PHP反序列化漏洞 | | `$_POST` 直接取参 | 没有过滤/验证 | 用结构体绑定 + 自动验证 | | 日志路径硬编码 | `LOG_PATH . '../complexPaylog/'` | 配置化,统一日志组件 | | `can_do_request` 限流 | 内联在业务代码中 | 中间件实现限流 | | 缓存策略碎片化 | 各函数自己管理缓存TTL | 统一缓存层,配置化TTL | --- ## 二、Go重构优先级(建议顺序) ### P0 - 核心支付链路(必须先做) 1. **统一回调处理器** - 替代19个渠道控制器 2. **支付服务** - 下单、查询、回调处理 3. **订单服务** - 订单CRUD、状态机 ### P1 - 用户体系 4. **认证服务** - 登录、注册、Token管理 5. **用户服务** - 用户信息、实名认证 6. **短信/验证码服务** - 统一验证码发送 ### P2 - 增值功能 7. **代金券服务** 8. **礼包服务** 9. **充值服务** ### P3 - 辅助功能 10. **渠道管理服务** - 替代8个渠道查询函数 11. **配置服务** - 替代散落各处的配置读取 12. **通知服务** - 钉钉告警等 --- ## 三、不建议迁移的内容 | 内容 | 原因 | |------|------| | `_bak` 文件 | 废弃代码 | | `dd()` 等调试函数 | 调试遗留 | | `is_mobile_request()` | 现代浏览器UA已不适用 | | `arrayColumnByObject()` | PHP7.0+已有 `array_column` | | `v2.game_notify/index_v2` | 已标记弃用 | | `v2.complex_authentication/query` | 已标记弃用 | | `gh/channel_data_summary` | 已被v2替代 | | 所有 `die()` 错误处理 | 改为标准错误响应 | --- ## 四、需要确认的问题 在开始Go重构前,建议确认: 1. **渠道回调**: 19个渠道哪些还在用?可以联系业务方确认,废弃的直接不迁移 2. **v1接口**: 哪些v1接口客户端还在调用?能否强制升级到v2 3. **数据表**: 151个model对应的实际表,哪些还有数据在写入 4. **第三方SDK**: 抖音、支付宝等SDK是否需要更新到最新版本 5. **签名规则**: 现有签名算法是否需要兼容,还是可以统一新规则