WeCom(企業微信)
SHA1 ソート+AES-256-CBC コールバックエンベロープを用いた WeCom 自社製アプリのメッセージング。中国企業向けデプロイの標準チャネルです。
🟡 送信対応・受信サポート済み。最も一般的なデプロイ形態である自社製アプリパスを中心に実装されています。WeChat OA と同じレガシー SHA1 + AES エンベロープを使うため、共有ヘルパー
wxcryptが両プロバイダーをカバーします。
できること
POST /cgi-bin/message/sendによる送信テキストメッセージ。1 人以上のtouser宛、またはエージェント全体へは@allを指定できます。/webhooks/wecomへの受信コールバックイベント。WeCom はすべてのコールバックにmsg_signature([token, timestamp, nonce, encrypt]を辞書順ソートした SHA1)を付与します。ボディは 43 文字のEncodingAESKeyを使った AES-256-CBC で暗号化されます。- アプリごとの
access_tokenを 2 時間キャッシュし、自動更新します。 - 現時点ではテキストのみ対応。 画像・ファイルのアップロード("upload media" エンドポイント)は今後の拡張予定です。
- テキスト上限は 2048 文字(マークダウンは 4096 文字ですが、現時点では未接続)。
セットアップ
1. 自社製アプリケーションの作成
- WeCom 管理コンソール にサインインします。
- 「アプリケーションとミニプログラム」→「自社製」→「作成」へ進みます。
- アプリケーションのメタデータを入力し、詳細ページで AgentID と Secret を控えます。
- 企業レベルの CorpID は「マイ企業」→「企業情報」にあります。
2. コールバックの有効化(受信する場合のみ)
- アプリケーション詳細ページ →「API 受信」→「API 受信設定」を開きます。
- URL を
https://<your-host>/webhooks/wecomに設定します。 - Token(任意の不透明文字列)を入力し、EncodingAESKey(43 文字の Base64)は「ランダム生成」をクリックします。
- 「保存」をクリックします。WeCom が GET ハンドシェイクで URL を叩き、Minara が echostr を復号してエコーバックし、バインディングが完了します。
3. Minara の設定
minara auth messaging add
# `wecom` を選び、corp id・agent id・secret・default touser・
# callback token・EncodingAESKey を貼り付けます。または環境変数を直接設定します。
WECOM_CORP_ID=ww<...>
WECOM_AGENT_ID=1000002
WECOM_SECRET=<application secret>
WECOM_DEFAULT_TOUSER=user1|user2 # または @all
WECOM_CALLBACK_TOKEN=<callback token>
WECOM_CALLBACK_AES_KEY=<43-char EncodingAESKey>WECOM_DEFAULT_TOUSER は WeCom の慣習に従い、パイプ区切りのユーザー ID、またはエージェントの全対象者へは @all を指定します。
4. テスト
minara auth messaging test wecomデフォルトリストの各 touser に「✅ Minara gateway test ping」が届きます。
受信 Webhook
WeCom はメッセージシグネチャをヘッダーではなく URL クエリに付与します。Minara はボディを復号する前に、SHA1(sort([token, timestamp, nonce, encrypt]).join("")) に対して msg_signature を検証します(Tencent のレガシー IM 方式)。
GET URL 検証ハンドシェイクでは、WeCom が ?msg_signature=…×tamp=…&nonce=…&echostr=<base64> を送信します。Minara はシグネチャを検証し、AES キー(IV はキーの先頭 16 バイト)で echostr を復号してプレーンテキストをエコーします。Token または AES キーが誤っている場合は 401 / 500 を返します。
復号後の XML ペイロード内部:
<xml>
<ToUserName>...</ToUserName>
<FromUserName>...</FromUserName>
<CreateTime>...</CreateTime>
<MsgType>text</MsgType>
<Content>...</Content>
<MsgId>...</MsgId>
</xml>現時点では MsgType=text のメッセージのみ Agent に送出されます。画像・音声・イベントタイプはサイレントに破棄されます。
制限・注意事項
access_tokenとコールバックトークンは別物です。 前者は WeCom のアプリごとの OAuth、後者はコールバック用の共有署名シークレットです。env ファイルで混同しないようにしてください。@allはよくある落とし穴です。 エージェントのスコープ内の全ユーザーに通知が届くため、本番環境ではWECOM_DEFAULT_TOUSERを特定のユーザー ID に固定してください。- AES キーの長さは必須要件です。 キーが正確に 32 バイトにデコードされない(43 文字の Base64 ではない)場合、WeCom は拒否します。
トラブルシューティング
「Get access token failed (errcode 40013)」
WECOM_CORP_IDが、その Secret が属する企業と一致していません。
「受信 Webhook が 401 を返す」
msg_signatureが一致していません。最も多い原因はWECOM_CALLBACK_TOKENの誤字です。まれに、リバースプロキシがシグネチャクエリを除去しているケースもあります。
「signCallbackParams length mismatch」
WECOM_CALLBACK_AES_KEYが 43 文字ではありません。WeCom コンソールから再生成してください。
リファレンス
- 環境変数:
WECOM_* - 送信:
apps/agent/src/messaging/wecom.ts - 受信仕様:
apps/agent/src/messaging/inbound/specs/wecom.ts - 共有暗号ヘルパー:
apps/agent/src/messaging/_shared/wxcrypt.ts - WeCom プラットフォーム: developer.work.weixin.qq.com