feat: 添加阿里云短信服务支持并优化验证码逻辑

- 引入 alibabacloud/dysmsapi-20170525 依赖,集成阿里云短信服务
- 将短信验证码从6位改为4位,优化用户体验
- 添加聚水潭商品按时间范围同步功能,支持分页拉取
- 增强Cron任务异常处理,添加错误日志记录
- 修复系统附件服务中图片路径处理逻辑
- 更新阿里云SDK相关组件至最新版本
- 添加think-trace调试扩展,便于问题排查
- 优化跨域中间件,使用str_contains替代strpos
This commit is contained in:
2026-04-30 15:19:40 +08:00
parent 0334fef6c1
commit c7f85ffbda
565 changed files with 59742 additions and 3391 deletions

View File

@@ -0,0 +1,7 @@
- [ ] 已列出回调入口路由与调用链路:`/api/work/serve` -> `Wechat::work()` -> `WechatServices::workServe()` -> `Work::serve()`
- [ ] 已列出 Work 基础配置项与系统配置键映射:`corp_id/token/aes_key` -> `wechat_work_corpid/wechat_work_token/wechat_work_aes_key`
- [ ] 已列出 Work 应用配置项(通讯录/客户联系/自建应用)与系统配置键:`wechat_work_address_secret`、`wechat_work_user_secret`、`wechat_work_build_agent_id`、`wechat_work_build_secret`
- [ ] 已说明 `Failed to decode request contents.` 的触发原因与正确校验方式(企业微信 GET 校验、POST 加密回调)
- [ ] 已给出“域名无法配置”的替代接入方案,并明确透明转发必须保持 query/body 不变
- [ ] 已给出“无法接入回调”的降级方案:使用后台同步成员能力,并标注其删除/全量重建的副作用
- [ ](可选增强)若实现 `wechat_work_callback_url`,后台表单能正确展示并可复制,空值时回退到 `site_url . '/api/work/serve'`

View File

