回调通知说明(旧版)
一. 回调说明
2023 年 5 月 15 日之后注册的企业,将默认使用新回调通知,请参考新版回调通知
若客户主动选择版本回调通知,请与客户经理联系处理
回调地址: 在企业应用管理中的企业版应用中配置(配置方式可以参考下方回调 FAQ中的回调地址是否支持更改或删除问题)
请求方式: 电子签平台的回调都是POST 请求, 如果得到的是GET请求,请确认回调地址是否存在http到https的转发
回调成功条件: 一旦贵方给电子签平台返回httpcode 200, 电子签平台认为回调成功, 将不会再重发回调消息
数据格式: JSON格式("Content-Type":"application/json")
回调地址验证: 如果配置了回调 Url地址,但是没有收到回调通知,贵方可在外网环境用下方curl命令简单, 需要能够正常返回 httpcode 200表示可用 , 如下
curl https://tsign.tencent.com/callback -H "Content-type: application/json" -X POST -d "{}"
# 需将https://tsign.tencent.com/callback 换成贵方配置的回调地址
如果没有回调通知, 建议日志记录一下接收到的请求, 方便排查问题。
二. 回调场景
通知类型以 MsgType 做区分,按照回调通知类型主要分为:
合同相关回调, 主要是合同状态变动等场景
印章相关回调, 主要是印章操作和印章授权等场景
模板相关回调, 主要是模板操作等场景
企业与员工相关回调, 主要是企业实名或者员工加入企业等场景
文件资源相关回调, 主要是合同合成等场景
三. 回调加密与校验
1. 回调消息加解密
回调加密 key
如果配置了回调加密 key(可选参数),电子签的回调请求体会进行加密处理,需要客户使用配置的回调加密 key进行解密得到真正的回调消息。
注意:配置了回调加密 key即会开启消息加密,去掉即为关闭发送明文回调消息。建议开启加密确保数据安全。
解密步骤
- 对收到的数据进行 Base64 解码得到密文。
- 对密文进行对称解密,算法为 AES-256-CBC,密钥为腾讯电子签提供的 CallbackUrlKey,IV 取 CallbackUrlKey 值的前 16 位,数据采用 PKCS#7 填充。
- 解密得到的数据为输入参数的 Json 格式。
解密代码可以参考 解密代码 demo
2. 回调消息校验
签名验证 token
如果配置了 签名验证 token(可选参数),电子签的回调请求会在header中附带签名参数[Content-Signature],客户方用来验证请求来源确实电子签,保证安全性。
原理可参考:https://docs.github.com/en/developers/webhooks-and-events/webhooks/securing-your-webhooks
校验步骤
当贵方回调服务接收到回调时:
取出 header [Content-Signature]
验证签名, 验证代码如下, 如果验证通过,继续处理。如果不通过,忽略该请求
// payload_body 为接收到的消息体内容
// verify_token 为在第三方应用中配置的 "签名验证 token"
// content_signature 为从请求头部中取得的Content-Signature的值
def verify_signature(payload_body,content_signature,verify_token):
signature = 'sha256=' + OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), verify_token, payload_body)
return halt 500, "Signatures didn't match!" unless Rack::Utils.secure_compare(signature, content_signature)
四. 通用结构体
1. 明文回调消息结构体
如果未设置回调加密 key, 回调服务接收到的请求直接是这个结构体的json序列化
参数名称 | 参数类型 | 参数描述 |
---|---|---|
MsgId | Sting | 消息唯一ID, 为32为字符串, 用于唯一确定本消息 |
MsgType | Sting | 消息类型, 标识本消息是那个场景发送的, 如FlowStatusChange标识合同状态变更, 可以参考各个场景的回调 |
MsgVersion | String | 消息版本,固定为 ThirdPartyApp |
MsgData | 结构体 | 消息数据, 各个消息类型的结构体不同, 可以参考各个场景的回调中MsgData结构体定义 |
2. 密文回调消息结构体
如果设置了回调加密 key , 回调服务接收到的请求是此密文回调消息结构体的json序列化, 解密后才是明文回调消息结构体json序列化
参数名称 | 参数类型 | 参数描述 |
---|---|---|
encrypt | String | 加密后的消息体(需通过回调加密 key解密得到明文回调消息结构体json序列化) |
五. 回调 FAQ
回调地址是否支持同时配置多个?
支持,回调地址可以同时存在多个, 根据您的需求不同的地址可以配置相同或者不同的 回调加密 key、签名验证 token。
回调地址是否支持更改或删除?
支持,您可以在控制台在企业应用管理中的企业应用中配置中进行回调地址的配置。
回调配置后多长时间生效呢?
配置完成后立即生效, 如果修改了回调加密 key 和签名验证 token , 确保回调已经支持新这两个key。
为什么客户收到 ALL(合同签署完成)的回调通知后,又收到了PART(合同签署中)或者INIT(合同创建)的通知?
以单方签署的合同为例,FlowCallbackStatus 状态变化一般是由合同签署中或者合同创建变为合同签署完成。 少量回调可能因状态变化间隔比较短、重发、或者网络传输等原因,小几率出现到达顺序不一致,建议开发者从代码层面进行适当控制,例如状态更新为合同签署完成后不能再更新为合同签署中和合同创建。
电子签发送回调时超时时间是多久?
超时时间为 5 秒。
电子签发送回调失败后,回调最大重试次数是多少?重试机制是怎么样的呢?
回调的最大重试次数是 36 次;回调重试间隔随次数增加,具体如下:
1 秒、2 秒、3 秒、4 秒、5 秒、10 秒、15 秒、20 秒、25 秒、30 秒、35 秒、40 秒、45 秒、50 秒、55 秒、1 分、2 分、3 分、4 分、5 分、6 分、7 分、8 分、9 分、10 分、15 分、25 分、35 分、45 分、55 分、1 时、2 时、3 时、4 时、5 时、6 时
如果36次都失败, 电子签平台认为此消息无法回调会丢弃此消息
六. 回调样例
1. 密文回调消息
POST /callback HTTP/1.1
Host: www.esstest.com
User-Agent: Go-http-client/1.1
Content-Length: 1088
Content-Type: text/plain
Accept-Encoding: gzip
YyYyLZonMceFMFFi5jRnnOWrOasvzmKtGAvRPq1IzuYma88UvTqyZy8QpNVMKxvJY3Sp+NJW6mgTfU35u7SbUon+QCjul1P9P6mcVRuVvYrM2DoFBDgjLURfX+CWnZ9m967nNqiubw9vj9ToysJDZyr0zo4NN1CCfvsyxnVNKhSNbRAy74x4SlLscZ/wcFwdy55S2rBxbjLCqViIj6llQFo74mLHJ8oumngBD1WJZ5ginDNEScPB7+cIHeKF5w3UvUpDqDIUjAj7KFUmIQM8/zY8EafhgCNhWRaGxuFxGF+iMqwC+HJYosbBmrKZ44+8xwL5WlXLx/Cf8bK7J4mJIWbKyul8PBE9Xh8lL/d0Ufnf4sUB0ypbdy/KIr+XQJgFjR2AQGENXvxxlCfdVY5svGfXYaaSSyDND1u9C8kMxQRfNHJye7ulTprROYTtq4GJ8UJQbJbuHvTcppGyMbGO2AvgXcoSogM0JuZzLK/gcPFIWIf9oFTg47M62sLf9YY7UASVITfA5LnE+/1clN4vn748wjS4tdxCL8wjWanPOONTPCMrwH0wsZ86xEf7aLl0/qBWGF13VYh4C4XgiDLtaOs6DdlzMz5EszWISpRRzfJLxcBnhHL9sQu7YWLZzRL6vmP1qtdWZbUYt4Z/eKff5gfmmDGHOxVjd3XhxhfHSdW3a8LzlMT3n69CPBEiOjXA4abshkiT6+hOlJ8uCws+ja2BSmwruqpUn4tq7Je91cT0AhGHuvq9s1VCB7vw8KsVimRHrC6eOa1rgm6qgQNP0fMgGRe+qu4BtfND1a/j9BBuIHQSjLSn2JB2P/EAvbb5J2iPVZj3SppgzhwVCgYUu+osA3LNC4NsYxm/yMs8mq7nOCIZd6D/BM9py5WKS6//e4mM6sY3/S2wOr8snkUsEuu5M35zyRcrCjIaRzV9OKZjP+aqkk2GcF/Figd3N/zCZ+WjC+L9r/ELHn64qEJxZDvXKXVE3dUOchbUPelCb3YO+Mub+76bnvt8IQ2MRf9NaFO7cWlh9mDWkZMXxmOTlxOxQtOeTrW+QywTkZaDGkP83HRjqXd7bn3YBcdFiOy/
此处使用 回调加密 key: TencentEssEncryptTestKey12345678
,参考解密代码Demo解密后可获取以下明文:
!该 回调加密 key 仅用于此处测试样例。
{
"FlowId": "yDRtrAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"DocumentId": "yDRtrBBBBBBBBBBBBBBBBBBBBBBBBBB",
"CallbackType": "sign",
"FlowName": "测试流程",
"FlowDescription": "",
"FlowType": "",
"FlowCallbackStatus": 4,
"Unordered": true,
"CreateOn": 1658892449,
"UpdatedOn": 1659604019,
"DeadLine": 1661615999,
"UserId": "",
"RecipientId": "yDRtrCCCCCCCCCCCCCCCCCCCCCCCCCCC",
"Operate": "sign",
"UserData": "",
"Approvers": [
{
"UserId": "yDRtrDDDDDDDDDDDDDDDDDDDDDDDDDDD",
"RecipientId": "yDRtrCCCCCCCCCCCCCCCCCCCCCCCCCCC",
"ApproverType": 1,
"OrganizationName": "",
"Required": true,
"ApproverName": "张三",
"ApproverMobile": "15912345678",
"ApproverIdCardType": "ID_CARD",
"ApproverIdCardNumber": "440300200101010001",
"ApproveCallbackStatus": 3,
"ApproveMessage": "",
"ApproveTime": 1659604019,
"VerifyChannel": "WEIXINAPP"
}
],
"CallbackUrl": "https://www.esstest.com"
}
2. 明文回调消息
POST /callback HTTP/1.1
Host: www.esstest.com
User-Agent: Go-http-client/1.1
Content-Length: xxx
Content-Type: application/json
Accept-Encoding: gzip
{"FlowId":"yDRtrAAAAAAAAAAAAAAAAAAAAAAAAAAA","DocumentId":"yDRtrBBBBBBBBBBBBBBBBBBBBBBBBBB","CallbackType":"sign","FlowName":"测试流程","FlowDescription":"","FlowType":"","FlowCallbackStatus":4,"Unordered":true,"CreateOn":1658892449,"UpdatedOn":1659604019,"DeadLine":1661615999,"UserId":"","RecipientId":"yDRtrCCCCCCCCCCCCCCCCCCCCCCCCCCC","Operate":"sign","UserData":"","Approvers":[{"UserId":"yDRtrDDDDDDDDDDDDDDDDDDDDDDDDDDD","RecipientId":"yDRtrCCCCCCCCCCCCCCCCCCCCCCCCCCC","ApproverType":1,"OrganizationName":"","Required":true,"ApproverName":"张三","ApproverMobile":"15912345678","ApproverIdCardType":"ID_CARD","ApproverIdCardNumber":"440300200101010001","ApproveCallbackStatus":3,"ApproveMessage":"","ApproveTime":1659604019,"VerifyChannel":"WEIXINAPP"}],"CallbackUrl":"https://www.esstest.com"}