symfony集成短信服务需四步:①安装依赖并配置sms.yaml;②定义smsgatewayinterface及抽象基类;③按厂商规范接入阿里云(sdk直连)或腾讯云(http签名);④注册服务、启用notifier组件并通过notifierinterface发送。

在 Symfony 项目中集成短信服务,让订单完成、密码重置等关键事件能通过短信触达用户,需要对接第三方短信网关(如阿里云、腾讯云、华为云或自建 SMPP 网关),并封装为可复用、可配置、可测试的通知服务。
安装依赖与基础配置
执行 composer 命令安装官方推荐的 HTTP 客户端和配置管理扩展:composer require symfony/http-client symfony/config symfony/options-resolver。
创建 config/packages/sms.yaml,定义默认网关类型、超时时间、重试次数等全局参数。该文件必须存在,否则后续服务无法加载配置。
这一步不能跳过——【Symfony 的服务容器在编译期读取 config/packages/ 下的 YAML 文件,缺失 sms.yaml 会导致 SmsGatewayInterface 无法自动绑定实现类】。
定义短信网关接口与抽象基类
在 src/Contract/SmsGatewayInterface.php 中声明核心方法:send(string $phone, string $message): bool 和 batchSend(array $recipients, string $message): int。
新建 src/AbstractSmsGateway.php,继承 AbstractNotifier(来自 symfony/notifier)并实现 SmsGatewayInterface;它统一处理签名拼接、模板变量替换、编码校验逻辑,避免每个厂商 SDK 重复实现。
注意:不要直接在控制器里 new 出具体网关实例——那样会破坏依赖注入原则,也无法启用 Symfony 的服务装饰、参数绑定和环境隔离。
接入阿里云短信服务(方法一:SDK 直连)
执行 composer require alibabacloud/sdk。
创建 src/Sms/Gateway/AliyunSmsGateway.php,构造函数接收 AcsClient 实例和配置数组(accessKeyId、accessKeySecret、regionId、signName、templateCode)。
在 send() 方法内调用 $this->client->rpcRequest('https://dysmsapi.aliyuncs.com', 'SendSms', [...]),传入 PhoneNumbers、SignName、TemplateCode 和 TemplateParam(JSON 字符串);返回结果需检查 Code === 'OK' 才视为成功。
⚠️ 阿里云要求 TemplateParam 必须是合法 JSON 字符串,传数组会触发 400 错误;务必用 json_encode($params, JSON_UNESCAPED_UNICODE) 处理中文参数。
接入腾讯云短信服务(方法二:HTTP API 封装)
不安装官方 SDK,改用轻量级 HTTP 调用:构造 POST 请求到 https://sms.tencentcloudapi.com,Header 设置 Content-Type: application/json; charset=utf-8 和 Authorization 签名头。
签名生成必须严格按腾讯云文档要求:对请求参数按字典序排序 → 拼接成 query string → SHA256-HMAC + SecretKey → Base64 编码 → 放入 Authorization 头。少一个字符都会返回 401。
发送成功后响应体中的 SmsSdkAppId 必须与配置一致,否则说明密钥或应用 ID 错误,日志里会显示 InvalidParameterValue.AppId。
注册服务并启用通知组件
第一步:在 src/DependencyInjection/SmsExtension.php 中,读取 sms.yaml 配置,根据 gateway: aliyun 或 gateway: tencent 动态注册对应网关服务,并设置为 SmsGatewayInterface 的别名。
第二步:运行 php bin/console debug:container --types SmsGatewayInterface,确认服务已注册且非私有。
第三步:在 config/packages/notifier.yaml 中添加渠道配置:transports: sms: 'sms://default';再声明 chatters: sms: 'sms://default',使 Notifier 组件能识别短信通道。
第四步:在控制器或监听器中注入 NotifierInterface,调用 $notifier->send(new SmsMessage('+8613800138000', '验证码:1234')) 即可触发发送。











