阿里云短信需严格校验凭证、签名、模板及配置:invalidaccesskeyid因accesskey未识别或无权限,signaturedoesnotmatch因密钥错误或时间偏移;批量发送三参数长度须一致;签名模板须审核通过且字符串完全匹配;自封装sdk必须显式addendpoint。

直接用 saviorlv/yii2-dysms 或 gmars/yii2-sms 就能跑通,但必须注意签名、模板、AccessKey 的权限和时效性——阿里云短信不是“配完就能发”,卡在审核或鉴权失败才是常态。
为什么 sendSms() 报错 InvalidAccessKeyId 或 SignatureDoesNotMatch
这两个错误基本都指向凭证问题,不是代码写错了,而是 AccessKey 没配对或没权限:
-
InvalidAccessKeyId:说明accessKeyId根本没被阿里云识别,常见于复制时多空格、用了 RAM 子账号但没授权AliyunDysmsFullAccess,或 Key 已被禁用 -
SignatureDoesNotMatch:accessKeySecret错了,或者时间偏移超过 15 分钟(SDK 内部用系统时间生成签名),也可能是你手动拼 URL 签名时漏了 header 排序或换行符 - 别用主账号 AK/SK —— 必须新建 RAM 用户,仅授予短信权限,否则一旦泄露等于交出整个云账号
sendBatchSms() 要求三个数组长度严格一致
批量发送不是“传个手机号列表”那么简单,sendBatchSms() 的前三个参数必须等长,否则会静默截断或抛异常:
- 第一个参数是签名数组:
['签名A', '签名B'],不能写成['签名A']却传两个手机号 - 第二个参数是模板 ID(固定一个字符串,不支持数组)
- 第三个参数是手机号数组:
['13800138000', '13900139000'] - 第四个参数是变量数组:
[['code'=>'123'], ['code'=>'456']],每个子数组 key 必须和模板里声明的变量名完全一致(大小写敏感)
少一个元素,sendBatchSms() 就会把最后一组数据丢掉,但不报错 —— 日志里只显示 “success: true” 且实际只发了一条。
签名和模板未审核通过导致 sendSms() 返回 isSuccess() === false
阿里云控制台里看到“已提交”不等于“已生效”,必须等人工审核(通常 1–2 个工作日):
- 签名名称必须和
sendSms()第一个参数字符串**逐字相同**,包括空格、中英文标点。比如控制台填的是【测试】,代码里写成[测试]就失败 - 模板 CODE(如
SMS_12345678)必须和控制台“模板管理”页显示的完全一致;模板内容里的变量(如${code})必须在templateParam数组里提供同名 key,且值不能为null或空字符串 - 测试阶段别用生产签名/模板,先建个“测试专用”签名,避免反复驳回影响上线节奏
自己封装 SDK 时 DefaultProfile::addEndpoint() 必须显式调用
如果不用拓展包、而是直接引入阿里云官方 PHP SDK(aliyun-openapi-php-sdk),容易漏掉这一步:
-
DefaultProfile::getProfile('cn-hangzhou', $key, $secret)只初始化配置,不注册 endpoint - 必须紧接着调
DefaultProfile::addEndpoint('cn-hangzhou', 'cn-hangzhou', 'Dysmsapi', 'dysmsapi.aliyuncs.com'),否则请求发到默认区域(可能超时或 404) - 区域固定为
cn-hangzhou,别写成hangzhou或China-Hangzhou—— 官方 SDK 对字符串校验很严格
最常被忽略的是:阿里云短信服务目前**不支持跨 Region 调用**,哪怕你 ECS 在深圳,也得用杭州 endpoint。











