从零开始系列-Laravel编写api服务接口:9.集成短信包

Laravel框架
408
0
0
2022-04-12

简介

laravel 短信包有几个比较优秀的如

参考:博客:通过 Laravel 消息通知使用 EasySms 短信服务,让你的代码更简洁

包:https://github.com/overtrue/easy-sms

下面介绍我们现在在用的包 laravel-sms 同样也非常强大

文档地址 https://github.com/toplan/laravel-sms

根据文档,下面是简单用法:

1. 安装

见 github 官方文档。

大部分按照官方文档即可。下面是一些注意事项官方文档也有,不过容易忽略。

测试发短信的时候官方会提供

通过以下方式可以查看验证码的发送情况

官方路由:

http[s]://your-domain/laravel-sms/info

or 自定义路由

if ('local' === config('app.env')) {
  Route::any('sms', '\\Toplan\\Sms\\SmsController@getInfo');
}

注意:如果是 api 应用 (无 session) 需要在上述地址后面加上?access_token=xxxx

2. 发送一般短信(验证码)

public function verify_code_test_template(Request $request)
{
  //$mobile = "15012422751";
  $mobile = $request->mobile;
  $sms = new \Toplan\Sms\SmsManager($mobile, ['mobile' => $mobile, 'template' => 'login']);
  $res = $sms->validateSendable();
  if (!$res['success']) {
    return $this->response->array($res)->setStatusCode(422);
  }

  $res = $sms->validateFields();
  if (!$res['success']) {
    return $this->response->array($res)->setStatusCode(422);
  }

  $res = $sms->requestVerifySms();
  Sms::queue(true);

  return $this->response->array($res);
}

3. 发送模板短信(自定义短信)

 /**
 * 测试发送模板消息
 */
public function sendTemplate()
{
  $sms = new \Toplan\Sms\SmsManager('token', ['mobile' => '15012422751', 'type' => '1', 'template' => 'nopass', 'number' => '15222', 'application' => '互联网医院-医生']);
  $result = $sms->validateSendable();
  if (!$result['success']) {
    return $this->response->array($result);
  }
  $result = $sms->validateFields();
  if (!$result['success']) {
    return $this->response->array($result);
  }
  $result = $sms->requestVerifySms();

  return $this->response->array($result);

}

4. 验证短信

// 验证短信

public function verification(Request $request)
{
  //验证数据
//    $key = config('laravel-sms.storage.prefix', 'laravel_sms');
//    $state = \Cache::get('laravel_sms._state');
//    $state2 = \Cache::get('laravel_sms.'.$request->mobile.'._state');
//    dump($state);
//    dump($state2);
  $validator = Validator::make($request->all(), [
    'mobile' => 'required|is_mobile|confirm_mobile_not_change|confirm_rule:mobile_required',
    'verifyCode' => 'required|verify_code',
  ], [
    'mobile.required' => '手机号不能为空1',
    'mobile.confirm_mobile_not_change' => '手机号已变更,请重新发送验证码',
    'mobile.confirm_rule' => '手机号不能为空2',
    'verifyCode.required' => '验证码不能为空',
    'verifyCode.verify_code' => '验证码错误',
  ]);
  if ($validator->fails()) {
    //验证失败后建议清空存储的发送状态,防止用户重复试错
    SmsManager::forgetState();
    return $this->response->errorUnauthorized('验证失败');
  }
  return $this->response->array(['message' => '验证成功']);
}

5. 配置文件

.env

# 阿里·云通讯 < 汇医培 下子账号 sms >
ALIYUN_MNS_ACCESS_KEY_ID=#####
ALIYUN_MNS_ACCESS_KEY_SECRET=*****
ALIYUN_MNS_TOPIC=sms.topic-cn-shenzhen
ALIYUN_MNS_SIGN=****
ALIYUN_MNS_REGION_ID=cn-shenzhen
ALIYUN_MNS_TEMPLATE=SMS_190788952
SMS_DRIVER=Aliyun
laravel-sms.php

<?php

