接口类,需要指定入参类型,出参类型

news/2025/11/6 9:14:18/文章来源:https://www.cnblogs.com/hlgg/p/19195344

ThinkPHP6 短信发送工厂模式实现方案

根据你的需求,我设计了一套符合 接口规范 + 工厂模式 的短信发送方案,统一方法名和返回格式,支持动态切换腾讯云 / 阿里云接口,结构清晰且易于扩展。

一、目录结构(遵循 TP6 规范)

plaintext
 
 
app/
├── common/
│   └── lib/
│       ├── sms/
│       │   ├── contract/      # 接口契约
│       │   │   └── SmsInterface.php  # 短信接口规范
│       │   ├── dto/           # 数据传输对象(统一返回格式)
│       │   │   └── SmsResult.php     # 短信返回结构体
│       │   ├── impl/          # 第三方实现
│       │   │   ├── AliyunSms.php     # 阿里云短信实现
│       │   │   └── TencentSms.php    # 腾讯云短信实现
│       │   └── SmsFactory.php        # 短信工厂类
├── config/
│   └── sms.php                       # 短信配置文件
└── controller/└── TestController.php            # 测试控制器
 

二、核心实现代码

1. 接口契约(统一方法规范)

app/common/lib/sms/contract/SmsInterface.php
php
 
 
<?php
namespace app\common\lib\sms\contract;use app\common\lib\sms\dto\SmsResult;/*** 短信发送接口规范* 所有第三方短信实现必须遵循此接口*/
interface SmsInterface
{/*** 发送短信* @param string $phone 手机号(支持单个号码)* @param string $templateId 模板ID* @param array $templateParams 模板参数(键值对)* @return SmsResult 统一返回结构体*/public function send(string $phone, string $templateId, array $templateParams): SmsResult;
}
 

2. 统一返回结构体(类似 Go 的 struct)

app/common/lib/sms/dto/SmsResult.php
php
 
 
<?php
namespace app\common\lib\sms\dto;/*** 短信发送统一返回结构体* 规范所有第三方返回格式,便于上层处理*/
class SmsResult
{// 状态码:200=成功,其他=失败private int $code;// 业务消息private string $message;// 第三方原始响应数据(便于调试)private array $raw;// 自定义扩展数据(如短信ID、回执ID等)private array $extra = [];public function __construct(int $code, string $message, array $raw = [], array $extra = []){$this->code = $code;$this->message = $message;$this->raw = $raw;$this->extra = $extra;}// 快捷创建成功结果public static function success(string $message = '发送成功', array $raw = [], array $extra = []): self{return new self(200, $message, $raw, $extra);}// 快捷创建失败结果public static function fail(string $message = '发送失败', array $raw = [], array $extra = []): self{return new self(500, $message, $raw, $extra);}// getter方法(只读,确保数据不可篡改)public function getCode(): int{return $this->code;}public function getMessage(): string{return $this->message;}public function getRaw(): array{return $this->raw;}public function getExtra(): array{return $this->extra;}// 转为数组(便于接口返回)public function toArray(): array{return ['code' => $this->code,'message' => $this->message,'extra' => $this->extra,'raw' => app()->isDebug() ? $this->raw : [], // 调试模式才返回原始数据];}
}
 

3. 第三方实现 - 阿里云短信

app/common/lib/sms/impl/AliyunSms.php
php
 
 
<?php
namespace app\common\lib\sms\impl;use app\common\lib\sms\contract\SmsInterface;
use app\common\lib\sms\dto\SmsResult;
use AlibabaCloud\Client\AlibabaCloud;
use AlibabaCloud\Dyplsapi\Dyplsapi;
use think\facade\Config;class AliyunSms implements SmsInterface
{// 阿里云配置private array $config;public function __construct(){// 从配置文件读取阿里云配置$this->config = Config::get('sms.providers.aliyun', []);// 初始化阿里云客户端AlibabaCloud::accessKeyClient($this->config['access_key_id'],$this->config['access_key_secret'])->regionId($this->config['region_id'])->asDefaultClient();}/*** @inheritDoc*/public function send(string $phone, string $templateId, array $templateParams): SmsResult{try {// 调用阿里云短信API$result = Dyplsapi::v20170525()->sendSms()->withPhoneNumbers($phone)->withSignName($this->config['sign_name'])->withTemplateCode($templateId)->withTemplateParam(json_encode($templateParams, JSON_UNESCAPED_UNICODE))->request();$rawData = $result->toArray();// 解析阿里云返回结果,转为统一格式if ($rawData['Code'] === 'OK') {return SmsResult::success('阿里云短信发送成功', $rawData, ['biz_id' => $rawData['BizId'],'request_id' => $rawData['RequestId']]);} else {return SmsResult::fail("阿里云短信发送失败:{$rawData['Message']}",$rawData,['error_code' => $rawData['Code']]);}} catch (\Exception $e) {return SmsResult::fail("阿里云短信异常:{$e->getMessage()}",['exception' => $e->getMessage(), 'line' => $e->getLine()],['error_code' => $e->getCode()]);}}
}
 

