搭完"积木"之后,我给开源框架接通了企微和开放平台

0 阅读15分钟

上次聊了怎么用"搭积木"的方式搭后台,这次聊聊怎么把积木搭进企业生态——企微集成 + 能力开放平台。


写在前面:后台框架的"孤岛困境"

上一篇《当 90% 的中后台还在重复造轮子》发出后,不少同学在评论区问了一个问题:

"框架内部能力确实全,但企业里不可能只用你一个系统。审批要推到企微,外部系统要调你的接口,这些怎么搞?"

好问题。说实话,这也是我做完低代码、工作流、AI 之后,一直在想的事。

一个后台框架如果只管自己内部那摊事,做得再好也是信息孤岛。

企业真实的长这样:

  • 员工日常用企业微信沟通,审批、通知、待办都希望在企微里完成
  • 外部 ERP / CRM / 小程序要调你的业务接口,不能每个对接方都给一套账号密码
  • 管理员配完企微和开放平台后,自己都不知道配得对不对,得让开发去翻日志
  • 企微通讯录一变,本地用户表就脱节了,新员工登不进来,离职员工还在系统里

这些事单独拎出来都不难,难的是每接一个项目都要重来一遍。于是我把企业微信协同和能力开放做进了 Forge,今天聊聊这两块。

先放个演示地址,文章里说的所有东西都能在线试:
www.dlforgelab.com:8084/forge/login (账号 admin / 123456)


一、企业微信集成:不是"扫码登录",是整个协同层

先说最大的误解——很多人以为"企微集成"就是加个企业微信扫码登录。不是。

1.1 多数框架的企微集成长什么样

能力多数框架的现状
登录支持企微扫码,但 OAuth 回调直接把用户信息丢给前端,前端再提交后端
通讯录手动导入或写一次性脚本同步,人员变动靠人工记得改
消息自己写企微 API 调用代码,散落在各个业务模块里
待办企微收不到审批通知,或者收到后点了跳过去是一个没有鉴权的 URL
安全Secret 明文存数据库,回调验签全靠自己手写,出了问题不好查

核心问题:每加一个平台(飞书、钉钉),这些逻辑全要再写一遍。

1.2 Forge 的做法:先建通用底座,企微只是第一个适配器

我没有把企微逻辑写死在登录、用户、消息、流程这些模块里。而是先做了一层平台无关的企业协同 SPI,企业微信只是它的第一个完整适配器。

架构长这样:

forge-starter-collaboration(通用 SPI 层)
  ├── Provider Connector 接口        ← 飞书/钉钉以后只需实现这个
  ├── 能力枚举(LOGIN/DIRECTORY/MESSAGE/TODO)
  ├── 统一上下文 + Provider Registry
  └── 合同测试套件 + Fake Provider    ← 证明编排层不依赖企微分支

forge-plugin-collaboration(编排插件)
  ├── 连接管理(一个租户可配多个企业连接)
  ├── 应用管理(每个连接下可挂多个物理应用,Secret 只存一份)
  ├── 通讯录同步(全量 + 增量 + 冲突处理 + 问题单)
  ├── 消息投递(统一 COLLABORATION 渠道,逐接收人结果)
  ├── 待办投影(Flowable 任务 → 企微卡片,状态始终以 Forge 为准)
  └── 回调收件箱(验签/解密/防重放/去重/异步补偿)

一句话总结:飞书、钉钉后续只需实现 Connector,不动组织同步、消息、待办和运维主链路。

1.3 安全这件事,我花了最多精力

企业集成涉及身份认证、人员停用和流程操作,安全出问题就是大事。几个关键设计:

登录链路彻底重写了 OAuth 流程:

环节旧做法(多数框架)Forge 的做法
OAuth state前端生成或不校验服务端一次性生成并保存,绑定连接/租户/动作
回调返回完整 AuthUser 返回前端只返回短期一次性socialTicket,前端拿不到第三方用户信息
身份来源信任前端提交的 socialUuid只认服务端校验过的连接和外部身份
账号合并手机号/邮箱相同自动合并禁止自动合并,只认通讯录已建立的映射,防止错误合并员工

凭据安全:

所有 Secret、Token、Callback Token、EncodingAESKey 全部走版本化 AES-GCM 认证加密存储,管理端只返回"已配置"状态和固定掩码。空值保留(不改不动),轮换用比较更新防并发恢复旧值。认证加密不可用时失败关闭,不回退明文

