Skip to content

短信发送

数据结构

后台短信发送功能提供了两个表,一个短信模板表,一个存储验证码的表,结构如下

短信模板表

sql
CREATE TABLE `system_sms_template` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `identify` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT '模版唯一标识',
  `channel` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'aliyun' COMMENT 'aliyun:阿里云短信,qcloud:腾讯短信',
  `template_id` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '模版ID',
  `content` varchar(2000) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '模版内容',
  `variables` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '模版变量',
  `creator_id` int unsigned NOT NULL DEFAULT '0' COMMENT '创建人ID',
  `created_at` int unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
  `updated_at` int unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
  `deleted_at` int unsigned NOT NULL DEFAULT '0' COMMENT '软删除',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='短信模版';

短信验证码表

sql
CREATE TABLE `system_sms_code` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `mobile` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT '手机号',
  `code` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT '短信验证码',
  `behavior` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT '短信行为表: 1 login 2 register',
  `channel` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'aliyun' COMMENT 'aliyun:阿里云短信,qcloud:腾讯短信',
  `status` int NOT NULL DEFAULT '1' COMMENT '状态 1 未使用 2 已使用',
  `expired_at` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '0' COMMENT '过期时间',
  `created_at` int unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
  `updated_at` int unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='短信验证码记录';

配置

到后台系统管理->短信配置里设置平台,目前支持阿里云腾讯云两个平台,如下图配置对应的平台配置 CatchAdmin 专业版短信配置

然后配置对应平台的短信模板

WARNING

注意这里需要你先到平台配置对应的模板,需要等模板审核通过后,录入到后台

CatchAdmin 专业版短信配置模板CatchAdmin 专业版短信配置模板

  • 模板标识 字符串,这里的示例是 login
  • 模板ID 平台获取的模板 ID

使用

WARNING

确保已经配置好了模板和平台

使用起来很简单,例如项目是发送登录短信码

php
$smsCode = new SmsCode();
$smsCode->login($request->get('mobile'));

具体细节看如下代码

php
class SmsCode
{
    protected Sms $channel;

    public const LOGIN_BEHAVIOR = 'login';

    public const REGISTER_BEHAVIOR = 'register';

    public function __construct()
    {
        $this->channel = Factory::make();
    }

    /**
     * 发送登录验证码
     * @throws \Throwable
     */
    public function login(string $mobile): bool
    {
        try {
            // 使用存储短信验证码的模型
            $smsCodeModel = new SystemSmsCode;

            // 短信对应的手机号是否有验证码记录,如果验证码没有使用则返回错误
            if ($smsCodeModel->hasCode($mobile, self::LOGIN_BEHAVIOR)) {
                throw new FailedException('验证码未使用或者未过期');
            }

            // 生成新的验证码
            $code = $this->getCode();
            // 发送验证码
            // self::LOGIN_BEHAVIOR 就是模板标识,是 login,用来查找模板,模板变量使用{}包裹,形如{code}
            // [$code] 这个就是变量数组,里面的值会被系统依次解析,注意需要和模板变量一一对应
            $this->channel->send(self::LOGIN_BEHAVIOR, $mobile, [$code]);
            // 然后保存发送的手机号验证码
            $smsCodeModel->store($mobile, self::LOGIN_BEHAVIOR, $code);

            return true;
        } catch (NoGatewayAvailableException $exception) {
            throw new FailedException($exception->getLastException()->getMessage());
        } catch (\Throwable|\Exception $e) {
            throw new FailedException($e->getMessage());
        }
    }

    /**
     * @return void
     */
    public function register(string $mobile)
    {
        $smsCodeModel = new SystemSmsCode;

        $smsCodeModel->hasCode($mobile, 'register');
    }

    protected function getCode(): int
    {
        return rand(100000, 999999);
    }
}