return [
  /*
  |--------------------------------------------------------------------------
  | 内置路由
  |--------------------------------------------------------------------------
  |
  | 如果是 web 应用建议 middleware 为 ['web', ...]
  | 如果是 api 应用建议 middleware 为 ['api', ...]
  |
   */
  'route'   => [
    'enable'   => true,
    'prefix'   => 'laravel-sms',
    'middleware' => ['api'],
  ],

  /*
  |--------------------------------------------------------------------------
  | 请求间隔
  |--------------------------------------------------------------------------
  |
  | 单位:秒
  |
   */
  'interval'  => 60,

  /*
  |--------------------------------------------------------------------------
  | 数据验证管理
  |--------------------------------------------------------------------------
  |
  | 设置从客户端传来的需要验证的数据字段(`field`)
  |
  | - isMobile  是否为手机号字段
  | - enable   是否开启验证
  | - default   默认静态验证规则
  | - staticRules 静态验证规则
  |
   */
  'validation' => [
    'mobile' => [
      'isMobile'  => true,
      'enable'   => true,
      'default'   => 'mobile_required',
      'staticRules' => [
        'mobile_required'   => 'required|is_mobile',
        'check_mobile_unique' => 'required|is_mobile|unique:users,mobile',
        'check_mobile_exists' => 'required|is_mobile|exists:users',
        'doctor_register'   => 'required|is_mobile|unique:doctors,mobile',
        'hospital_register'  => 'required|is_mobile|unique:organs,tel',
      ],
    ],
  ],

  /*
  |--------------------------------------------------------------------------
  | 验证码管理
  |--------------------------------------------------------------------------
  |
  | - length    验证码长度
  | - validMinutes 验证码有效时间长度,单位为分钟
  | - repeatIfValid 如果原验证码还有效,是否重复使用原验证码
  | - maxAttempts  验证码最大尝试验证次数,超过该数值验证码自动失效,0或负数则不启用
  |
   */
  'code'    => [
    'length'    => 6,
    'validMinutes' => 5,
    'repeatIfValid' => false,
    'maxAttempts'  => 0,
  ],

  /*
  |--------------------------------------------------------------------------
  | 验证码短信通用内容
  |--------------------------------------------------------------------------
  |
  | 如需缓存配置,则需使用 `Toplan\Sms\SmsManger::closure($closure)` 方法进行配置
  |
   */
  'content'  => function ($code, $minutes, $input) {
    return '【signature】您的验证码是' . $code . ',有效期为' . $minutes . '分钟,请尽快验证。';
  },

  /*
  |--------------------------------------------------------------------------
  | 验证码短信模版
  |--------------------------------------------------------------------------
  |
  | 每项数据的值可以为以下三种之一:
  |
  | - 字符串/数字
  |  如: 'YunTongXun' => '短信模版id'
  |
  | - 数组
  |  如: 'Alidayu' => ['短信模版id', '语音模版id'],
  |
  | - 匿名函数 $input 请求参数 $type string verify_sms短信验证码 voice_verify语音验证码
  |  如: 'YunTongXun' => function ($input, $type) {
  |      return $input['isRegister'] ? 'registerTempId' : 'commonId';
  |    }
  |
  | 如需缓存配置,则需使用 `Toplan\Sms\SmsManger::closure($closure)` 方法对匿名函数进行配置
  |
   */
  'templates' => [
    // SMS_xxxxxxxxx 提交验证码,参数: code -> 验证码、number -> 4位手机尾号
    'Aliyun' => function ($input, $type) {
      if (isset($input['template'])) {
        switch ($input['template']) {
          // 根据短信模板业务逻辑来
          case 'case_submit':
          case 'rx_submit':
            return 'SMS_xxxxxxxx';
            break;
          case "pass": // 通过
            return 'SMS_xxxxxxxxx';
          case "nopass": //不通过
            return 'SMS_xxxxxxxxx';
          case "login": //登录
            return 'SMS_xxxxxxxxx';
          case "updateAppointmentTime":
            return 'SMS_xxxxxxxxx';
          default:
            return env('ALIYUN_MNS_TEMPLATE', 'SMS_xxxxxxxxx');
        }
      }
      return env('ALIYUN_MNS_TEMPLATE', 'SMS_xxxxxxxxx');
    },
  ],

  /*
  |--------------------------------------------------------------------------
  | 模版数据管理
  |--------------------------------------------------------------------------
  |
  | 每项数据的值可以为以下两种之一:
  |
  | - 基本数据类型
  |  如: 'minutes' => 5
  |
  | - 匿名函数(如果该函数不返回任何值,即表示不使用该项数据)
  |  如: 'serialNumber' => function ($code, $minutes, $input, $type) {
  |      return $input['serialNumber'];
  |    }
  |  如: 'hello' => function ($code, $minutes, $input, $type) {
  |      //不返回任何值,那么hello将会从模版数据中移除 :)
  |    }
  |
  | 如需缓存配置,则需使用 `Toplan\Sms\SmsManger::closure($closure)` 方法对匿名函数进行配置
  |
   */
  'data'    => [
    'code'    => function ($code) {
      return $code;
    },
    'minutes'   => function ($code, $minutes) {
      return $minutes;
    },
    'number'   => function ($code, $minutes, $input, $type) {
      if (isset($input['template'])) {
        switch ($input['template']) {
          // 提交处方或提交病例验证码
          case 'case_submit':
          case 'rx_submit':
          case 'pass':
            return $input['number'];
            break;
        }
      }
    },
    'application' => function ($code, $minutes, $input, $type) {
      if (isset($input['template']) && in_array($input['template'], ['pass', 'nopass'])) {
        return $input['application'];
      }
    },
    'hospital' => function ($code, $minutes, $input, $type) {
      if (isset($input['template']) && in_array($input['template'], ['updateAppointmentTime'])) {
        return $input['hospital'];
      }
    },
    'checks' => function ($code, $minutes, $input, $type) {
      if (isset($input['template']) && in_array($input['template'], ['updateAppointmentTime'])) {
        return $input['checks'];
      }
    },
    'check_time' => function ($code, $minutes, $input, $type) {
      if (isset($input['template']) && in_array($input['template'], ['updateAppointmentTime'])) {
        return $input['check_time'];
      }
    },
  ],

  /*
  |--------------------------------------------------------------------------
  | 存储系统配置
  |--------------------------------------------------------------------------
  |
  | driver:
  | 存储方式,是一个实现了'Toplan\Sms\Storage'接口的类的类名,
  | 内置可选的值有'Toplan\Sms\SessionStorage'和'Toplan\Sms\CacheStorage',
  | 如果不填写driver,那么系统会自动根据内置路由的属性(route)中middleware的配置值选择存储器driver:
  | - 如果中间件含有'web',会选择使用'Toplan\Sms\SessionStorage'
  | - 如果中间件含有'api',会选择使用'Toplan\Sms\CacheStorage'
  |
  | prefix:
  | 存储key的prefix
  |
  | 内置driver的个性化配置:
  | - 在laravel项目的'config/session.php'文件中可以对'Toplan\Sms\SessionStorage'进行更多个性化设置
  | - 在laravel项目的'config/cache.php'文件中可以对'Toplan\Sms\CacheStorage'进行更多个性化设置
  |
   */
  'storage'  => [
    'driver' => '',
    'prefix' => 'laravel_sms',
  ],

  /*
  |--------------------------------------------------------------------------
  | 是否数据库记录发送日志
  |--------------------------------------------------------------------------
  |
  | 若需开启此功能,需要先生成一个内置的'laravel_sms'表
  | 运行'php artisan migrate'命令可以自动生成
  |
   */
  'dbLogs'   => true,

  /*
  |--------------------------------------------------------------------------
  | 队列任务
  |--------------------------------------------------------------------------
  |
   */
  'queueJob'  => 'Toplan\Sms\SendReminderSms',

  /*
  |--------------------------------------------------------------------------
  | 验证码模块提示信息
  |--------------------------------------------------------------------------
  |
   */
  'notifies'  => [
    // 频繁请求无效的提示
    'request_invalid'  => '请求无效,请在%s秒后重试',

    // 验证码短信发送失败的提示
    'sms_sent_failure'  => '短信验证码发送失败,请稍后重试',

    // 语音验证码发送发送成功的提示
    'voice_sent_failure' => '语音验证码请求失败,请稍后重试',

    // 验证码短信发送成功的提示
    'sms_sent_success'  => '短信验证码发送成功,请注意查收',

    // 语音验证码发送发送成功的提示
    'voice_sent_success' => '语音验证码发送成功,请注意接听',
  ],
];