待办回调不能越权审批:

企微卡片点击后,Forge 重新校验:外部身份 → 接收人 → 租户 → 任务当前状态 → 办理权限。任务已完成、已撤回或操作者无权时,返回业务已失效并更新外部卡片,不重复执行。

1.4 通讯录同步:不是一次性脚本,是完整运维闭环

能力说明
全量同步读取完整快照 → 校验父子关系 → 分阶段落库 → 成功后才处理未出现记录
增量处理成员新增/变更/离职/转部门,定时全量校准兜底
权限边界同步只管本连接拥有的映射,Forge 角色/组织内角色/手工岗位不覆盖
失败保护拉取中断时不误停用存量人员(这个坑很常见)
问题单冲突、失败进队列,管理员可绑定/忽略/重试
同步日志批次、阶段、计数、游标、状态全可查

"企微是通讯录权威来源,Forge 是权限权威来源" ——这个边界很重要。同步不会误删你手工配的角色和权限。

1.5 管理端:配完就知道行不行

新增了一整套管理界面(演示站可体验):

页面干什么
连接管理配置企业连接,管理登录/通讯录/消息/待办应用,Secret 永不明文返回
连通测试按能力执行 Token/读取/测试消息验证,配完立刻知道行不行
同步日志查看同步批次和阶段统计
问题单冲突/失败队列,可人工处理
映射查看查看外部部门/成员/岗位/标签与 Forge 的映射
投递管理消息和待办投递状态,失败可人工重试
回调事件回调元数据和 processing 状态(不返回解密正文)

二、统一能力开放平台:把内部能力安全地"开出去"

第二块是能力开放平台。这个更硬核——它解决的是"外部系统怎么安全地调你的接口"。

2.1 为什么要做这个

客户场景很真实:外围系统(ERP、小程序、第三方应用)需要调 Forge 的业务接口——建单、发起审批、查询数据。老做法是给每个对接方开一个账号,写一段鉴权代码,然后在 Controller 里手动校验权限。

问题在哪?

  • 没有统一鉴权:每个接口各写各的,漏一个就是越权
  • 没有幂等:网络重试就重复建单
  • 没有限流:对接方一个循环就把你打垮
  • 没有审计:出了问题查不到谁调了什么
  • 管理员没法自助:配完授权不知道能不能调,要开发去翻日志

2.2 Forge 的做法:一个网关兜住所有外部调用

核心是一个统一 REST 开放网关:

外部请求
  │
  ├── 1. 认证(OAuth Bearer 或 HMAC-SHA256 签名)
  ├── 2. 防重放(timestamp ±5分钟 + nonce 一次性校验)
  ├── 3. 授权(能力是否已发布?客户端是否已授权?)
  ├── 4. 身份校验(required_actor_type:USER/SERVICE/BOTH)
  ├── 5. 限流(读 120/分,写 20/分,可配置)
  ├── 6. 幂等(写操作强制 Idempotency-Key,命中返回首次响应快照)
  ├── 7. Schema 校验(按已发布版本校验请求体)
  ├── 8. 执行(CapabilityExecutor + ExecutionIdentity 上下文)
  ├── 9. 统一响应 {code, message, requestId, timestamp, data}
  └── 10. 审计入库(不保存请求/响应原文)

这条链路上每一步都是可配置、可审计、可拒绝的。  任何一步不通过,直接返回明确的错误码,不往下走。

2.3 两种认证模式,覆盖主流对接场景

模式认证方式身份类型适用场景
OAuth BearerAuthorization: Bearer fdu_...SERVICE 或 USER现代对接,支持用户委托
HMAC 签名X-Forge-App-Id+timestamp+nonce+signature仅 SERVICE传统系统对接,不依赖 OAuth

签名串固定为 appId\ntimestamp\nnonce\nMETHOD\npath\nsha256(body),HMAC-SHA256,常量时间比较。简单、安全、可复制。

关键安全设计:  签名密钥是 KEK 加密可逆存储(因为验签要还原原文),和现有 Bearer 凭据的哈希存储完全分离——不改动现有凭据的安全语义。

2.4 能力注册:三种来源,受控发布

不是什么接口都能开放。能力要先注册、发布、授权,才能被外部调用:

