不是简单搬代码,而是借重构机会解决历史债务
这是项目最大的技术债。所有工具函数堆在一个文件里,没有分类、没有接口约束。
| 函数名 | 行数 | 功能 |
|---|---|---|
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 方法,统一超时、重试、日志。
stringObfuscation() - 通用字符串脱敏
idcardObfuscation() - 身份证脱敏
passwordObfuscation() - 密码脱敏
mobileObfuscation() - 手机号脱敏
usernameObfuscation() - 用户名脱敏
mailObfuscation() - 邮箱脱敏
问题: 6个函数逻辑几乎相同,只是保留位数不同。
Go重构建议: 一个 Mask(s string, keepStart, keepEnd int) 函数搞定,或用 MaskMobile / MaskIDCard 等语义化方法包装。
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),但原版没删Go重构建议: 一个 ChannelService,提供 GetAncestors(channelId) 返回完整祖先链,所有上层查询都从这个方法派生。缓存统一管理。
// 硬编码加密密钥(第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重构建议:
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() 方法结构完全相同:
$this->checkOrder() 验证订单唯一的差异:
orderid vs m_order_no vs cp_orderno)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)
// ... 统一的验单、签名、写库、通知逻辑
}
| 问题 | 示例 |
|---|---|
| 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/v1/users/login(RESTful)- 分隔GamePayService.php
GamePayService_bak.php ← 备份文件
MemberCoinService.php
MemberCoinService_bak.php ← 备份文件
问题: 用 _bak 做版本管理,说明:
Go重构建议: 直接丢弃 _bak 文件,只参考当前版本。如果当前版本有明显问题,基于业务需求重写。
快速验证方法: 检查每个model是否还有控制器在引用。
Go重构建议: 不要1:1迁移model。先梳理核心数据表,只迁移有业务流量的表对应的model。
| 问题 | 说明 | Go建议 |
|---|---|---|
die() 做错误处理 |
19个渠道控制器都用 die() 终止 |
用 error 返回 + 统一错误响应 |
unserialize() 反序列化 |
从DB取参数后直接 unserialize |
用 JSON 存储,避免PHP反序列化漏洞 |
$_POST 直接取参 |
没有过滤/验证 | 用结构体绑定 + 自动验证 |
| 日志路径硬编码 | LOG_PATH . '../complexPaylog/' |
配置化,统一日志组件 |
can_do_request 限流 |
内联在业务代码中 | 中间件实现限流 |
| 缓存策略碎片化 | 各函数自己管理缓存TTL | 统一缓存层,配置化TTL |
| 内容 | 原因 |
|---|---|
_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重构前,建议确认: