签名错误主因是时间戳、nonce、签名顺序或哈希方式未对齐文档;需用HMAC-SHA256按平台要求拼接timestamp+nonce+body,timestamp偏差≤5分钟,nonce每次唯一,且须打印签名原文比对。

requests.post 发送短信 API 时返回 401 或 {"code":4001,"msg":"签名错误"}
签名错误不是你密钥填错了,大概率是时间戳、nonce、签名拼接顺序或哈希方式没对齐文档。第三方平台(比如阿里云、腾讯云、容联云)要求你用 secret_key 对 timestamp + nonce + body(或特定字段)做 HMAC-SHA256,且要求 timestamp 与服务器时间偏差不能超过 5 分钟。
- 先确认你用的是
hmac.new(key.encode(), msg.encode(), digestmod=hashlib.sha256),不是hashlib.sha256()直接哈希 -
nonce必须每次请求唯一,建议用secrets.token_urlsafe(8)生成,别用时间戳或自增数 - 签名原文顺序必须严格按文档来:有些平台要
nonce+timestamp+body,有些是timestamp+nonce+body,少一个加号或换行都失败 - 发送前打印出你算出的
signature和用于签名的原始字符串,和 Postman 里跑通的对照一下
用 urllib.parse.urlencode 处理短信模板参数时发不出中文或乱码
不是编码问题,是你把整个 content 当成普通表单字段提交了。多数短信平台(如云片、SUBMAIL)要求模板变量走 JSON body,且 Content-Type 必须是 application/json;而 urlencode 只适用于 application/x-www-form-urlencoded 场景,一混就解不出变量。
- 检查你调用的是
requests.post(url, data=...)还是requests.post(url, json=...)—— 模板类接口几乎都该用json=参数自动序列化 - 中文变量不用手动
urllib.parse.quote,json=会自动处理 Unicode - 如果非要用
data=(比如老接口),记得设headers={'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'},再用urlencode({...}, encoding='utf-8')
短信发送后没收到,但 API 返回 code=0 或 "success":true
成功响应只代表平台**接收并校验通过**,不代表已送达手机。运营商通道、手机号格式、签名/模板审核状态、日发送限额,任何一个环节卡住都会静默失败。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
- 立刻查平台控制台的「发送记录」,看具体状态是「发送中」「超频拦截」「模板未审核」「签名不匹配」还是「号码黑名单」
- 用测试号(如自己手机号)发时,确认该号码没被平台加入调试白名单——有些平台默认只放行白名单号码,其他全丢弃
- 检查
mobile字段是否带国家码(如 +86138****),部分平台强制要求,缺了就进黑洞 - 别依赖 HTTP 状态码 200:有些平台内部失败也返回 200 + 成功体,必须解析响应里的
status或error_code字段
并发发 100 条短信时出现 ConnectionResetError 或 timeout
不是网络不稳定,是默认的 requests 连接池太小,又没复用 session,每条请求都新建 TCP 连接,触发平台限流或本机端口耗尽。
立即学习“Python免费学习笔记(深入)”;
- 用单个
requests.Session()实例发全部请求,它会自动复用连接 - 给 session 设置连接池:
adapter = requests.adapters.HTTPAdapter(pool_connections=10, pool_maxsize=10),再session.mount('https://', adapter) - 加
time.sleep(0.1)控制节奏,别一股脑for循环发——多数平台 QPS 限制在 10~20,超了直接拒绝 - 别用
threading硬扛并发,改用concurrent.futures.ThreadPoolExecutor(max_workers=5)更稳
签名算法细节、模板变量键名、返回字段含义,每个平台都不一样。别信“通用封装”,同一份代码切不同平台时,至少有三处要重写:签名逻辑、body 构造方式、结果解析路径。文档里标星号的字段,就是你明天凌晨三点排查失败原因的地方。

















