短信接口必须异步调用,使用消息队列(如think-queue)封装sendsms()任务;密钥须通过.env环境变量管理;验证码需校验模板code与签名一致性;日志必须记录template_code、mobile及response_code。

短信发送接口必须走异步,否则页面会卡住
ThinkPHP 默认同步调用第三方短信 SDK(比如阿里云、腾讯云)时,HTTP 请求阻塞会导致用户点击后白屏几秒。这不是框架问题,而是网络 I/O 的天然延迟。
实操建议:
- 用
think-queue或workerman做消息队列,把sendSms()封装成任务类,dispatch()推入队列 - 避免在控制器里直接调用
$sms->send();哪怕加了try/catch,失败重试逻辑也得写进队列任务里 - 测试时用
php think queue:listen启动监听,别依赖浏览器刷新——队列失败不会报错到页面上
配置文件里不能硬编码 access_key_secret
很多开发者把阿里云的 access_key_secret 直接写进 config/sms.php,Git 提交后密钥就泄露了。
实操建议:
- 改用环境变量:在
.env里写ALIYUN_SMS_SECRET=xxx,然后在配置中用Env::get('aliyun_sms.secret') - 确保
.env已加入.gitignore;线上部署时由运维注入,不随代码下发 - 如果用腾讯云,注意它的
secret_key和secret_id是两组值,别和阿里云的字段名混用
验证码类短信必须校验签名与模板 Code 一致性
阿里云/腾讯云要求每个模板有唯一 template_code,且必须和后台申请的签名(sign_name)绑定。发错模板或签名不匹配,会返回 InvalidTemplateCode.NotFound 或 SignatureDoesNotMatch 错误。
实操建议:
- 在
config/sms.php中按场景分组定义模板,例如:'verify_login' => ['template' => 'SMS_123456789', 'sign' => '我的App'] - 发送前检查
isset(config('sms.templates.'.$scene)),而不是拼接字符串构造模板 ID - 测试阶段用沙箱号(如阿里云的
13800138000)验证签名是否审核通过,别一上来就用真实手机号
日志必须记录 template_code、mobile、response_code
短信是否真正发出、对方是否收到、运营商是否拦截——这些无法 100% 确认,但至少要留痕。只记“发送成功”没意义,response_code 为 OK 才算平台接收成功。
实操建议:
- 在队列任务的
handle()方法末尾加Log::info('sms.sent', ['mobile' => $this->mobile, 'template' => $this->template, 'code' => $result['Code'] ?? 'unknown']) - 不要用
Log::debug()记敏感信息(如完整 response body),Code和Message足够定位问题 - 线上出问题时,先 grep 日志里的
Code: InvalidPhoneNumber或Code: TemplateExpired,比翻代码快得多
template_code 仍可用;而腾讯云一旦更新模板,旧 code 就立即失效。这个差异不写文档、不测不发现。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











