MakeFortune 中的企业微信能力是一套完整的外部平台子系统。源码包含服务商应用与授权企业配置、成员和部门同步、客户群管理、开放数据组件,以及接口许可账号和订单。它为社群任务提供组织与执行对象,但不等同于任务业务本身。
能力范围
| 能力 | 主要对象 | 作用 |
|---|---|---|
| 服务商应用 | 服务商企业、第三方应用、Suite | 保存应用身份、回调配置和授权范围 |
| 企业授权 | 授权企业、永久授权码、企业访问令牌 | 建立第三方应用与客户企业的授权关系 |
| 组织同步 | 部门、成员、服务人员 | 为后台选择器、任务执行和数据归属提供组织快照 |
| 客户群同步 | 群聊、群主、成员和同步状态 | 支撑群邀请、群运营和任务结果关联 |
| 开放数据 | 企业、成员和部门显示信息 | 在前端通过企业微信开放数据组件展示受保护名称 |
| 接口许可 | 许可账号、订单、激活状态 | 管理购买、同步和激活,不与普通商品订单混用 |
总体拓扑
flowchart LR Admin[运营管理端] --> API[MakeFortune API] API --> Adapter[企业微信适配层] WeCom[企业微信开放平台] --> Callback[授权与事件回调] Callback --> Adapter Adapter --> Token[SuiteTicket / AccessToken] Adapter --> Org[授权企业 / 部门 / 成员] Adapter --> Chats[客户群 / 群成员] Adapter --> License[接口许可账号 / 订单] Org --> Mission[加好友 / 群邀请 / 朋友圈任务] Chats --> Mission API --> DB[(业务数据库)] Token --> Redis[(Redis 缓存与锁)]
图中的适配层负责企业微信协议、令牌和错误转换;社群任务只使用已经同步并验证归属的企业、成员和群聊对象。这样企业微信接口变化不会直接扩散到活动和任务领域。
关键身份
| 标识 | 所属范围 | 设计注意点 |
|---|---|---|
服务商 corp_id |
服务商企业 | 与客户企业 ID 分开保存 |
suite_id |
第三方应用 | 决定回调、权限和授权企业集合 |
授权企业 corpid |
单个客户企业 | 所有部门、成员和群聊都必须带企业归属 |
userid |
授权企业内成员 | 只在当前企业范围内解释 |
department_id |
授权企业内部门 | 同步父子层级和排序,不使用名称作为主键 |
chat_id |
客户群 | 记录群主和最近同步时间,成员列表单独维护 |
| 许可订单号 | 接口许可 | 与业务订单分表或使用明确订单类型 |
同一个成员名可能出现在多个授权企业中,因此任何查询都至少包含授权企业和成员标识。页面展示名称可以由开放数据组件解析,数据库关系不能依赖展示文本。
第三方应用授权流程
sequenceDiagram participant W as 企业微信 participant C as 回调入口 participant A as 企业微信适配层 participant D as 数据库 participant J as 同步任务 W->>C: 推送 SuiteTicket C->>A: 验签、解密并校验 Suite A->>D: 幂等保存最新 Ticket A->>W: 换取 SuiteAccessToken 与预授权码 W-->>A: 返回短期凭据 W->>C: 推送企业授权结果 C->>A: 使用临时授权码换取永久授权信息 A->>D: 保存授权企业与权限范围 A->>J: 提交首次组织同步任务 J->>W: 拉取部门、成员和客户群 J->>D: 按企业范围增量写入
回调入口只做验签、解密、幂等落库和任务投递,并尽快返回成功。通讯录和群聊拉取可能耗时或触发限流,不应在回调请求中同步完成。
令牌与回调
第三方应用会同时出现 SuiteTicket、SuiteAccessToken、企业永久授权码和企业 AccessToken。它们的来源、有效期和权限不同,不能共用一个无类型的 Token 字段。
建议为每类凭据记录应用、授权企业、过期时间和最后刷新时间。短期 Token 放入 Redis 时使用 suite_id 与 corpid 组成命名空间,并在过期前刷新;刷新过程加分布式锁,避免多个请求同时击穿企业微信接口。
所有回调都需要校验签名、时间戳、随机数、接收方和 Suite 归属。原始事件保存事件 ID 或稳定摘要,重复推送只更新接收次数,不重复触发授权、同步或激活操作。
组织与客户群同步
首次授权完成后进行全量同步,日常由事件回调和定时校准共同维护:
- 拉取部门并按父部门建立层级;
- 按部门或游标拉取成员,保存企业内
userid与状态; - 拉取客户群列表,再按群 ID 同步详情和成员;
- 对外部已删除对象标记失效,不直接物理删除历史任务引用;
- 保存游标、最后成功时间、错误码和重试次数;
- 全量校准与实时事件使用同一幂等写入逻辑。
批量同步按授权企业排队并限制并发。接口限流时读取平台返回的重试信息,采用延迟重试,而不是在 Web 请求中循环等待。
与社群任务的关系
加好友、群邀请和朋友圈分享等任务会选择授权企业、执行成员或客户群。任务创建时保存企业、成员、群聊的稳定标识和必要快照;执行前再次检查授权状态、成员可用性和应用权限。
企业微信回调或同步结果只更新平台映射,不直接把任务标记为成功。任务状态由任务执行记录和可验证结果决定,避免一次组织同步误改运营统计。
开放数据组件
管理端使用开放数据组件展示成员或部门名称时,需要从服务端获取当前页面的 JSSDK 配置。服务端按页面 URL、Suite 和授权企业生成签名,前端只获得本次页面所需的短期参数。
开放数据解决的是受保护名称的展示,不替代数据库关系。列表筛选、任务归属和权限判断仍使用 corpid、userid、department_id 与 chat_id。
接口许可生命周期
接口许可包含账号、购买订单、激活和同步状态。推荐使用明确状态机:
待下单 → 已下单 → 待支付/确认 → 可激活 → 已激活 → 已过期或失效
创建订单使用本地幂等业务号;同步远端订单时只更新企业微信负责的状态和有效期;激活操作校验授权企业、成员和可用账号数量。许可订单与内容、会员或活动订单分开,避免退款和结算规则互相影响。
安全与运维
- SuiteSecret、Token、EncodingAESKey、企业永久授权码和 AccessToken 进入密钥服务或环境配置,不写入前端和日志;
- 授权企业只能访问自己的部门、成员、群聊和许可数据,后台接口强制附加
corpid范围; - 回调日志记录请求 ID、Suite、企业和事件类型,消息正文与敏感凭据脱敏;
- 对授权取消、权限变更、成员离职和群解散建立失效处理;
- 监控 Token 刷新失败、回调积压、同步延迟、限流次数和许可激活失败;
- 为每个授权企业提供最后同步时间和手动重试入口,但禁止并发启动多次全量同步。
改进顺序
- 把源码中分散的企业微信配置收口到统一适配层,并轮换历史固定凭据;
- 为授权、组织、群聊和许可建立带企业范围的唯一约束;
- 将回调处理改为快速落库加异步任务,统一事件幂等键;
- 为同步任务补充游标、锁、限流退避、失败重放和可观测指标;
- 让社群任务只依赖内部组织模型,不直接调用企业微信 SDK;
- 明确授权取消后的数据保留、任务停止和敏感信息清理策略。
企业微信是 MakeFortune 的外部平台能力,dd、sj 等业务应用只是它的使用方。保持这条依赖方向,才能在不拆仓库的前提下继续扩展业务,同时控制授权、同步和安全风险。