使用overtrue/easy-sms集成阿里云短信网关最稳妥,避免手动curl遗漏签名、编码及错误处理;tp6中配置凭证、模板code后传手机号和变量数组即可发送,需校验手机号格式并用cache存储验证码确保安全校验。

直接用 overtrue/easy-sms + 阿里云网关是最稳的路径,硬写 cURL 容易漏掉签名、编码、错误码处理这些关键点。
ThinkPHP6 用 easy-sms 发送短信验证码
别自己拼 URL 和 curl 参数,overtrue/easy-sms 已经封装好阿里云、腾讯云、云片等主流网关,适配 ThinkPHP6 的容器和配置体系。
- 执行
composer require overtrue/easy-sms -vvv安装扩展包 - 在
config/sms.php中填入阿里云凭证:access_key_id、access_key_secret、sign_name和模板template(注意不是模板内容,是控制台生成的TEMPLATE_CODE) - 发送时只传手机号和变量数组,比如
['code' => '123456'],变量名必须和你在阿里云模板里写的${code}严格一致 - 务必在调用前检查手机号格式:
preg_match('/^1[3-9]\d{9}$/', $mobile),避免无效请求触发限流
ThinkPHP5.1 手动集成阿里云 SDK 的坑
官方 PHP SDK(aliyun-openapi-php-sdk)在 TP5.1 下容易因命名空间或 autoload 冲突报 Class not found,尤其当你把 SDK 放进 extend/ 后没改 composer.json 的 autoload PSR-4 映射。
- 不建议直接解压 SDK 到
extend/并手动 require —— 更可靠的做法是用composer require alibabacloud/sdk,再通过AlibabaCloud::accessKeyClient()初始化 - 阿里云要求所有参数按字典序排序后参与签名,手动拼参极易出错;SDK 自动处理,但你要确保传入的
TemplateParam是 JSON 字符串,不是 PHP 数组(否则会签名失败返回InvalidParameter) - 错误码
isv.BUSINESS_LIMIT_CONTROL表示该手机号 1 小时内超频(默认 5 条),不是代码问题,得查业务逻辑是否重复触发
短信验证码的存储与校验必须匹配
发出去的验证码,必须存在服务端可验证的地方,且过期时间、单次有效性、IP 或手机号维度限频要统一设计。
- 别用
cookie存验证码值 —— 客户端可篡改,且跨域、HTTPS 下可能失效;改用cache()->set("sms:{$mobile}", $code, 300) - 校验时用
cache()->get("sms:{$mobile}") === $inputCode,注意是全等(===),防止类型转换绕过(比如 '000123' 和 123 被当成相等) - 每次发送新验证码前,先
cache()->delete("sms:{$mobile}"),避免旧码未过期就覆盖,导致用户收不到最新短信却能用旧码通过 - 如果用 Redis,确认缓存驱动配置了序列化方式(如
serialize),否则存进去的是对象,取出来是字符串,校验永远失败
云片、创世华信等第三方平台的参数差异
不同厂商对参数名、编码、认证方式要求不一,硬编码会导致换平台时大量重写。
- 云片用
apikey+mobile+text,text必须含签名,如【小太阳】您的验证码是1234,不能只传纯数字 - 创世华信用
account/password(MD5 大写),且password是明文 MD5,不是接口返回的密钥,填错直接returnstatus=error - 所有平台都要求
Content-Type: application/x-www-form-urlencoded,但 ThinkPHP 的Http::post()默认发 JSON,得显式设form_params或用raw()手动拼 body - 响应体格式不统一:云片返回 JSON,创世华信返回 XML,阿里云返回标准 JSON 但字段嵌套深(
data->Message),解析前先json_decode($res, true)并判空
真正难的不是“怎么发出去”,而是“怎么确保它只被正确的人、在正确的时间、用正确的方式验证”。签名、缓存键设计、错误码映射、限频策略——这些细节一旦松动,安全性和用户体验就同步崩塌。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