4. 第三方实现 - 腾讯云短信

app/common/lib/sms/impl/TencentSms.php
php
 
 
<?php
namespace app\common\lib\sms\impl;use app\common\lib\sms\contract\SmsInterface;
use app\common\lib\sms\dto\SmsResult;
use Qcloud\Sms\SmsSingleSender;
use think\facade\Config;class TencentSms implements SmsInterface
{// 腾讯云配置private array $config;public function __construct(){// 从配置文件读取腾讯云配置$this->config = Config::get('sms.providers.tencent', []);}/*** @inheritDoc*/public function send(string $phone, string $templateId, array $templateParams): SmsResult{try {// 腾讯云短信要求参数为数组格式(按模板顺序)$params = array_values($templateParams);// 初始化腾讯云短信客户端$sender = new SmsSingleSender($this->config['app_id'],$this->config['app_key']);// 调用腾讯云短信API$result = $sender->sendWithParam($this->config['nation_code'], // 国家码(如86)$phone,$templateId,$params,$this->config['sign_name'], // 签名'', // 扩展码(可选)''  // 延伸码(可选));$rawData = json_decode($result, true) ?: [];// 解析腾讯云返回结果,转为统一格式if ($rawData['result'] === 0) {return SmsResult::success('腾讯云短信发送成功', $rawData, ['sid' => $rawData['sid'],'fee' => $rawData['fee']]);} else {return SmsResult::fail("腾讯云短信发送失败:{$rawData['errmsg']}",$rawData,['error_code' => $rawData['result']]);}} catch (\Exception $e) {return SmsResult::fail("腾讯云短信异常:{$e->getMessage()}",['exception' => $e->getMessage(), 'line' => $e->getLine()],['error_code' => $e->getCode()]);}}
}
 

5. 短信工厂类(动态创建实例)

