This commit is contained in:
Your Name
2026-09-01 11:26:47 +08:00
parent 5bd5eae62d
commit 398f9f3726
357 changed files with 733 additions and 343 deletions
@@ -1,20 +1,20 @@
# 企业微信推广自动化部署与验收
此实现覆盖推广渠道欢迎语、企业标签、客户备注/描述及原客户同步补偿。它不会覆盖企业微信后台欢迎语设置,也不意味着企业已开通接口权限。官方能力及限制见 [核验报告](research/wecom-promotion-api-capabilities.md)。
此实现覆盖推广渠道欢迎语、企业标签、客户备注/描述及原客户同步补偿。企微获客链接接口不提供欢迎语和标签配置字段,因此这些设置不会显示在企微链接详情的“配置”入口,而是在客户添加回调后通过客户联系接口执行;它不会覆盖企业微信后台欢迎语设置,也不意味着企业已开通接口权限。官方能力及限制见 [核验报告](research/wecom-promotion-api-capabilities.md)。
## 部署顺序
1. 先执行 `server/sql/1.9.20260831/add_wecom_promotion_automation.sql`。脚本仅使用 `CREATE TABLE IF NOT EXISTS`默认表前缀 `zyt_`实际前缀不同须由部署人员调整。本开发任务没有执行业务数据库迁移。
1. 新环境先执行 `server/sql/1.9.20260831/add_wecom_promotion_automation.sql`;已建四张自动化表的环境再执行 `server/sql/1.9.20260901/upgrade_qywx_promotion_automation_runtime.sql`,补登记分钟补偿和素材刷新任务。默认表前缀 `zyt_`实际前缀不同须由部署人员调整。本开发任务没有执行业务数据库迁移。
2. 部署 PHP 代码。为 PHP-FPM、CLI worker 使用同一项目目录 `server/runtime/qywx_promotion_private/`,授予应用运行用户读写权限。目录必须位于 Web 根目录之外,禁止静态文件映射;保留源文件,不能随意清理该目录。
3. 配置客户联系“可调用应用”,优先使用创建获客链接的同一自建应用。代码默认使用 `qywx_customer_acquisition.secret`,无该值才使用 `pay.wechat_work.customer_contact_secret`。需要明确覆盖时设置 `WECHAT_WORK_PROMOTION_CONTACT_SECRET`。不会使用 `external_pay_secret`。新接入不要依赖已受官方限制的客户联系系统应用 Secret。检查应用可见范围、可信 IP、外部联系人变更事件订阅;欢迎语回调必须来自可调用应用的相应配置。
4. 建议设置至少32字符的随机 `WECHAT_WORK_PROMOTION_ENCRYPTION_KEY`,所有 API/CLI 节点保持一致。未设置时会自动在项目私有目录生成 `welcome.key`(0600)。多节点使用共享源文件目录和一致密钥;更换密钥前先处理/过期并清空待处理欢迎码。
5. 在启用渠道欢迎语之前,启动并监控下面的常驻 worker,安装分钟补偿和素材预热。仅配置分钟任务不足以发送欢迎语
5. 在启用渠道欢迎语之前,启动并监控下面的常驻 worker,并确保系统 `crontab` 调度进程正常运行。回调会立即尝试欢迎语和标签;常驻 worker 负责欢迎码窗口内的快速重试,分钟任务负责其余补偿和素材预热
若旧版脚本在 `welcome_cipher` 字段的 `COMMENT=` 处报 MySQL 1064,请重新打开已修正的 SQL 文件并完整重跑。字段注释必须使用 `COMMENT '内容'`(不带等号);表级的 `COMMENT='内容'` 是合法语法,无须修改。脚本中的四张表都使用 `CREATE TABLE IF NOT EXISTS`,已成功创建的表会保留,不需要删表。四张表全部创建成功后再启动 worker。
## 必须运行的进程
欢迎码只有20秒有效。验签回调中只做数据库和加密操作,并及时返回;欢迎语由独立常驻进程秒级消费,不能等待普通客户同步或临时素材上传
欢迎码只有20秒有效。验签回调入库后会立即尝试欢迎语,并为正式客户立即添加标签;普通客户同步、备注、范围更新和素材上传等慢动作不进入回调。独立常驻进程继续秒级消费明确可重试的欢迎语任务
```sh
cd /path/to/server
@@ -41,14 +41,14 @@ stdout_logfile=/var/log/qywx-promotion-welcome.log
stderr_logfile=/var/log/qywx-promotion-welcome-error.log
```
每分钟运行补偿每5分钟预热素材。以下为部署样例,不代表本任务已经安装这些定时任务
迁移会把每分钟补偿每5分钟素材预热登记到 `zyt_dev_crontab`;部署仍须保证 `php think crontab` 被系统每分钟触发。若部署不使用内置任务表,可改用以下系统 cron
```cron
* * * * * cd /path/to/server && /usr/bin/flock -n /tmp/qywx-promotion-retry.lock /usr/bin/php think qywx:retry-promotion-automation
*/5 * * * * cd /path/to/server && /usr/bin/flock -n /tmp/qywx-promotion-media.lock /usr/bin/php think qywx:refresh-promotion-media
```
现有 `qywx:sync-promotion-ranges``qywx:retry-customer-acquisition-events` 也须保留。新推广配置事件的标签、备注、描述、成员记账、范围更新、客户同步由补偿任务执行处理延迟通常不超过一分钟,繁忙时可能更长。不要把这些慢速动作塞进欢迎语worker。方案日上限是回调后的统计控制,不是企微并发建联的硬性上限。
现有 `qywx:sync-promotion-ranges``qywx:retry-customer-acquisition-events` 也须保留。新推广配置事件优先在回调中添加标签;失败标签以及备注、描述、成员记账、范围更新、客户同步由补偿任务执行处理延迟通常不超过一分钟。不要把这些慢速动作塞进欢迎语worker。方案日上限是回调后的统计控制,不是企微并发建联的硬性上限。
## 配置与素材契约
@@ -65,10 +65,10 @@ stderr_logfile=/var/log/qywx-promotion-welcome-error.log
## 回调、幂等与失败策略
- 入口仅在 EasyWeChat 已验签/解密的 `change_external_contact` listener 中调用 `enqueueVerifiedEvent()`;不得把此服务直接作为未验签HTTP接口。
- 入口仅在 EasyWeChat 已验签/解密的 `change_external_contact` listener 中调用 `enqueueVerifiedEvent($event, true)`;不得把此服务直接作为未验签HTTP接口。
- 优先用 `State=zyt_pool:{id}`,无State时才使用事件实际存在的 `LinkId/LinkID`。必须存在正常的推广方案、非删除成员关系、官方有效链接、新配置记录。仅有可猜测的State不是授权。普通客户事件、无新配置旧方案、迁移尚未安装时保留旧同步路径;不会让所有客户突然依赖新worker。
- 正式客户add可执行全部动作;半客户add_half只处理欢迎语,不提前打标签、改备注或落正式客户表。事件重复通过唯一事件键去重;同一WelcomeCode在half/add之间通过唯一摘要索引只分配一次消费权。
- 队列持久化失败会抛专用异常,listener不吞掉,HTTP返回500供企微重投。成功入队后的业务失败由持久任务补偿,不影响回调应答
- 队列持久化失败会抛专用异常,listener不吞掉,HTTP返回500供企微重投。即时发送结果按分动作持久化;明确可重试的失败由持久任务补偿,事件重投不会重复发送已完成动作
- 每条任务保存配置快照;分时欢迎语按事件时间和Asia/Shanghai选择,未命中用基础欢迎语。`default``none`均不发送本系统欢迎语,不能抑制企业微信管理端或其他应用发送。
- 欢迎码以AES-256-GCM短存;动作进入sent/skipped/expired/uncertain/failed后清除密文。既有客户事件raw字段现在移除WelcomeCode;审计中无明文code/token、上游请求或Guzzle异常链。历史已有raw数据需要另外评估清理,本次未改历史记录。
- 发送前先持久化running。网络超时、无法解析响应、HTTP失败,或进程在发送后记录成功前崩溃,均记为uncertain,清理密文并停止自动重发,避免重复推送;需通过企微实际聊天结果人工核对。