WeCom (기업 위챗)
SHA1 정렬 + AES-256-CBC 콜백 봉투를 사용하는 WeCom 자체 구축 앱 메시징. 중국 엔터프라이즈 배포의 표준 채널입니다.
🟡 아웃바운드 준비 완료, 인바운드 지원, 자체 구축 애플리케이션 경로(가장 일반적인 배포 형태)를 기반으로 구축되었습니다. WeChat OA에서 사용하는 것과 동일한 레거시 SHA1 + AES 봉투를 통해 라우팅되므로, 공유
wxcrypt헬퍼가 두 공급자를 모두 지원합니다.
제공 기능
- 아웃바운드 텍스트 메시징:
POST /cgi-bin/message/send를 통해 하나 이상의touser수신자(또는 전체 Agent 대상의@all)에게 메시지를 전송합니다. - 인바운드 콜백 이벤트:
/webhooks/wecom엔드포인트로 수신합니다. WeCom은 모든 콜백에msg_signature(사전순으로 정렬된[token, timestamp, nonce, encrypt]에 대한 SHA1)로 서명합니다. 본문은 43자EncodingAESKey를 사용하는 AES-256-CBC로 암호화됩니다. - 앱별
access_token캐시: 2시간 동안 캐시되며 자동 갱신됩니다. - 현재 텍스트만 지원합니다. 이미지 및 파일 업로드("미디어 업로드" 엔드포인트 경유)는 향후 추가될 예정입니다.
- 텍스트 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 또는 Agent 전체 대상의 @all을 허용합니다.
4. 테스트
minara auth messaging test wecom기본 목록의 각 touser에게 "✅ Minara gateway test ping" 메시지가 전송됩니다.
인바운드 웹훅
WeCom은 메시지 서명을 헤더가 아닌 URL 쿼리로 전달합니다. Minara는 본문을 복호화하기 전에 msg_signature를 SHA1(sort([token, timestamp, nonce, encrypt]).join("")) (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과 콜백 token은 서로 다릅니다. 전자는 WeCom의 앱별 OAuth 토큰이고, 후자는 콜백용 공유 서명 시크릿입니다. 환경 변수 파일에서 혼동하지 않도록 주의하십시오.@all은 자주 발생하는 함정입니다. Agent 범위 내 모든 사용자에게 알림을 일괄 전송합니다. 프로덕션 환경에서는WECOM_DEFAULT_TOUSER를 특정 사용자 ID로 고정하십시오.- AES 키 길이는 필수 조건입니다. WeCom은 정확히 32바이트(패딩 전 43자 base64)로 디코딩되지 않는 키를 거부합니다.
문제 해결
"Get access token failed (errcode 40013)"
WECOM_CORP_ID가 해당 시크릿이 속한 회사와 일치하지 않습니다.
"인바운드 웹훅이 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