直接检查签名生成代码中 timestamp 是否参与了 URL 编码,以及最终 sign 值在拼接 URL 时是否做了 URL 编码,大多数校验失败是因为这两步顺序或对象搞错了。
先说结论:签名计算时 timestamp 不应提前编码,最终 sign 必须编码,顺序错乱必失败
- 先确认:secret 复制是否有空格或换行
- 先处理:严格按照“时间戳 + 换行 + 密钥”拼接后再哈希
- 再验证:用 curl 发送请求看返回 errmsg 是否为 ok
命令速用版
import hashlib, hmac, base64, urllib.parse, time
secret = 'SEC...'
timestamp = str(round(time.time() * 1000))
string_to_sign = f'{timestamp}\n{secret}'
sign = urllib.parse.quote_plus(base64.b64encode(hmac.new(secret.encode(), string_to_sign.encode(), digestmod=hashlib.sha256).digest()))
webhook = f'https://oapi.dingtalk.com/robot/send?access_token=...×tamp={timestamp}&sign={sign}'为什么会这样
钉钉机器人加签机制要求使用 HMAC-SHA256 算法,协议规定字符串拼接完成后才进行哈希,最后对哈希结果进行 URL 编码。如果在哈希前对 timestamp 编码,或者哈希后忘记对 sign 编码,都会导致服务端计算出的签名与你发送的不一致。
分步处理
1. 检查密钥:确保 secret 没有多余空格,最好重新复制一次。
2. 检查时间戳:使用当前毫秒级时间戳,不要使用秒级。
3. 检查拼接:timestamp 和 secret 之间必须有一个换行符 \n。
4. 检查编码:最终 sign 包含特殊字符,必须用 URL Encode 处理。
怎么验证是否生效
发送请求后,观察 HTTP 状态码是否为 200,且返回 JSON 中 errmsg 字段为 ok。如果返回 errcode 不为 0,查看 errmsg 提示。
常见坑
1. 某些语言默认哈希输出是 hex 字符串,钉钉要求 base64。
2. 时间戳过期,签名有效期通常为请求前后一定时间内,确保服务器时间同步。
3. 二次编码,不要在生成 sign 后再次对整个 URL 进行编码。
参考来源
钉钉开放平台文档中心 - 自定义机器人接入 https://open.dingtalk.com/document/robots/custom-robot-access
原文链接:https://www.zjcp.cc/ask/10685.html
