Yii短信后端核心是可追踪、可重试、可审计,须规范组件注册(独立声明于components)、请求构造(动态签名+URL编码+时间戳校验)和响应解析(检查业务code而非仅HTTP状态码)。

Yii 做短信业务后端,核心不是“调通接口”,而是让每次发送都可追踪、可重试、可审计。不规范的对接常导致:明明返回 200 却没发出去、验证码被吞、高并发时连接池打满、错误日志为空、重试逻辑失效——这些问题基本都源于组件注册、请求构造和响应解析三个环节没做对。
必须手动注册独立短信组件
不能把短信配置写在 params.php 或用全局 Yii::$app->httpclient;必须在 config/web.php(或 console.php)的 components 中显式声明:
'sms' => [ 'class' => 'common\components\SmsClient', 'apiUrl' => 'https://sms-api.example.com/v3/send', 'accessKey' => 'ak-xxx', 'secretKey' => 'sk-xxx', 'timeout' => 8, ]- timeout 必须 ≥ 8 秒:阿里云、腾讯云等在高峰时段响应常达 3~6 秒,设 5 秒默认值会导致约 12% 请求被误判超时
- 组件必须由 Yii DI 容器管理,否则控制器里无法通过
$this->sms访问
请求构造要严格合规
多数平台(如互亿无线、阿里云)要求动态签名 + URL 编码 + 时间戳校验,任意一环出错都会返回“成功”但实际失败:
- 中文内容必须
urlencode(),否则签名值错、平台拒收 - 签名串拼接顺序必须与文档一致(如
account+mobile+content+time+key),且time是 10 位 Unix 时间戳,误差 ≤ 300 秒 - 密码类字段(如
password)不能是固定密钥,而应是md5($apiKey . $time)动态生成 - 阿里云模板变量名大小写敏感:
${code}对应['code' => '123456'],写成CODE或【code】都会报InvalidTemplateParam
响应解析不能只看 HTTP 状态码
HTTP 200 ≠ 发送成功。必须解码 JSON 并检查业务字段:
- 先判断
$response->isOk,非 true 则抛出异常 - 再解码
$data = json_decode($response->content, true),检查$data['code'] === 0(以阿里云为例) - 对临时性错误(如
code = 10003“频率超限”)记录完整响应体到@runtime/logs/sms-error.log,并实现指数退避重试 - 不要用模糊匹配(如
strpos($content, 'success')),避免把错误提示里的“success”当真
异步发送推荐走队列解耦
用户注册/下单后发短信,不应阻塞主请求流程:
- 用
yii-queue扩展,定义SmsJob类封装发送逻辑 - 控制器中先返回成功响应(
return $this->asJson(['status' => 'accepted'])),再调用Yii::$app->queue->push(new SmsJob(...)) - 更稳妥的做法是把
push()放在afterAction()钩子里,确保响应已发出 - 轻量通知类任务(如日志、非关键短信)可直接用
yii\queue\sync\Queue,避免 DB 队列表锁竞争


















