Channel 领域:渠道配置与校验(微信/企业微信)

2026年1月25日
2 分钟阅读
作者:ixNieStudio

Channel 领域:渠道配置与校验(微信/企业微信)

Channel 是这个项目里“最像外部世界”的一个对象:它承载了凭证、权限、错误码、网络不稳定……

如果说 KV/服务层的复杂度是你自己能掌控的,那 Channel 带来的复杂度是你必须“消化掉”的。

这篇文章想讲的不是“它有哪些字段”,而是:

  • 为什么 Channel 是推送系统的地基?
  • 为什么必须把微信/企业微信的差异隔离在 service 层?
  • 为什么要把 token 维护做成一种“可观测状态”,而不是“失败了再说”?

Channel 的角色:把“平台差异”挡在业务外面

在业务模型里:

  • Channel 描述“通过哪个平台发送消息”(微信测试号 / 企业微信等)
  • 一个 Channel 下可以挂多个 App(不同 AppKey、不同推送策略)

从架构角度看,它扮演的是“适配器”:

  • 业务层只关心“我要把消息送出去”
  • 平台层负责“怎么拿 token、怎么发、失败怎么解释”

关键约束:渠道是共享资源,不是一次性配置

因为多个 App 可能共用同一个 Channel,所以它必须满足一些约束:

  • 渠道被 App 引用时,禁止删除(否则会产生悬挂引用)
  • 渠道配置变更需要触发:
    • token 状态更新
    • API 可用性校验

对应逻辑通常集中在:

  • node-functions/services/channel.service.ts

为什么微信/企业微信要拆成两套 service

项目里把两类平台拆成两套 service:

  • wechat.service.ts
  • enterprise-wechat.service.ts

这不是“代码洁癖”,而是为了避免一个常见的工程灾难:

所有平台差异都堆在 push.service 里,用 if/else 写到最后没人敢改。

两者差异很实际:

  • token 获取接口不同
  • 消息发送接口不同(企业微信支持 textcard 等)
  • 用户体系不同(OpenID vs UserID/部门)
  • 错误码集合完全不同

拆分后的收益是可量化的:

  • 错误码映射集中、可维护
  • token 缓存策略清晰
  • 更容易写单元测试(平台服务可以被单独验证)

一张图:服务层怎么分工

flowchart TB P["push.service
编排"] -->|send message| WS[wechat.service] P -->"|"send message"|" EWS[enterprise-wechat.service] WS -->"|"get/put token status"| KV["(configKV)"] EWS -->|get/put token status| KV WS -->"|"HTTPS"|" WXAPI[WeChat API] EWS -->"|"HTTPS"| QYAPI[WeCom API]

你会注意到:

  • push.service 不知道 token 是怎么来的
  • push.service 也不应该知道“40001 到底是什么意思”

Token 维护状态:把不稳定变成可观测

两套 service 都实现了“token 状态缓存”(本质是把 token 维护过程显式化):

  • valid
  • lastRefreshAt
  • lastRefreshSuccess
  • expiresAt
  • error / errorCode

它的价值在于:

  • UI 能展示渠道健康度(这比“点一下试试看”靠谱得多)
  • 排障时能快速判断:
    • 是凭证错(AppSecret/CorpSecret 不对)
    • 还是网络错(临时失败)
    • 还是权限不足(API 未授权)

常见坑与排障

  • 渠道验证失败但凭证看起来没问题

    • 很多时候是“权限不足”(比如测试号/未授权接口),看 errorCode 比猜更快。
  • 偶发发送失败

    • 先看是否 token 过期触发了刷新;如果刷新失败,问题通常不在“发消息”,而在“获取 token”。

启发:把平台当成“依赖”,别当成“业务的一部分”

  • 平台差异要被适配器隔离,否则业务代码会被错误码/鉴权方式污染。
  • token 状态要被显式化,否则你只能靠“重试几次试试”这种玄学。