Laravel如何集成阿里云短信_Laravel 短信发送接口实现【实战】

6次阅读

应使用 jacobcyl/aliyunsms 而非 aliyun/aliyun-openapi-php-sdk,因其专为 laravel 设计,支持 .env 配置、服务提供者和队列,避免签名失败、参数校验错误及初始化问题。

Laravel如何集成阿里云短信_Laravel 短信发送接口实现【实战】

直接用 aliyun/aliyun-openapi-php-sdk 在 Laravel 里发短信,大概率会卡在签名失败、参数校验不通过、或 SDK 初始化报错——不是 Laravel 不兼容,而是阿里云新版 OpenAPI SDK(v2+)默认不支持 Laravel 的自动加载和配置管理方式。

为什么不能直接 composer require aliyun/aliyun-openapi-php-sdk

这个 SDK 是面向传统 PHP 脚本设计的,依赖全局 require_once 和手动实例化客户端,没有服务提供者、不读取 .env、也不适配 Laravel 的容器绑定。强行引入会导致:

  • AlibabaCloudClientAlibabaCloud 类找不到(autoload 未注册)
  • 每次发短信都要重复写 endpoint、accessKeyId、accessKeySecret,无法复用配置
  • 签名算法用的是旧版 ACS,而阿里云短信新控制台强制要求 rpc 风格 + V2 签名

推荐方案:用 aliyun-dysms-php + 自定义 Facade

这是目前最轻量、最稳定、且适配 Laravel 8+ 的选择。它只封装短信核心逻辑,不带 SDK 依赖,所有参数走 config().env,还能无缝接入队列。

操作步骤:

  • 执行 composer require jacobcyl/aliyunsms(注意作者是 jacobcyl,不是官方包)
  • 发布配置:运行 php artisan vendor:publish --provider="JacobcylAliyunSmsAliyunSmsServiceProvider"
  • .env 中填入:ALIYUN_SMS_ACCESS_KEY_ID=xxxALIYUN_SMS_ACCESS_KEY_SECRET=yyyALIYUN_SMS_REGION_ID=cn-hangzhouALIYUN_SMS_SIGN_NAME="你的签名"ALIYUN_SMS_TEMPLATE_CODE="SMS_123456789"
  • 发短信示例:
    $result = AliyunSms::sendSms('13800138000', ['code' => '1234'], 'SMS_123456789');

    返回数组含 CodeMessageBizId,不用再手动解析 xml/json

发送失败常见错误及对应处理

实际部署时最常遇到三个报错,都跟配置或环境强相关:

  • InvalidAccessKeyId.NotFound:检查 ALIYUN_SMS_ACCESS_KEY_ID 是否复制了空格,是否用了 RAM 子账号但没给 AliyunDysmsFullAccess 权限
  • isv.BUSINESS_LIMIT_CONTROL:新申请的 AccessKey 默认有流控(1 条/秒),测试期建议先在阿里云控制台把短信模板设置为“测试模板”,或提交工单提额
  • SignatureDoesNotMatch:90% 是因为 ALIYUN_SMS_REGION_ID 写成了 https://dysmsapi.aliyuncs.com 这种完整 URL,它只要区域 ID,比如 cn-hangzhou

如果必须用官方 SDK(比如要同时调用 OSS + 短信)

可以保留 aliyun/aliyun-openapi-php-sdk,但得绕过它的 autoload 机制,手动引入关键类:

  • 下载 SDK 源码,把 aliyun-openapi-php-sdk/aliyun-openapi-php-sdk/aliyun-php-sdk-corealiyun-openapi-php-sdk/aliyun-openapi-php-sdk/aliyun-php-sdk-dysmsapi 复制到 app/Services/Aliyun/
  • AppServiceProvider::boot() 中加:
    require_once app_path('Services/Aliyun/core/Config.php');<br>require_once app_path('Services/Aliyun/dysmsapi/Dysmsapi.php');
  • 构造客户端时显式指定 RegionIdEndpoint
    $client = new DefaultAcsClient(AliyunCoreProfileDefaultProfile::getProfile(<br>    config('aliyun_sms.region_id'),<br>    config('aliyun_sms.access_key_id'),<br>    config('aliyun_sms.access_key_secret')<br>));<br>$client->setEndpoint('https://dysmsapi.aliyuncs.com');

这种做法维护成本高,升级 SDK 就得重新复制文件,仅建议已有项目深度耦合官方 SDK 的场景。

text=ZqhQzanResources