能力来源说明安全控制
业务动作(BUSINESS_ACTION)低代码业务对象的增删改查按字段白名单过滤
流程动作(FLOW_ACTION)发起流程、提交业务申请、审批强制 USER 委托身份
系统服务(SYSTEM_SERVICE)代码显式注册的服务(如"启动已发布流程")管理端不可填任意 URL,只选注册项

系统服务是关键设计——  管理员不能在后台填一个任意 URL 就开放出去。系统服务只能由代码注册,发布时固定流程模型和允许变量,调用者不能指定 modelKey、tenantId、userId 或 initiator。这避免了"把内部接口直接代理出去"的风险。

2.5 调用指南:管理员配完就知道怎么调

这是我花精力最多的地方。以前配完授权,管理员不知道行不行,要开发翻日志。现在:

四步式调用指南:

  1. 选择客户端 → 展示可调用状态和阻断原因(不返回模糊 403)
  2. 调用前检查 → 逐条诊断:网关开关、客户端状态、grant 状态、actor/auth/权限
  3. 契约与示例 → 递归参数表(含中文名称、类型、必填、含义、示例)+ Curl/Java 17 示例
  4. 在线测试 → 真实走 /oauth2/token + /openapi/v1/capabilities/:code/invoke,有副作用的能力二次确认

认证方式一键切换:  OAuth 和 HMAC 示例通过单一选择器切换,URL、能力编码、Header、Body 与真实网关契约完全一致。

文档下载:

  • Markdown 调用文档:概述、地址、主体要求、认证、Header、参数表、业务规则、权限、幂等/限流、错误码、OAuth/HMAC 示例、排障——外围开发不用看 Forge 源码就能接入
  • OpenAPI 3.1 JSON:可直接导入 Swagger/Apifox

一句话:管理员配完,自己就能判断能不能调、怎么调、为什么不能调。

2.6 身份桥接:外部用户怎么变成 Forge 用户

外部系统调用流程审批类能力时,需要一个真实的 Forge 用户身份。Forge 提供两条路:

方式说明适用场景
受信 OIDC Token Exchange外围系统提交受信 IdP 签发的 JWT,Forge 按issuer + subject自动映射现有用户并签发短期 USER Token有统一身份提供方
客户端签名用户断言无统一 OIDC 时,客户端用 RSA 私钥签发短期 JWT(最长 2 分钟),Forge 验签后按预绑定sub委托真实用户无统一 IdP

安全边界很明确:

  • 外部 JWT 只接受管理员显式配置的 HTTPS issuer 和 audience,默认不配置即失败关闭
  • 只允许 RS256,禁止 none 和共享密钥
  • 手机号匹配默认关闭,只有验签 + 防重放 + 格式校验全通过后才允许租户内唯一匹配
  • 不为不存在的 Forge 用户自动建号
  • 断言和 OIDC 使用不同 subject_token_type,验签失败不互相回退

2.7 审计:每一次调用都可追溯

每次调用(含被拒绝的)写
ai_capability_invocation_log,记录:

requestId / capabilityCode / version / clientId / actorType / actorUserId / tenantId / resultCode / httpStatus / schemaPath / durationMs

不保存:  请求 Body、响应 Body、Token、Secret、签名、Nonce 原文、用户手机号。

控制台可按 requestId 串联:入口接收 → 认证完成 → 授权完成 → 幂等命中 → 执行成功/失败。排障不用翻服务器日志。


三、两块拼在一起:企业集成的完整故事

企微集成和能力开放平台不是孤立的两个功能,拼在一起就是一条完整的企业集成链路:

                    ┌─────────────────────────────────┐
                    │         Forge Admin              │
                    │                                  │
  企业微信 ───────→ │  企微协同层                       │
  (通讯录/登录)    │  ├── 人员同步 → sys_user          │
                    │  ├── 安全登录 → Sa-Token 会话     │
                    │  ├── 消息投递 → 消息中心          │
                    │  └── 待办投影 → Flowable 任务     │
                    │                                  │
  外部系统 ───────→ │  能力开放平台                     │
  (ERP/小程序/      │  ├── OAuth/HMAC 认证              │
   第三方应用)       │  ├── 能力注册/发布/授权           │
                    │  ├── 网关调用 → CapabilityExecutor│
                    │  └── 审计追溯 → 调用日志          │
                    │                                  │
                    │  低代码 + 工作流 + AI + 多租户     │
                    └─────────────────────────────────┘

