5.6 KiB
Executable File
5.6 KiB
Executable File
企业微信 员工↔客户 IM 功能部署说明
本文档对应「管理后台 IM」功能(admin/src/views/chat),负责在后端/后台视角下的收/发一对一消息。
- 发送:企业群发
add_msg_template(员工本人身份 + 手机端确认) - 接收:会话内容存档(官方 C SDK + RSA 解密 + 计划任务拉取)
- 老回调接口
QywxExternalContactCallbackController仍用于 添加/编辑/删除外部联系人 事件,不承载消息内容。
1. 数据表
执行一次:
mysql -u<user> -p<pass> <db> < server/database/migrations/2026_04_20_create_qywx_msg_tables.sql
新增 5 张:qywx_msg_session、qywx_msg_archive、qywx_msg_archive_media、qywx_msg_send_task、qywx_msg_archive_cursor。
2. 配置(server/config/pay.php → wechat_work)
'customer_contact_secret' => '客户联系 Secret', // 已有:发消息 / 客户列表
// 会话内容存档
'msgaudit_enabled' => true, // 开关
'msgaudit_secret' => '会话存档 Secret', // 独立应用 Secret
'msgaudit_public_key_ver' => 1, // 管理后台上传公钥返回的版本号
'msgaudit_private_key_path'=> '/data/qywx/priv.pem', // RSA 私钥文件路径(建议)
'msgaudit_sdk_lib_path' => '/data/qywx/libWeWorkFinanceSdk_C.so', // SDK 动态库
'msgaudit_timeout' => 60,
'msgaudit_limit' => 500,
msgaudit_enabled = false或msgaudit_sdk_lib_path留空时,后端不会崩溃——拉取命令会以noop方式返回,方便「先上线、再接 SDK」。
3. C SDK & 私钥准备
- 从企微管理后台 → 安全与合规 → 会话内容存档 → SDK 下载区,下载官方 C SDK。
- Linux 部署
libWeWorkFinanceSdk_C.so到/data/qywx/,并确保 PHP-FPM 账户有可执行权限。 - 安装 PHP FFI:
php.ini开启ffi.enable=true(preload 场景用preload,CLI + FPM 用true)。 - 生成 RSA 密钥对:
openssl genrsa -out priv.pem 2048 && openssl rsa -in priv.pem -pubout -out pub.pem - 企微后台上传
pub.pem→ 记录返回的public_key_ver→ 回填到配置。 - 私钥
priv.pem放到msgaudit_private_key_path指向的位置,权限 600。
轮换公钥时,保留历史
public_key_ver → private_key映射(SDK 会用旧消息的版本号去找旧私钥)。如需多版本,代码已预留:在WeComFinanceSdkClient::loadPrivateKeys()同一配置下,可额外传入msgaudit_private_keys数组形式支持多版本(自行扩展)。
4. 计划任务
推荐 30 秒一次(企微限制:每分钟不超过 600 次)。
Linux crontab(每 30s 跑一次的 2 行写法):
* * * * * cd /path/to/server && /usr/bin/php think qywx:sync-msg-archive --download >/dev/null 2>&1
* * * * * cd /path/to/server && sleep 30 && /usr/bin/php think qywx:sync-msg-archive --download >/dev/null 2>&1
可选:把媒体下载拆开、并发运行:
* * * * * cd /path/to/server && /usr/bin/php think qywx:sync-msg-archive >/dev/null 2>&1
*/2 * * * * cd /path/to/server && /usr/bin/php think qywx:sync-msg-archive --only-media --max-media=500 >/dev/null 2>&1
命令已做 flock 互斥(runtime/qywx_msg_archive.lock),并发多跑也不会重复写。
5. 权限与菜单
后台菜单需新增一条,路径 /chat(或自定义),component 指向 views/chat/index.vue。
建议开启菜单权限控制:仅运营/客服组可见。API 路由前缀为 qywx.message/*,请在 adminapi 权限中心相应配置。
6. 使用流程
- 打开「IM」页面,系统自动拉取会话列表。
- 左侧可按员工筛选;选中会话后中间展示消息流,8 秒轮询新消息。
- 在底部输入框输入文本/添加附件(图片/视频/文件/链接/小程序)→ 点击「发送」。
- 后端创建企微
add_msg_template任务,员工手机会收到确认弹窗,确认后客户即可收到。 - 已发送任务可在右侧「发送任务」Tab 查看送达详情。
7. 故障排查
| 症状 | 排查 |
|---|---|
| 前端顶部提示「会话存档 SDK 不可用」 | 查 config/pay.php msgaudit_* 配置 + libWeWorkFinanceSdk_C.so 路径 + ffi.enable + 日志 runtime/log/。调 GET /adminapi/qywx.message/archive_status 看诊断。 |
| 消息拉取无数据 | php think qywx:sync-msg-archive -vvv;看 qywx_msg_archive_cursor 表 seq 是否推进;确认企微已开通会话存档 License 并勾选目标员工。 |
| 媒体文件一直下载中 | qywx_msg_archive_media.status / retry_count / last_error;路径 runtime/qywx_msg_media/ 写权限;SDK GetMediaData 超时调大 msgaudit_timeout。 |
| 发送「消息内容不能为空」 | 文本 + 附件都为空;或附件上传失败导致没有 media_id,面板会红色报错。 |
| 发送成功但客户未收到 | 员工手机端漏点确认;或该员工未启用企业群发能力;查 qywx_msg_send_task.fail_list & 右侧「送达详情」。 |
| 需要撤回消息 | 企微规则:群发任务已提交后无法撤回单条;会话存档里会记录 recall 动作并在前端打「已撤回」标记。 |
8. 未来扩展点
- 多版本 RSA 私钥轮换:
WeComFinanceSdkClient::loadPrivateKeys()改造为读取msgaudit_private_keys数组,key 为public_key_ver。 - WebSocket 推送新消息:在
QywxMsgArchiveService::persistBatch()写入后发布到 Workerman / Swoole,前端改成订阅(当前是 8s 轮询)。 - 群聊发送:企微「客户群 SOP」接口,当前 UI 仅展示群会话消息不允许发送(
canSendMessage为 false)。