# 回调配置

注:本文参考企业微信的和公众号回调配置 (opens new window)。如果开发者有公众号、小程序、企业微信的开发经验,可以迅速上手。

# 什么时候需要回调服务

  1. 异步任务:某些接口采用异步任务,这种接口一般会立即返回一个请求ID (requestId),并在任务完成后通过回调通知开发者,通过请求ID (requestId) 可以确认是哪次调用的结果。
  2. 事件通知:当系统中发生了某些事件时,会通过回调告知开发者。例如:订单成交、客户删除跟进成员等。

# 配置参数说明

配置回调服务,需要有三个配置项,分别是:URL, Token, EncodingAESKey

首先,URL为回调服务地址,由开发者搭建(需要满足接口要求,参考第3部分说明),用于接收通知消息或者事件。

其次,Token用于计算签名,由英文或数字组成且长度不超过32位的自定义字符串。开发者提供的URL是公开可访问的,这就意味着拿到这个URL,就可以往该链接推送消息。那么URL服务需要解决两个问题:

  • 如何分辨出是否为 API 来源
  • 如何分辨出推送消息的内容是否被篡改

通过数字签名就可以解决上述的问题。具体为:约定Token作为密钥,仅开发者和API服务器知道,在传输中不可见,用于参与签名计算。API在推送消息时,将消息内容与Token计算出签名。开发者接收到推送消息时,也按相同算法计算出签名。如果为同一签名,则可信任来源为API,并且内容是完整的。

  • 如果非API来源,由于攻击者没有正确的Token,无法算出正确的签名;
  • 如果消息内容被篡改,由于开发者会将接收的消息内容与Token重算一次签名,该值与参数的签名不一致,则会拒绝该请求。

最后,EncodingAESKey用于消息内容加密,由英文或数字组成且长度为43位的自定义字符串。由于消息是在公开的因特网上传输,消息内容是可被截获的,如果内容未加密,则截获者可以直接阅读消息内容。若消息内容包含一些敏感信息,就非常危险了。EncodingAESKey就是在这个背景基础上提出,将发送的内容进行加密,并组装成一定格式后再发送。

# 回调服务需要实现哪些功能

配置回调服务时,需要能同时支持HttpGet以及HttpPost两种能力,

  • API 会先判断URL服务是否具备解析API推送消息的能力。 具体方式是,API往URL服务上发一条Get请求带签名及密文参数到URL服务上,如果URL服务检查签名通过,并能正确返回密文参数对应的明文字符串,则验证通过。此时在API的配置就开始生效。
  • 后续的业务请求(比如应用菜单的点击事件,用户消息等),都会类似的方式(签名+密文)向服务URL推送消息。URL服务验证签名通过后,需要将POST数据解密,就可以得到对应的业务消息明文。

# 支持Http Get请求验证URL有效性

假设开发者的接收消息的URL设置为 http://yourdomain.com/callback

企业管理员在保存回调配置信息时,API服务器会发送一条验证消息到填写的URL,请求内容如下:

GET http://yourdomain.com/callback?signature=SIGNATURE&timestamp=TIMESTAMP&nonce=NONCE&echostr=ENCRYPT

参数说明:

参数 类型 说明
signature String 消息加密签名,signature计算结合了企业填写的token、请求中的timestamp、nonce、加密的消息体。签名计算方法参考 消息体签名检验
timestamp Long 时间戳(精度:毫秒)。与nonce结合使用,用于防止请求重放攻击。
nonce String 随机字符串。与timestamp结合使用,用于防止请求重放攻击。
echostr String 加密的字符串。需要解密得到消息内容明文,解密后有random、msg_len、msg、receiveid四个字段,其中msg即为消息内容明文

回调服务需要作出正确的响应才能通过URL验证,具体操作如下:

  1. 对收到的请求,解析上述的各个参数值(参数值需要做Urldecode处理)
  2. 根据已有的token,结合第1步获取的参数timestamp, nonce, encrypt重新计算签名,然后与参数signature检查是否一致,确认调用者的合法性。计算方法参考:消息体签名检验
  3. 解密encrypt参数得到消息内容(即msg字段)
  4. 在1秒内响应GET请求,响应内容为上一步得到的明文消息内容(不能加引号,不能带bom头,不能带换行符)

开发模式

在开发模式下,请求的文本数据不加密,格式如下:

GET http://yourdomain.com/callback?echostr=ENCRYPT

开发者需要获取 echostr 的内容,并在1秒内直接原样返回。

# 支持Http Post请求接收业务数据

假设企业的接收消息的URL设置为 http://yourdomain.com/callback 。 当用户触发回调行为时,企业微信会发送回调消息到填写的URL,请求内容如下:

POST http://yourdomain.com/callback

{
	"signature": "SIGNATURE",   // 消息加密签名
	"timestamp": 1629086602073, // 时间戳(精度:毫秒)
	"nonce": "NONCE",           // 随机字符串
	"encrypt": "ENCRYPT_MSG"    // 加密过的消息
}

参数说明:

参数 类型 说明
signature String 消息加密签名,signature计算结合了企业填写的token、请求中的timestamp、nonce、加密的消息体。签名计算方法参考 消息体签名检验
timestamp Long 时间戳(精度:毫秒)。与nonce结合使用,用于防止请求重放攻击。
nonce String 随机字符串。与timestamp结合使用,用于防止请求重放攻击。
encrypt String 加密的字符串。需要解密得到消息内容明文,解密后有random、msg_len、msg、receiveid四个字段,其中msg即为消息内容明文

开发模式

在开发模式下,请求的内容不加密,开发者可以直接获取明文。