跳到主要内容

WeComHelper(WeComHelper)

WeComHelper 提供获取企业微信(WeCom / 企微)AccessToken 的能力,由平台统一获取并维护 token 缓存,供插件脚本直接调用企业微信开放 API 使用。

概述​

企业微信的大部分开放能力(发送应用消息、查询通讯录、管理审批等)都需要携带 access_token 调用企业微信 API。WeComHelper 解决的核心问题是 token 的统一维护:

  • 平台统一缓存:AccessToken 由服务端代理统一向企业微信申请并缓存(提前 5 分钟过期留出缓冲),多个调用方共享同一份缓存,避免每个插件各自频繁请求企业微信 token(企业微信对 token 获取有频率限制,重复获取会使旧 token 失效)
  • 配置统一校验:获取 token 前会校验当前租户是否已配置企业微信所需的租户设置项,配置缺失时给出明确错误提示

常见别名:企业微信 token / 企微 token / WeCom access token / 企业微信凭证。

与相邻能力的边界:

  • OpenApiHelper — 调用平台自身的开放 API,与企业微信无关
  • HttpClientFactory — 通用 HTTP 调用能力,使用 WeComHelper 拿到 token 后调用企业微信 API 时使用它

API 方法​

GetWeComInternalTokenAsync — 获取企业微信 AccessToken​

获取平台维护缓存的企业微信 AccessToken,token 类型决定了使用哪个企业微信应用的 secret。

Task<string> GetWeComInternalTokenAsync(WeComTokenTypeEnum tokenType);

参数说明:

参数类型说明
tokenTypeWeComTokenTypeEnumtoken 类型,见下方取值

WeComTokenTypeEnum 取值​

界面/语义名称枚举值对应企业微信 secret所需租户设置
Auth(应用消息/登录)1企业自建应用 secret(AuthSecret)WeComCorpAppId、WeComCorpAgentId、WeComAuthSecret
Contact(通讯录)2通讯录 secret(ContactSecret)WeComCorpAppId、WeComContactSecret

枚举数值与服务端 SecretTypeEnum(Chameleon.Model.ValueObjects.WeCom)保持对齐。

GetWeComCorpAppId — 获取企业微信企业 Id(corpid)​

读取当前租户设置中的企业 AppId(设置项 WeComCorpAppId),未配置时返回空字符串。

string GetWeComCorpAppId();

GetWeComCorpAgentId — 获取企业微信应用 AgentId(agentid)​

读取当前租户设置中的应用 AgentId(设置项 WeComCorpAgentId),发送应用消息时作为 agentid 参数使用,未配置时返回空字符串。

string GetWeComCorpAgentId();

示例:

// 获取企业自建应用的 AccessToken(用于发送应用消息等)
var token = await sdk.WeComHelper.GetWeComInternalTokenAsync(WeComTokenTypeEnum.Auth);

// 获取通讯录应用的 AccessToken(用于读写企业微信通讯录)
var token = await sdk.WeComHelper.GetWeComInternalTokenAsync(WeComTokenTypeEnum.Contact);

// 获取企业 Id 与应用 AgentId(内部读取租户设置,无需手动拼设置项键名)
var corpId = sdk.WeComHelper.GetWeComCorpAppId();
var agentId = sdk.WeComHelper.GetWeComCorpAgentId();

使用场景​

在插件中调用企业微信 API​

典型场景是自定义通知渠道插件:插件收到通知发送请求后,先用 WeComHelper 取 token,再携带 token 调用企业微信「发送应用消息」API。

using Chameleon.Common.Models;
using Chameleon.SDK;
using Newtonsoft.Json;
using System.Net.Http;
using System.Text;

public class ChameleonCSharpScript
{
public async Task<object> ExecuteAsync(ComponentContext context, ChameleonSDK sdk)
{
// 1. 获取平台缓存的企业微信 token
var token = await sdk.WeComHelper.GetWeComInternalTokenAsync(WeComTokenTypeEnum.Auth);

// 2. 组装企业微信应用消息(agentid 由 helper 内部从租户设置读取)
var agentId = int.Parse(sdk.WeComHelper.GetWeComCorpAgentId());
var touser = context.DicParam["Receiver"]; // 接收人的企业微信 userid,由插件自行维护映射
var content = context.DicParam["Content"];

// 3. 创建 HTTP 客户端并携带 token 调用企业微信 API
var client = sdk.HttpClientFactory.CreateClient("wecom");

// 4. 组装消息体(匿名对象,序列化交给 JsonConvert)
var payload = new
{
touser,
msgtype = "text",
agentid,
text = new { content }
};

var json = JsonConvert.SerializeObject(payload);

// 5. 用不带 BOM 的 UTF-8 编码,否则企业微信可能报 invalid json
var requestBody = new StringContent(json, new UTF8Encoding(false), "application/json");

var response = await client.PostAsync($"https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={token}", requestBody);

var body = await response.Content.ReadAsStringAsync();

// 6. 解析 errcode 判断是否发送成功
var result = JsonConvert.DeserializeAnonymousType(body, new { errcode = 0, errmsg = "" });

if (result is not null && result.errcode != 0)
throw new System.Exception($"WeCom send failed: {result.errcode} {result.errmsg}");

return null;
}
}
人员映射由插件自行处理

