SmsService.php 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
  4. // +----------------------------------------------------------------------
  5. // | 版权所有 2017~2021 LARAVEL研发中心
  6. // +----------------------------------------------------------------------
  7. // | 官方网站: http://www.laravel.cn
  8. // +----------------------------------------------------------------------
  9. // | Author: laravel开发员 <laravel.qq.com>
  10. // +----------------------------------------------------------------------
  11. namespace App\Services;
  12. use AlibabaCloud\Tea\Exception\TeaUnableRetryError;
  13. use AlibabaCloud\SDK\Dysmsapi\V20170525\Dysmsapi;
  14. use Darabonba\OpenApi\Models\Config;
  15. use AlibabaCloud\SDK\Dysmsapi\V20170525\Models\SendSmsRequest;
  16. use AlibabaCloud\Tea\Utils\Utils\RuntimeOptions;
  17. /**
  18. * 阿里云短信管理-服务类
  19. * @author laravel开发员
  20. * @since 2020/11/11
  21. * Class SmsService
  22. * @package App\Services
  23. */
  24. class SmsService extends BaseService
  25. {
  26. // 静态对象
  27. protected static $instance = null;
  28. /**
  29. * 静态入口
  30. * @return SmsService|static|null
  31. */
  32. public static function make(){
  33. if(!self::$instance){
  34. self::$instance = new static();
  35. }
  36. return self::$instance;
  37. }
  38. /**
  39. * @param $accessKeyId
  40. * @param $accessKeySecret
  41. * @return mixed
  42. */
  43. public function createClient($accessKeyId, $accessKeySecret, $endpoint){
  44. $config = new Config([
  45. // 必填,您的 AccessKey ID
  46. "accessKeyId" => $accessKeyId,
  47. // 必填,您的 AccessKey Secret
  48. "accessKeySecret" => $accessKeySecret
  49. ]);
  50. // 访问的域名
  51. $config->endpoint = $endpoint;
  52. return new Dysmsapi($config);
  53. }
  54. /**
  55. * 发送短信验证码
  56. * @param $mobile
  57. * @param string $type
  58. * @return bool
  59. */
  60. public function send($mobile, $type='login')
  61. {
  62. $cacheKey = "caches:sms:{$mobile}:{$type}";
  63. if(RedisService::get($cacheKey.'_lock')){
  64. $this->error = '2011';
  65. return false;
  66. }
  67. $config = ConfigService::make()->getConfigOptionByGroup(2);
  68. $accessKey = isset($config['ali_sms_access_key'])? trim($config['ali_sms_access_key']) : '';
  69. $accessSecret = isset($config['ali_sms_access_secret'])? trim($config['ali_sms_access_secret']) : '';
  70. $smsTemplateCode = isset($config['ali_sms_template_code'])? trim($config['ali_sms_template_code']) : '';
  71. $smsSignName = isset($config['ali_sms_sign_name'])? trim($config['ali_sms_sign_name']) : '';
  72. $endpoint = isset($config['sms_endpoint'])? trim($config['sms_endpoint']) : '';
  73. if(empty($accessKey) || empty($accessSecret) || empty($smsTemplateCode) || empty($smsSignName) || empty($endpoint)){
  74. $this->error = 2012;
  75. return false;
  76. }
  77. // 发送逻辑
  78. $code = rand(1000,9999);
  79. $client = $this->createClient($accessKey, $accessSecret, $endpoint);
  80. $request = new SendSmsRequest();
  81. $request->phoneNumbers = $mobile;
  82. $request->signName = $smsSignName;
  83. $request->templateCode = $smsTemplateCode;
  84. $request->templateParam = json_encode(['code'=> $code], 256);
  85. $runtime = new RuntimeOptions();
  86. $runtime->maxIdleConns = 5;
  87. $runtime->connectTimeout = 10000;
  88. $runtime->readTimeout = 10000;
  89. try {
  90. // 复制代码运行请自行打印 API 的返回值
  91. $response = $client->sendSms($request, $runtime);
  92. $resultCode = $response->body->code;
  93. if($resultCode == 'OK'){
  94. $this->error = 2005;
  95. RedisService::set($cacheKey,['code'=> $code,'mobile'=>$mobile,'bizId'=>$response->body->bizId,'date'=> date('Y-m-d H:i:s')], 600);
  96. return true;
  97. }else{
  98. $this->error = '发送失败:'.$response->body->message;
  99. RedisService::set($cacheKey.'_fail', ['mobile'=> $mobile,'config'=>$config,'error'=>$this->error,'date'=> date('Y-m-d H:i:s')], 6 * 3600);
  100. return false;
  101. }
  102. } catch (TeaUnableRetryError $e){
  103. //$date = date('Y-m-d H:i:s');
  104. //logger()->error("【{$date} SMS短信验证码】发送失败:".$e->getMessage());
  105. RedisService::set($cacheKey.'_error', ['mobile'=> $mobile,'config'=>$config,'error'=>$e->getMessage()], 6 * 3600);
  106. }
  107. $this->error = 2006;
  108. return false;
  109. }
  110. /**
  111. * 短信验证码验证
  112. * @param string $mobile 手机号
  113. * @param string $code 当前验证码
  114. * @param string $type 验证码场景类型,login-登录,reg-注册
  115. * @return bool
  116. */
  117. public function check($mobile, $code, $type='login')
  118. {
  119. // 测试
  120. if(env('SMS_DEBUG') && $code == env('SMS_CODE','1100')){
  121. return true;
  122. }
  123. $cacheKey = "caches:sms:{$mobile}:{$type}";
  124. $data = RedisService::get($cacheKey);
  125. $smsCode = isset($data['code'])? $data['code'] : '';
  126. if(empty($data) || empty($smsCode)){
  127. $this->error = '2012';
  128. return false;
  129. }
  130. if($smsCode != $code){
  131. $this->error = '2013';
  132. return false;
  133. }
  134. return true;
  135. }
  136. }