TP6调用阿里云短信SDK报SignatureDoesNotMatch或InvalidAccessKeyId.NotFound,根本原因在于access_key_id与secret须取自RAM控制台、签名与模板必须审核通过且完全匹配、templateParam键名须与模板占位符一致、region_id需与endpoint严格对应。

ThinkPHP发短信不是调一个函数就能成的事,漏掉任意一环——比如模板 CODE 拼错、templateParam 键名不匹配、签名含空格、access_key_secret 硬编码在配置里——线上就收不到验证码。
TP6 用阿里云 SDK 发短信老报 SignatureDoesNotMatch 或 InvalidAccessKeyId.NotFound
这不是你代码写错了,是四个地方没对齐:
-
access_key_id和access_key_secret必须从阿里云「访问控制 RAM」控制台拿,不是用户中心旧 AK 页面; -
sign_name必须和控制台审核通过的签名**完全一致**,包括全角括号【】、空格、大小写,写成“我的公司”或“【我的公司 】”都会触发SignNameNotExists; -
template_code必须复制控制台「模板管理 → 已通过」状态下的模板 CODE(如SMS_123456789),草稿/待审核 ID 无效; -
region_id和请求host必须匹配:用cn-hangzhou就配dysmsapi.aliyuncs.com,换区域必须查对应 endpoint。
TP5 调创世华信接口返回空或 returnstatus=405
这是典型的编码+协议陷阱,它不认 UTF-8,也不吃小写 MD5:
- 内容必须转 GB2312:
iconv('UTF-8', 'GB2312//IGNORE', $content),否则静默丢弃; -
password必须是 32 位大写 MD5:strtoupper(md5($password)),小写、base64、加盐都不行; - URL 中含中文或符号(如【】)必须
urlencode()包一层,不能直接拼; - 别用
file_get_contents(),它不支持 POST,得用curl_init()并显式设CURLOPT_POST和CURLOPT_POSTFIELDS。
用 Overtrue/EasySms 封装多网关时,sendCode 方法总失败
失败往往不在网关本身,而在前置校验和参数组装环节:
立即学习“PHP免费学习笔记(深入)”;
-
$code必须先trim()再is_numeric()校验,防止空格或字母混入; - 不同网关对模板变量键名要求不同:阿里云要
code,云片可能认number或code,得按gateways配置动态适配; - 缓存 Key 必须严格为
sms:code:{$mobile}:{$scene},TTL 设 900 秒,否则验证时取不到; - 策略类必须设为
\Overtrue\EasySms\Strategies\OrderStrategy::class,否则备用网关不会自动切换。
验证码能发但收不到,或收到乱码
问题大概率出在字符集或服务商限制上:
- 所有内容(含签名、模板文案、变量值)必须统一 UTF-8 编码,且服务端响应头不能覆盖为 GBK;
- 部分网关(如容联云)要求手动注册 PSR-4 命名空间,否则 SDK 类找不到;
- 创世华信等老平台若用
sms.aspx接口,必须确认是否启用了「内容过滤」,含敏感词(如“免费”“中奖”)会被拦截且不报错; - 腾讯云需提前购买国内短信套餐包,否则调用成功但实际不下发,控制台也无日志。
最常被忽略的是:错误日志没单独记录手机号、错误码和请求 ID。线上出问题时,没有这三样,基本靠猜。



















