Search by

youvision / think-easysms

indiboy-create

ThinkPHP 8 短信发送组件,基于 overtrue/easy-sms 实现多网关短信发送

Package info

github.com/indiboy-create/think-easysms

pkg:composer/youvision/think-easysms

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.0 2026-11-07 20:58 UTC

This package is auto-updated.

Last update: 2026-11-11 03:19:01 UTC


README

面向 ThinkPHP 的开源工程索引:组件、框架、服务与发布工具,按能力组织,持续整理。 仓库地址:https://github.com/indiboy-create/ThinkPHP-PanGu/ 在线站点:https://indiboy-create.github.io/ThinkPHP-PanGu/

think-easysms

基于 overtrue/easy-sms 的 ThinkPHP 8 短信发送组件。

  • 一套写法兼容阿里云、腾讯云、华为云、云片、Submail、容联云通讯等 30+ 服务商
  • 按顺序或轮询自动切换网关,失败自动尝试下一个
  • 支持自定义网关、自定义短信消息类、国际短信
  • 与 ThinkPHP 容器、门面、依赖注入无缝集成

环境要求

  • PHP >= 8.0
  • ThinkPHP >= 8.0
  • overtrue/easy-sms ^3.2

安装

composer require youvision/think-easysms

ThinkPHP 8 项目的 composer.json 通常已配置以下脚本,安装完成后会自动发现服务并发布配置:

"scripts": {
    "post-autoload-dump": [
        "@php think service:discover",
        "@php think vendor:publish"
    ]
}

若没有自动执行,可手动运行:

php think service:discover
php think vendor:publish

执行后项目根目录会生成 config/easysms.php。

配置

编辑 config/easysms.php,至少配置一个可用网关,并将默认网关改为该网关:

return [
    'timeout' => 5.0,

    'default' => [
        'strategy' => \Overtrue\EasySms\Strategies\OrderStrategy::class,
        'gateways' => ['aliyun'],
    ],

    'gateways' => [
        'aliyun' => [
            'access_key_id' => env('EASYSMS_ALIYUN_ACCESS_KEY_ID'),
            'access_key_secret' => env('EASYSMS_ALIYUN_ACCESS_KEY_SECRET'),
            'sign_name' => env('EASYSMS_ALIYUN_SIGN_NAME'),
        ],
    ],
];

配置项说明:

配置项 说明
timeout HTTP 请求超时时间,单位秒,可被单个网关的 timeout 覆盖
options 所有网关共享的 Guzzle 请求选项,如代理、证书、请求头
default.strategy 网关选择策略,OrderStrategy 顺序尝试,RoundRobinStrategy 轮询
default.gateways 默认网关列表,数组顺序即尝试顺序
gateways 各服务商凭证,仅需配置实际使用的网关
extend 自定义网关,值为网关类名或工厂闭包

默认网关为 errorlog,短信内容会写入 runtime/easysms.log,不会真正发送,便于本地调试。生产环境请务必修改。

快速开始

使用门面

use Youvision\ThinkEasySms\Sms;

$result = Sms::send('13800138000', [
    'content'  => '您的验证码为:6379,5 分钟内有效。',
    'template' => 'SMS_001',
    'data'     => ['code' => 6379],
]);

依赖注入

use Youvision\ThinkEasySms\EasySms;

class Login
{
    public function __construct(protected EasySms $sms)
    {
    }

    public function sendCode(string $phone, int $code): array
    {
        return $this->sms->send($phone, [
            'content'  => "您的验证码为:{$code}",
            'template' => 'SMS_001',
            'data'     => ['code' => $code],
        ]);
    }
}

也可以注入底层客户端:

use Overtrue\EasySms\EasySms as EasySmsClient;

public function __construct(protected EasySmsClient $client)
{
}

短信内容

由于同一条短信可能通过不同网关发送,组件抽象了三个通用属性:

  • content:短信正文,适用于云片等按内容发送的平台
  • template:模板 ID,适用于按模板发送的平台
  • data:模板变量,适用于按模板发送的平台
Sms::send('13800138000', [
    'content'  => '您的验证码为:6379',
    'template' => 'SMS_001',
    'data'     => ['code' => 6379],
]);

content、template、data 都支持闭包,可根据网关动态返回不同内容:

Sms::send('13800138000', [
    'template' => function ($gateway) {
        return $gateway->getName() === 'aliyun' ? 'SMS_ALIYUN_001' : 'SMS_001';
    },
    'data' => ['code' => 6379],
]);

