组件实现了一套干净、简洁的 API ,并为诸多第三方短信发送服务提供了相应的驱动,让你可以快速、简单地从您的应用发送短信。驱动基本移植自 overtrue/easy-sms ,同时借鉴了其网关策略并进行了扩展。
composer require hyperf-ext/smsphp bin/hyperf.php vendor:publish hyperf-ext/sms配置文件中的 senders 节点配置的每个发送器配置都有自己的「驱动」和配置选项,这将允许你的应用程序使用不同的短信服务来发送特定的消息。例如,你的应用程序可能使用阿里云发送验证码类消息,而使用腾讯云发送通知类消息。再或者为同类消息配置多个发送器来提高服务可用性。
短信消息类可用配置内容方法:template,with,signature
[
'driver' => \HyperfExt\Sms\Drivers\AliyunDriver::class,
'config' => [
'access_key_id' => '',
'access_key_secret' => '',
'sign_name' => '',
],
]短信消息类可用配置内容方法:template,with
[
'driver' => \HyperfExt\Sms\Drivers\BaiduCloudDriver::class,
'config' => [
'ak' => '',
'sk' => '',
'invoke_id' => '',
'domain' => '',
],
]短信消息类可用配置内容方法:template,with,from
[
'driver' => \HyperfExt\Sms\Drivers\HuaweiCloudDriver::class,
'config' => [
'endpoint' => '', // 从管理控制台获取到的 App 接入地址'app_key' => '',
'app_secret' => '',
'from' => [
'default' => '', // 默认签名通道号// 'another' => '', // 其他签名通道号
],
],
]短信消息类可用配置内容方法:template,with
[
'driver' => \HyperfExt\Sms\Drivers\JuheDataDriver::class,
'config' => [
'app_key' => '',
],
]短信消息类可用配置内容方法:content
[
'driver' => \HyperfExt\Sms\Drivers\LuosimaoDriver::class,
'config' => [
'app_key' => '',
],
]短信消息类可用配置内容方法:template,with
[
'driver' => \HyperfExt\Sms\Drivers\QiniuDriver::class,
'config' => [
'secret_key' => '',
'access_key' => '',
],
]短信消息类可用配置内容方法:template,with
[
'driver' => \HyperfExt\Sms\Drivers\RongCloudDriver::class,
'config' => [
'app_key' => '',
'app_secret' => '',
],
]短信消息类可用配置内容方法:template,with
[
'driver' => \HyperfExt\Sms\Drivers\RonglianDriver::class,
'config' => [
'app_id' => '',
'account_sid' => '',
'account_token' => '',
'is_sub_account' => false,
],
]短信消息类可用配置内容方法:template,with
[
'driver' => \HyperfExt\Sms\Drivers\SendCloudDriver::class,
'config' => [
'sms_user' => '',
'sms_key' => '',
'timestamp' => false, // 是否启用时间戳
],
]短信消息类可用配置内容方法:template,with
[
'driver' => \HyperfExt\Sms\Drivers\SmsBaoDriver::class,
'config' => [
'user' => '',
'password' => '',
],
]短信消息类可用配置内容方法:template,with,signature
[
'driver' => \HyperfExt\Sms\Drivers\TencentCloudDriver::class,
'config' => [
'sdk_app_id' => '',
'secret_id' => '',
'secret_key' => '',
'sign' => null, // 短信签名'from' => [ // SenderId,中国大陆地区无需配置'default' => '', // 默认 SenderId// 'another' => '', // 其他 SenderId
],
],
]短信消息类可用配置内容方法:content
[
'driver' => \HyperfExt\Sms\Drivers\TwilioDriver::class,
'config' => [
'account_sid' => '',
'token' => '',
'from' => [
'default' => '',
// 'another' => '',
],
],
]短信消息类可用配置内容方法:template、with、signature
[
'driver' => \HyperfExt\Sms\Drivers\UCloudDriver::class,
'config' => [
'private_key' => '',
'public_key' => '',
'sig_content' => '', // 短信签名'project_id' => '', // 项目ID,子账号才需要该参数
],
]短信消息类可用配置内容方法:content、signature
[
'driver' => \HyperfExt\Sms\Drivers\YunpianDriver::class,
'config' => [
'api_key' => '',
'signature' => '', // 短信签名,内容中无签名时使用
],
]短信消息类可用配置内容方法:template,with
[
'driver' => \HyperfExt\Sms\Drivers\YunxinDriver::class,
'config' => [
'app_key' => '',
'app_secret' => '',
'code_length' => 4, // 随机验证码长度,范围 4~10,默认为 4'need_up' => false, // 是否需要支持短信上行
],
]应用发送的每种消息都被表示为短信消息类。这些类存储于 app/Sms 目录中。如果您的应用中没有该目录,别慌,当您使用 gen:sms 命令生成您的首个短信消息类时,应用将会自动创建它:
php bin/hyperf.php gen:sms VerificationCode所有的短信消息类的配置都在 build 方法中完成。您可以通过调用诸如 content、template、signature 和 from 这样的各种各样的方法来配置消息的内容及其发送。
在发送消息前,您需要指定哪些发送器可被用于发送消息。有两种方式来指定可用发送器。
您可以通过配置文件的 default.senders 节点来指定默认的被用于发送消息的发送器,值类型可以是 array 或 string。
[
'default' => [
'senders' => ['aliyun', 'twillo'],
],
]您也可以通过短信消息类的 senders 公开属性来指定可用发送器,如果您未在短信消息类中指定,那么在发送时会自动使用配置文件中指定的发送器。
useHyperfExt\Sms\Smsable;
class VerificationCode extends Smsable
{
public$senders = ['aliyun', 'twillo'];
}由于短信服务提供商所服务的地区是有限的,亦或是因各地区价格因素的考量,您可能会为此使用多个提供商来让您的业务覆盖尽可能多的地区,此时您可为指定地区的号码配置指定的发送器。
[
'aliyun' => ['cn', 'hk', 'mo', 'tw'], // 仅当手机号是大陆和港澳台地区时使用阿里云和腾讯云'tencent_cloud' => ['cn', 'hk', 'mo', 'tw'],
'twillo', // 大陆和港澳台地区以外使用 Twillo
]地区代码使用 ISO 3166-1 两位地区代码,不区分大小写。
发送器的筛选逻辑在内建的发送器策略中实现,您可以通过自定义发送器策略来根据自身需求实现自己的处理逻辑。
发送器策略是在使用多个发送器的情况下,用来确定发信程序以何种顺序来选择发送器的排序和筛选程序。当一个发送器发送失败后会根据顺序选择下一个发送器,直到发送成功。
组件内建 OrderStrategy 和 RandomStrategy 两个默认的策略。OrderStrategy 策略依照您指定发送器的顺序来选择发送器。RandomStrategy 策略则将发送器列表打乱来随机排序。
就像配置发送器一样,发送器策略有着相同的两种配置方式。配置文件的 default.strategy 节点,或短信消息类的 strategy 公开属性。
您也可以自定义发送器策略,只需实现 StrategyInterface 接口。该接口只有一个 apply 方法,接受两个参数。第一个参数接受您配置的可用发送器列表,第二个参数接受要收信的手机号码 MobileNumber 类。
您可以在短信消息类的 build 方法中使用 content 方法指定短信内容,使用 template 方法来指定在短信模板,使用 with 方法来指定短信参数,使用 signature 方法来指定短信签名。
您需要根据您选择的短信服务的不同来选择使用哪些方法。
publicfunctionbuild(SenderInterface$sender): void
{
return$this
->content('您的验证码是 123456')
->signature('【HyperfExt】');
}publicfunctionbuild(SenderInterface$sender): void
{
return$this
->template('SMS_001')
->signature('【HyperfExt】')
->with('code', '123456');
}某些短信业务提供商可能会要求传递发件人 ID(一般称为 sender id 或 from),您可以在对应发送器下的 config.from 节点内配置,并通过短信消息类的 from 方法使用。以 Twillo 为例:
// 在配置文件中指定'twillo' => [
'driver' => \HyperfExt\Sms\Drivers\TwilioDriver::class,
'config' => [
'account_sid' => '',
'token' => '',
'from' => [
'default' => '123', // 当未在短信消息类中指定时使用 `default` 的值'another1' => '456',
'another2' => '789',
],
],
],
// 在短信消息类中使用
public functionbuild(SenderInterface$sender): void
{
return$this
->from('another2');
}若要发送短信,使用 Sms 辅助类的 to 方法。to 方法接受手机号码和实现了 HasMobileNumber 接口的实例。一旦指定了收信人,就可以将短信消息类实例传递给 send 方法:
<?phpnamespaceApp\Controller;
useApp\Sms\VerificationCode;
useHyperf\HttpServer\Contract\RequestInterface;
useHyperf\HttpServer\Contract\ResponseInterface;
useHyperfExt\Sms\Sms;
class VerificationController
{
publicfunctionsend(RequestInterface$request): ResponseInterface
{
// 假定 $user 已经实现了 HasMobileNumber 接口$user = $request->user();
// 发送
Sms::to($user)->send(newVerificationCode());
}
}默认情况下,组件将使用你配置的发送器来发送短信。但是,你可以使用 sender 方法通过特定的发送器发送:
Sms::sender('twillo')
->to($request->user())
->send(newVerificationCode());由于发送短信消息可能大幅度增加应用的响应时间,许多开发者选择将短信消息加入队列放在后台发送。组件使用 hyperf/async-queue 简化了这一工作,安装时已经自动依赖,请根据文档进行配置。
若要将短信消息加入队列,可以在指定消息的接收者后,使用 Sms 辅助类的 queue 方法:
Sms::to($request->user())
->queue(newVerificationCode());此方法自动将作业推送到队列中以便消息在后台发送。使用此特性之前,需要配置队列。
如果要将短信推送到指定队列,可以通过设置
queue方法的第二个参数实现。
想要延迟发送队列化的短信消息,可以使用 later 方法。later 方法的第二个参数是标示消息延后多少秒后发送:
Sms::to($request->user())
->later(newVerificationCode(), 300); //延后 5 分钟发送如果要将短信推送到指定队列,可以通过设置
queue方法的第二个参数实现。
如果你希望你的短信类始终使用队列,您可以给短信消息类实现 HyperfExt\Contract\ShouldQueue 接口,现在即使你调用了 send 方法,短信依旧使用队列的方式发送。另外,如果需要将短信推送到指定队列,可以设置在短信消息类中设置 queue 属性。
useHyperfExt\Contract\ShouldQueue;
useHyperfExt\Sms\Smsable;
class VerificationCode extends Smsable implements ShouldQueue
{
/** * 列队名称。 * * @var string */public$queue = 'default';
}当你正在开发一个短信的应用程序时,您可能不想实际地向真实手机号码发送消息。组件提供了在本地开发过程中「禁用」实际发送短信的方法。
log 发送器驱动不发送短信,而是将所有短信消息写入日志文件用来校验。有关为每个环境配置应用程序的更多信息,请参阅配置文档。
在发送短信消息的时候,组件会触发两个事件。SmsMessageSending 事件在发送消息前触发,SmsMessageSent 事件在消息发送完成后触发。记住,这些事件都是在短信被发送时触发,而不是在队列化的时候。
为了有限的减少发送短信到无效的手机号码的情况,组件提供了两个方便使用的验证规则来手机号码的有效性。
需要安装配置
hyperf/validation组件。需要在验证消息的多语言文件中自行添加mobile_number和mobile_number_format两条翻译。这些验证器验证的有效性是指验证手机号码规则的有效,而非验证其真实性。
mobile_number 验证规则用来验证手机号码字段值是否有效,可选验证号码所属国家或地区是否在 regions 列表中。regions 为 ISO 3166-1 两位字母代码(下称「地区代码」)的地区代码列表。
当 regions 列表为空且配置文件中默认地区代码为 null 时,要验证的号码必须含有 ITU-T E.164 建议书规定的国家代码(下称「国码」),否则将视为无效号码。
当 regions 列表为空且配置文件中默认地区代码有值时,无论要验证的号码是否含有国码,都验证此号码是否属于默认地区,适合业务仅面向单一地区的场景。
当 regions 列表仅有一个地区代码时,无论要验证的号码是否含有国码、配置文件中默认地区代码是否有值,都验证此号码是否属于该地区。
当 regions 列表地区代码数量大于一个时,要验证的号码都必须含有国码,否则将视为无效号码。
注意,该验证规则接受任意电话号码格式。如果您需要同时验证地区和格式,请额外使用
mobile_number_format规则。如果仅验证号码有效性和格式,可以只用mobile_number_format规则。
'phone' => mobile_number'
'phone' => mobile_number:cn,hk,mo,tw'
mobile_number_format 验证规则用来验证手机号码字段值是否有效,且号码格式是否符合 format 格式。
验证号码格式是否符合 ITU-T E.164 建议书规定的格式。例如,+8618812345678。
验证号码格式是否符合国际拨号格式。例如,+86 188 1234 5678。
验证号码格式是否符合受话地号码格式,不能含有国际冠码和国码。例如,188 1234 5678。配置文件中默认地区代码为 null 时,必须提供 region 值。
验证号码格式是否符合 RFC3966。例如,tel:+86-188-1234-5678。
验证号码格式是否都是数字。例如,8618812345678 或 18812345678。
验证号码格式是否匹配此正则表达式。
除
e164、digits和自定义正则表达式外的验证格式均为 ITU-T E.123 建议书规定的格式。
'phone' => mobile_number_format:e164'
- 测试用例