@@ -0,0 +1,76 @@
# 企业微信通讯录配置项使用逻辑与回调域名替代方案 Spec
## Why
现网企业微信通讯录/客户联系能力依赖“接收事件服务器”回调地址(如 `https://shop.douba.top/api/work/serve`)来接收成员/部门/客户等变更事件。实际部署中可能遇到企业微信后台无法填写或无法通过校验(域名限制、HTTPS 证书、网络可达性、网关/WAF 等)导致无法上线。
本 Spec 的目标是:
- 梳理后端企业微信通讯录相关配置项在代码中的读取、组装与使用路径,便于定位配置错误。
- 给出当企业微信侧无法配置项目域名时的可行替代配置方式(运维/网络层方案 + 业务层降级方案)。
- (可选增强)提供独立的“企业微信回调地址”配置项,仅用于展示与复制,避免必须修改全站 `site_url`。
## Current Behavior(现状)
### 1) 回调路由入口
- 企业微信回调入口固定为 `/api/work/serve`,路由映射到 `app\controller\api\v1\wechat\Wechat::work()`,最终调用 `crmeb\services\wechat\Work::serve()`。
- 后台配置表单中“服务器地址”字段为只读展示:`sys_config('site_url') . '/api/work/serve'`。
### 2) 配置项来源与组装
企业微信配置通过两层组装后交给 EasyWeChat:
- **基础配置**(用于验签/解密/加密回复):`corp_id`、`token`、`aes_key`
- 映射到系统配置键:`wechat_work_corpid`、`wechat_work_token`、`wechat_work_aes_key`
- **应用配置**(用于调用不同能力 API):按类型注入 `secret` / `agent_id`
- 通讯录同步:`wechat_work_address_secret`
- 客户联系:`wechat_work_user_secret`
- 自建应用:`wechat_work_build_agent_id` + `wechat_work_build_secret`
### 3) 回调验签与事件处理
- `Work::serve()` 调用 EasyWeChat Work Server 完成 URL 校验与消息解密;解密后消息交给 `app\listener\wechat\WorkListener` 分发。
- `WorkListener` 处理的关键事件包含:
- 通讯录事件:`change_contact`(成员/部门增删改)
- 客户事件:`change_external_contact`
- 客户群事件:`change_external_chat`
- 客户标签事件:`change_external_tag`
## Problems(常见问题)
- 直接在浏览器访问回调 URL 或用普通 HTTP 客户端随意请求,会触发 EasyWeChat 的解析失败,出现 `Failed to decode request contents.`;这不代表系统异常,只是请求不是企业微信回调协议(缺少 `echostr/msg_signature` 或正文不是企业微信 XML/加密格式)。
- 企业微信后台“接收事件服务器”校验失败,常见原因:
- URL 不可公网访问(内网/防火墙/白名单/运营商限制)
- HTTPS 证书链不完整/过期/不被信任
- 反向代理/WAF 改写了 query/body(导致 `msg_signature` 校验失败)
- 回调域名无法在企业微信侧配置(企业侧安全策略或域名限制)
## What Changes(拟新增/调整)
### A. 文档化与定位指引(必做)
- 输出一份“配置项—代码使用点—故障排查清单”的说明(本 Spec + checklist)。
- 明确哪些配置影响“回调校验”,哪些配置只影响“API 调用”。
### B. 回调域名替代方案(不改代码即可落地)
- 允许使用“可在企业微信侧配置的域名/网关”作为回调入口,通过透明转发(反向代理/网关/隧道)转发到实际项目的 `/api/work/serve`。
- 允许在无法接入回调时,使用后台已有的“同步企业微信成员”能力做业务降级(非实时)。
### C. 可选增强:增加独立的回调地址配置项(需要改代码)
新增系统配置键(示例):`wechat_work_callback_url`
- 用途:仅用于后台表单展示/复制,默认值仍为 `site_url . '/api/work/serve'`。
- 不改变实际回调逻辑(仍然由路由 `/api/work/serve` 接收);目的是让运维能把“实际对外可用的回调域名”记录在系统里,减少误配。
## Requirements
### Requirement 1: 配置项可追溯
系统 SHALL 明确以下配置项的用途与作用范围:
- `wechat_work_corpid` / `wechat_work_token` / `wechat_work_aes_key`:影响回调验签解密与企业微信身份
- `wechat_work_address_secret`:影响通讯录同步相关 API(拉部门、拉成员等)
- `wechat_work_user_secret`:影响客户联系相关 API
- `wechat_work_build_agent_id` + `wechat_work_build_secret`:影响自建应用相关 API
### Requirement 2: 当域名无法配置时可替代接入
在企业微信后台无法配置项目域名时,运维 SHALL 能选择以下一种方式完成回调接入:
- 方案 A:配置一个企业微信可接受的域名作为回调入口,并反向代理透明转发到本项目 `/api/work/serve`
- 方案 B:无法接入回调时,使用后台“同步企业微信成员”接口进行人工/定时全量同步作为降级(承认非实时)
### Requirement 3(可选): 回调地址可配置展示
系统 SHOULD 提供 `wechat_work_callback_url` 配置项用于展示与复制,默认回退到 `site_url . '/api/work/serve'`。
## Impact(影响面)
### 不改代码即可采用
- 仅影响运维部署方式与企业微信后台填写的回调 URL。
### 若做可选增强
- 影响后台“企业微信配置”表单展示字段。

View File

@@ -0,0 +1,19 @@
# Tasks
- [ ] Task 1: 梳理配置项与使用链路(文档输出)
- [ ] SubTask 1.1: 汇总企业微信回调入口、路由、控制器与服务调用链路。
- [ ] SubTask 1.2: 汇总企业微信配置项(sys_config 键)与代码读取点、作用范围(回调验签 vs API 调用)。
- [ ] SubTask 1.3: 汇总回调事件类型与本地处理服务(通讯录/客户/客户群/标签)。
- [ ] Task 2: 给出“无法配置域名”的替代接入方式(运维/网络层)
- [ ] SubTask 2.1: 反向代理/网关透明转发方案(保持 query/body 不变,避免验签失败)。
- [ ] SubTask 2.2: 备用公网域名/子域名方案(同服务器多域名证书)。
- [ ] SubTask 2.3: 隧道映射方案(frp/ngrok 类,仅建议测试或临时)。
- [ ] Task 3: 给出“无法接入回调”的业务降级方式(不改代码)
- [ ] SubTask 3.1: 使用后台“同步企业微信成员”接口触发全量同步(说明副作用与适用场景)。
- [ ] SubTask 3.2: 建议定时执行策略(如低频全量同步,或按部门增量同步的可拓展方向)。
- [ ] Task 4(可选增强): 增加独立的回调地址展示配置项
- [ ] SubTask 4.1: 增加系统配置键 `wechat_work_callback_url`(若已有配置表/初始化机制则按既有方式接入)。
- [ ] SubTask 4.2: 修改企业微信配置表单展示字段,优先展示 `wechat_work_callback_url`,空则回退 `site_url . '/api/work/serve'`。