app/common/lib/sms/SmsFactory.php
php
 
 
<?php
namespace app\common\lib\sms;use app\common\lib\sms\contract\SmsInterface;
use think\facade\Config;
use InvalidArgumentException;class SmsFactory
{/*** 动态创建短信实例* @param string $driver 驱动名称(aliyun/tencent)* @return SmsInterface* @throws InvalidArgumentException*/public static function make(string $driver = ''): SmsInterface{// 若未指定驱动,使用配置文件中的默认驱动$driver = $driver ?: Config::get('sms.default', 'aliyun');// 映射驱动到具体实现类$driverMap = ['aliyun' => \app\common\lib\sms\impl\AliyunSms::class,'tencent' => \app\common\lib\sms\impl\TencentSms::class,];// 验证驱动是否支持if (!isset($driverMap[$driver])) {throw new InvalidArgumentException("不支持的短信驱动:{$driver}");}$className = $driverMap[$driver];// 检查类是否存在并实现接口if (!class_exists($className) || !is_subclass_of($className, SmsInterface::class)) {throw new InvalidArgumentException("短信驱动类 {$className} 未实现 SmsInterface 接口");}// 创建实例(支持依赖注入)return app()->make($className);}
}
 

6. 配置文件

config/sms.php
php
 
 
<?php
return [// 默认短信驱动(aliyun/tencent)'default' => env('SMS_DEFAULT', 'aliyun'),// 第三方短信配置'providers' => [// 阿里云短信配置'aliyun' => ['access_key_id' => env('ALIYUN_SMS_ACCESS_KEY_ID', ''),'access_key_secret' => env('ALIYUN_SMS_ACCESS_KEY_SECRET', ''),'region_id' => env('ALIYUN_SMS_REGION_ID', 'cn-hangzhou'),'sign_name' => env('ALIYUN_SMS_SIGN_NAME', ''), // 短信签名],// 腾讯云短信配置'tencent' => ['app_id' => env('TENCENT_SMS_APP_ID', ''),'app_key' => env('TENCENT_SMS_APP_KEY', ''),'nation_code' => env('TENCENT_SMS_NATION_CODE', '86'), // 国家码'sign_name' => env('TENCENT_SMS_SIGN_NAME', ''), // 短信签名],],
];
 

7. 环境变量配置(.env)

env
 
 
# 短信配置
SMS_DEFAULT=aliyun # 默认驱动# 阿里云短信
ALIYUN_SMS_ACCESS_KEY_ID=your_access_key_id
ALIYUN_SMS_ACCESS_KEY_SECRET=your_access_key_secret
ALIYUN_SMS_SIGN_NAME=你的短信签名# 腾讯云短信
TENCENT_SMS_APP_ID=your_app_id
TENCENT_SMS_APP_KEY=your_app_key
TENCENT_SMS_SIGN_NAME=你的短信签名
 

三、使用示例(控制器调用)

app/controller/TestController.php
php
 
 
<?php
namespace app\controller;use app\common\lib\sms\SmsFactory;
use app\common\lib\sms\dto\SmsResult;
use think\facade\Log;
use think\response\Json;class TestController
{/*** 发送短信示例* @return Json*/public function sendSms(): Json{try {// 1. 通过工厂类创建短信实例(动态切换驱动)// $sms = SmsFactory::make('tencent'); // 手动指定腾讯云$sms = SmsFactory::make(); // 使用默认驱动// 2. 调用统一的send方法发送短信$phone = '13800138000'; // 接收手机号$templateId = 'SMS_123456789'; // 短信模板ID$templateParams = ['code' => rand(100000, 999999), // 验证码'expire' => '5' // 有效期(分钟)];/** @var SmsResult $result */$result = $sms->send($phone, $templateId, $templateParams);// 3. 统一处理返回结果if ($result->getCode() === 200) {Log::info("短信发送成功:手机号={$phone},回执ID={$result->getExtra()['biz_id'] ?? ''}");return json($result->toArray(), 200);} else {Log::error("短信发送失败:手机号={$phone},错误信息={$result->getMessage()},原始数据=" . json_encode($result->getRaw()));return json($result->toArray(), 500);}} catch (\Exception $e) {Log::error("短信发送异常:{$e->getMessage()}", ['trace' => $e->getTraceAsString()]);return json(['code' => 500,'message' => '短信发送异常:' . $e->getMessage()], 500);}}
}
 

四、依赖安装

需要安装对应第三方 SDK:
bash
 
 
# 阿里云SDK
composer require alibabacloud/dyplsapi-20170525# 腾讯云SDK
composer require qcloudsms/qcloudsms_php
 

五、核心特性说明

  1. 接口规范约束:所有第三方实现必须遵循 SmsInterface,确保方法名(send)和参数格式统一
  2. 统一返回格式:通过 SmsResult DTO 类,规范返回结构(类似 Go 的 struct),上层无需关心第三方差异
  3. 工厂模式动态切换:通过 SmsFactory::make() 可快速切换驱动,无需修改业务代码
  4. 配置分离:敏感配置放在环境变量,支持多环境部署
  5. 调试友好:调试模式下返回第三方原始响应,便于问题排查
  6. 扩展性强:新增短信服务商(如华为云、极光短信)时,只需:
    • 新建实现类并实现 SmsInterface
    • 在工厂类的 driverMap 中添加映射
    • 在配置文件中添加对应配置

六、注意事项

  1. 需先在对应云服务商控制台完成短信签名和模板的审核
  2. 确保环境变量中配置了正确的 AccessKey、AppID 等敏感信息
  3. 生产环境建议关闭调试模式(app_debug=false),避免泄露原始响应数据
  4. 可根据实际需求扩展 SmsInterface(如添加批量发送、短信回执查询等方法)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/957369.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025年质量好的杭州全屋定制优选厂家排行榜

2025年质量好的杭州全屋定制优选厂家排行榜 随着人们对居住环境要求的不断提高,全屋定制已成为现代家装的主流趋势。杭州作为国内家装行业的重要城市,拥有众多实力雄厚的全屋定制企业。本文精选2025年杭州地区口碑与…

2025年评价高的翻身护理床厂家最新TOP排行榜

2025年评价高的翻身护理床厂家最新TOP排行榜 随着老龄化社会的加速发展,翻身护理床作为适老化家居的重要组成部分,市场需求持续增长。优质的翻身护理床不仅能提升卧床老人的生活质量,还能减轻护理人员的负担。2025…

2025年比较好的西安户外露营救援低温电池厂家最新推荐权威榜

2025年西安户外露营救援低温电池厂家最新推荐权威榜 随着户外露营、应急救援等场景对低温电池需求的快速增长,西安作为西北地区科技产业高地,涌现出一批专注于高性能低温电池研发的优质企业。以下是2025年综合技术实…

MySQL 统计每个时间段的数量

数据库存放数据如下: SELECT t.start_time,t.end_time FROM vipsoft_order tMySQL SELECT CONCAT(LPAD(hour_range, 2, 0), :00~, LPAD(hour_range + 1, 2, 0), :00) as time_period,SUM(CASE WHEN HOUR(start_time) …

2025年靠谱的干冰清洗设备用户口碑最好的厂家榜

2025年靠谱的干冰清洗设备用户口碑最好的厂家榜 干冰清洗技术凭借其高效、环保、无损伤等优势,已成为工业清洗领域的重要选择。随着市场需求的增长,干冰清洗设备厂家如雨后春笋般涌现,但真正值得信赖的品牌却需要经…

怎样把golang的程序编译为Service

在linux的目录下面编写service 文件: /etc/systemd/syste/gok8s.service 保存后加载: systemctl daemond-reloadsystemctl start gok8s//注意: 路径一定要正确,权限要给够[Unit] Description=gok8s After=network.…

2025年喷砂机品牌新排行榜白皮书,博拉斯特喷砂机可靠吗

2025年表面处理行业朝着智能化、环保化方向加速迭代,喷砂机作为金属加工、汽车制造、电子五金等领域的核心处理设备,其性能稳定性、自动化程度、环保合规性直接影响企业生产效率与合规成本。然而当前市场中,喷砂机厂…

2025年靠谱的散热器哪家好?电脑散热器生产厂排名全解析

在人工智能、大数据计算与智能驾驶技术爆发式增长的当下,散热性能已成为制约高精尖设备稳定运行的核心瓶颈。面对市场上良莠不齐的散热器供应商,企业如何找到兼具技术实力、品质保障与丰富案例的合作伙伴?以下是202…

2025年自建房门窗生产厂家权威推荐榜单:封包阳台窗/性价比门窗/断桥铝门窗源头厂家精选

面对市场众多选择,五大实力厂家以技术硬实力与服务可靠性脱颖而出。 随着建筑节能标准的提升与消费者对高品质家居需求的增长,自建房门窗市场正迎来快速发展。据行业统计,2025年系统门窗市场规模已突破1000亿元,其…

2025年口碑好的防撞重型纸箱厂家最新热销排行

2025年口碑好的防撞重型纸箱厂家最新热销排行 在工业包装领域,重型防撞纸箱因其出色的承重性、缓冲性和环保特性,成为机械设备、电子产品、危化品运输等行业的首选包装方案。随着市场竞争加剧,消费者对厂家的技术实…

【2025-11-05】在意评价

20:00让我们谨记,我们是和人打交道,不是与逻辑打交道。我们是与有感情的动物相处,这个动物充斥着偏见、骄傲和虚荣。——戴尔卡耐基又是忙碌的一天,忙到我的副手都在叹息太忙了。当然,相比较于他平时那种“休闲”…

CF1485D Multiples and Power Differences

首先发现第 \(3\) 个限制很难办,我们想 \(k = 0\) 怎么做。 发现 \(a_{i, j}\) 是很小的,我们求个 \(lcm\) 每个位置都填上即可。 然后黑白染色,往黑色格子里加个 \(a_{i, j}^4\) 即可。

2025年热门的反弹缓冲托底轨行业内口碑厂家排行榜

2025年热门的反弹缓冲托底轨行业内口碑厂家排行榜 随着家居五金行业的快速发展,反弹缓冲托底轨作为高端家具的核心配件,其市场需求持续增长。优质的缓冲托底轨不仅能提升家具的使用寿命,还能增强用户体验,因此选择…

2025年业内口碑好的建筑模板厂家推荐及选购指南

2025年业内口碑好的建筑模板厂家推荐及选购指南 建筑模板作为建筑施工中不可或缺的材料,其质量直接影响工程的安全性和施工效率。随着建筑行业的快速发展,市场对高品质建筑模板的需求日益增长。本文将为您推荐2025年…

2025年评价高的油雾空气过滤器TOP实力厂家推荐榜

2025年评价高的油雾空气过滤器TOP实力厂家推荐榜 在工业制造、医疗、食品加工等领域,油雾空气过滤器的应用越来越广泛。高效、耐用的油雾过滤器不仅能改善工作环境,还能提升生产设备的寿命,降低维护成本。2025年,…

2025年靠谱的水泥基防火涂料用户好评厂家排行

2025年靠谱的水泥基防火涂料用户好评厂家排行 在建筑防火安全领域,水泥基防火涂料因其优异的耐火性能和环保特性,已成为工业与民用建筑防火工程的首选材料。随着国家消防标准的日益严格和市场需求持续增长,选择一家…

2025年靠谱的等速降温平板硫化机行业内知名厂家排行榜

2025年靠谱的等速降温平板硫化机行业内知名厂家排行榜行业概述等速降温平板硫化机作为高分子材料加工领域的关键设备,在橡胶、塑料、复合材料等行业中扮演着不可或缺的角色。随着新材料技术的快速发展,市场对高精度、…

Mappa 语音 AI 招聘:声学信号分析候选人表现,ARR 300 万美元;上海银行推出首个沪语交互 AI 应用丨日报

开发者朋友们大家好:这里是 「RTE 开发者日报」 ,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE(Real-Time Engagement) 领域内「有话题的技术」、「有亮点的产品」、「有思考的文章」、「有态…