指定网关

单条短信可以覆盖默认网关配置:

Sms::send('13800138000', $message, ['qcloud', 'aliyun']);

也可以直接发送字符串内容:

Sms::send('13800138000', '您的验证码为:6379');

返回值与异常

发送成功时返回每个网关的结果数组:

[
    'aliyun' => [
        'gateway' => 'aliyun',
        'status'  => 'success',
        'template' => 'SMS_001',
        'result'  => [/* 服务商原始返回值 */],
    ],
]

所有网关均失败时抛出 Overtrue\EasySms\Exceptions\NoGatewayAvailableException:

use Overtrue\EasySms\Exceptions\NoGatewayAvailableException;

try {
    Sms::send('13800138000', $message);
} catch (NoGatewayAvailableException $e) {
    $e->getResults();        // 所有网关的发送结果
    $e->getExceptions();     // 所有异常
    $e->getLastException();  // 最后一个异常
}

自定义网关

通过配置注册

实现 Overtrue\EasySms\Contracts\GatewayInterface,然后在配置中注册:

// config/easysms.php
'extend' => [
    'mygateway' => \app\sms\MyGateway::class,
],

将 mygateway 加入 default.gateways 即可使用。

运行时注册

use Youvision\ThinkEasySms\Sms;

Sms::extend('mygateway', function (array $config) {
    return new \app\sms\MyGateway($config);
});

Sms::send('13800138000', $message, ['mygateway']);

国际短信

use Overtrue\EasySms\PhoneNumber;
use Youvision\ThinkEasySms\Sms;

$number = new PhoneNumber(13188888888, 31);

Sms::send($number, [
    'content'  => 'Your verification code is 6379',
    'template' => 'SMS_001',
    'data'     => ['code' => 6379],
]);

自定义短信消息

针对固定业务场景,可继承 Overtrue\EasySms\Message,实现一处定义、多处调用:

use Overtrue\EasySms\Contracts\GatewayInterface;
use Overtrue\EasySms\Message;
use Overtrue\EasySms\Strategies\OrderStrategy;

class OrderPaidMessage extends Message
{
    protected string $strategy = OrderStrategy::class;

    protected array $gateways = ['aliyun', 'qcloud'];

    public function __construct(protected string $orderNo)
    {
    }

    public function getContent(?GatewayInterface $gateway = null): ?string
    {
        return "您的订单 {$this->orderNo} 已完成付款";
    }

    public function getTemplate(?GatewayInterface $gateway = null): ?string
    {
        return 'SMS_003';
    }

    public function getData(?GatewayInterface $gateway = null): array
    {
        return ['order_no' => $this->orderNo];
    }
}
Sms::send('13800138000', new OrderPaidMessage('202601010001'));

常用网关配置示例

腾讯云

短信使用 template + data,data 按模板占位顺序传值:

'qcloud' => [
    'sdk_app_id'  => env('EASYSMS_QCLOUD_SDK_APP_ID'),
    'secret_id'   => env('EASYSMS_QCLOUD_SECRET_ID'),
    'secret_key'  => env('EASYSMS_QCLOUD_SECRET_KEY'),
    'sign_name'   => env('EASYSMS_QCLOUD_SIGN_NAME'),
],
Sms::send('13800138000', [
    'template' => 101234,
    'data'     => ['6379', '5'],
]);

华为云

'huawei' => [
    'endpoint'   => env('EASYSMS_HUAWEI_ENDPOINT'),
    'app_key'    => env('EASYSMS_HUAWEI_APP_KEY'),
    'app_secret' => env('EASYSMS_HUAWEI_APP_SECRET'),
    'from'       => [
        'default' => env('EASYSMS_HUAWEI_FROM'),
        'custom'  => 'csms12345',
    ],
],
Sms::send('13800138000', [
    'template' => 'SMS_001',
    'data'     => ['6379', 'from' => 'custom'],
]);

云片

短信使用 content:

'yunpian' => [
    'api_key'   => env('EASYSMS_YUNPIAN_API_KEY'),
    'signature' => '【默认签名】',
],

调试网关

'errorlog' => [
    'file' => runtime_path() . 'easysms.log',
],

更多网关及其参数见 easy-sms 官方文档。

测试

composer install
vendor/bin/phpunit

License

MIT