平台不维护「系统用户 ↔ 企业微信 userid」的映射。企业微信的 touser 是什么、如何从系统用户推导出来,完全由插件脚本自行决定(例如查询映射表、使用工号、使用邮箱等)。

注意事项​

  • token 由平台缓存共享,不要在插件中自行请求 /cgi-bin/gettoken,重复获取会导致其他调用方的 token 失效
  • token 有有效期(企业微信默认 7200 秒,平台提前 5 分钟过期刷新),每次调用企业微信 API 前都应重新获取,不要在插件中长期缓存
  • 使用前需确保当前租户已配置企业微信设置项,见上方「所需租户设置」列;GetWeComCorpAppId / GetWeComCorpAgentId 未配置时返回空字符串,发送应用消息前建议判空
  • WeComTokenTypeEnum.Auth 对应企业微信自建应用的 secret,发送应用消息时 agentid 通过 GetWeComCorpAgentId 获取

属性明细​

以下内容面向技术实现与 AI 检索。

WeComTokenTypeEnum 属性表​

属性名类型含义取值/存储值
AuthWeComTokenTypeEnum自建应用 token(应用消息/登录)1,对应服务端 SecretTypeEnum.Auth
ContactWeComTokenTypeEnum通讯录 token2,对应服务端 SecretTypeEnum.Contact

OpenAPI 请求/响应​

SDK 通过平台开放 API 获取 token:

项目值
端点POST api/OpenApi/WeCom/GetInternalToken
鉴权PolicyConst.System
请求体{ "tokenType": "1" },TokenType 为 string,接受枚举数值或名称字符串(如 "1" / "Auth",不区分大小写)
响应ResponseResult<string>.Success(token),data 为 token 字符串

请求体定义:WeComInternalTokenRequest(Chameleon.Model.ValueObjects.WeCom),仅一个 TokenType(string)属性。

服务端执行逻辑​

调用链:WeComHelper → WeComOpenApiController(POST api/OpenApi/WeCom/GetInternalToken)→ WeComInternalProxy.GetAccessTokenAsync:

  1. 解析 TokenType 为 SecretTypeEnum,解析失败或未定义时抛出 ChameleonException(WeComTokenTypeInvalid)
  2. 校验该 token 类型所需的租户设置(Auth:WeComCorpAppId / WeComCorpAgentId / WeComAuthSecret;Contact:WeComCorpAppId / WeComContactSecret),缺失时抛出 WeComConfigurationMissing,MoreMessage 中列出缺失的设置项键名
  3. 以 WeCom_AccessToken_Cache_{corpId}_{tokenType} 为键查询缓存(CacheHelper.StringGetAsync),命中直接返回
  4. 未命中则调用企业微信 /cgi-bin/gettoken(corpid + 对应 secret)获取 token,缓存 expires_in - 300 秒后返回

异常与校验​

场景行为
TokenType 为空、非数字/名称或未定义的枚举值抛出 ChameleonException(locale 常量 WeComTokenTypeInvalid)
租户未配置对应 token 类型的设置项抛出 ChameleonException(locale 常量 WeComConfigurationMissing),MoreMessage 为缺失的设置项键名列表
企业微信 API 返回 errcode != 0抛出 ChameleonException,MoreMessage 携带企业微信 errmsg

相关实现​

位置说明
Chameleon.SDK/Interfaces/IWeComHelper.cs接口与 WeComTokenTypeEnum 定义
Chameleon.SDK/Internal/Services/WeComHelper.csSDK 实现,请求平台开放 API
Chameleon.ApiCore/Controllers/OpenApi/WeComOpenApiController.cs服务端开放 API 端点
Chameleon.Repository/Proxy/WeComInternalProxy.cstoken 获取与缓存逻辑(GetAccessTokenAsync)
Chameleon.Model/ValueObjects/WeCom/WeComConfig.cs服务端 SecretTypeEnum 定义

下一步​