一个真实场景走一遍:

  1. 企业微信通讯录同步 → Forge 自动建立用户映射
  2. 员工在企微收到审批卡片 → 点击安全跳转到 Forge 待办 → 完成审批
  3. 外部 ERP 系统通过 HMAC 签名调用 Forge 开放接口 → 发起采购审批流程
  4. 流程审批人通过企微待办完成审批 → 结果回写业务系统
  5. 全程:内部用户走企微协同,外部系统走能力开放,两套链路各自安全

以前这套东西从零搭,至少一个月。现在配一配,跑通验证,几天就能上线。


四、算笔账:自己搭 vs 用 Forge

能力自己从零搭用 Forge
企微通讯录同步写同步脚本 + 增量处理 + 冲突处理 ≈ 5 人日配置连接 + 连通测试 ≈ 半天
企微安全登录OAuth + state 校验 + 票据交换 ≈ 3 人日配置连接 + 能力绑定 ≈ 2 小时
企微消息投递企微 API + 逐人结果 + 重试 ≈ 3 人日统一消息渠道,配置即用
企微待办卡片任务投影 + 回调 + 鉴权 ≈ 5 人日绑定流程 + 安全跳转
开放 API 网关认证 + 防重放 + 限流 + 幂等 ≈ 8 人日开启网关 + 注册能力
客户端授权管理凭据 + 授权 + 审计 ≈ 5 人日控制台配置,开箱即用
调用文档手写文档 + 维护 ≈ 持续成本自动生成 Markdown + OpenAPI
飞书/钉钉扩展全部重来 ≈ 15+ 人日实现 Connector,不改主链路

粗算:自己搭这套企业集成,40-50 人日起步。用 Forge,配置 + 验证,一周内能跑通。


五、说点实在的不足

不吹,客观说几个当前的限制:

  1. 飞书、钉钉适配器还没做。  通用底座和合同测试已经就位,企微是第一个完整适配器,飞书/钉钉需要后续独立实现——但不用改主编排链路,这是架构上的保证。
  2. 企微待办的"卡片内直批"默认关闭。  基线只开放"安全跳转到 Forge 查看详情"。客户要启用卡片内同意/驳回,需要额外配置流程白名单和专项 UAT——这是安全取舍,不是技术做不到。
  3. 需要公网 HTTPS 和企微可信域名。  企微回调要求公网可达的 HTTPS 地址、可信域名/IP 白名单和稳定证书,本地开发需要用内网穿透工具。
  4. 开放平台默认关闭。  FORGE_CAPABILITY_OPEN_GATEWAY_ENABLED=false,需要显式开启。这是安全设计——不用的能力默认不暴露。
  5. 作为相对年轻的功能模块,  企微集成的真实大规模 UAT 还在积累中。如果你的企业规模大(几千人以上),建议先在测试企业验证同步性能和回调量级。

六、上手体验

所有文章里说的能力,演示站都可以在线试:

源码地址:


七、最后聊两句

上篇"搭积木"聊的是怎么把内部能力做扎实。这篇聊的是怎么把这些能力接通企业生态——向内接企业微信,向外开能力网关。

企业后台说到底解决的是三件事:内部管得好、对内能协同、对外能开放。  缺一不可。

做企微集成时最深的感受是:安全边界比功能更重要。  登录不能信任前端身份、通讯录同步不能误删人员、待办回调不能越权审批——这些不是"做了就行",是"做对了才敢上"。所以你在文章里看到大量"失败关闭""禁止自动合并""重新校验"的设计,都是被真实场景教出来的。

做开放平台时最深的感受是:管理员体验决定成败。  网关安全做得再好,管理员配完不知道行不行、开发要翻日志排障,那这个平台就是半成品。所以调用指南、就绪诊断、在线测试、自动文档——这些"体验"功能花的精力不比安全链路少。

开源不易,持续迭代更难。如果觉得有用,点个 Star 是最大的鼓励。

你现在的企业集成方案是什么?企微对接最头疼的是哪块?评论区聊聊,想看哪块源码拆解的也可以扣——

  • 扣 1:想看企微通讯录同步的源码拆解(全量快照 + 增量 + 冲突处理)
  • 扣 2:想看开放网关安全链路的源码拆解(认证 → 防重放 → 授权 → 限流 → 幂等)
  • 扣 3:想看 OAuth state + 一次性票据登录链路的完整拆解

我挑呼声最高的那块下一篇详细写。