// +---------------------------------------------------------------------- namespace App\Services; use AlibabaCloud\Tea\Exception\TeaUnableRetryError; use AlibabaCloud\SDK\Dysmsapi\V20170525\Dysmsapi; use Darabonba\OpenApi\Models\Config; use AlibabaCloud\SDK\Dysmsapi\V20170525\Models\SendSmsRequest; use AlibabaCloud\Tea\Utils\Utils\RuntimeOptions; /** * 阿里云短信管理-服务类 * @author laravel开发员 * @since 2020/11/11 * Class SmsService * @package App\Services */ class SmsService extends BaseService { // 静态对象 protected static $instance = null; /** * 静态入口 * @return SmsService|static|null */ public static function make(){ if(!self::$instance){ self::$instance = new static(); } return self::$instance; } /** * @param $accessKeyId * @param $accessKeySecret * @return mixed */ public function createClient($accessKeyId, $accessKeySecret, $endpoint){ $config = new Config([ // 必填,您的 AccessKey ID "accessKeyId" => $accessKeyId, // 必填,您的 AccessKey Secret "accessKeySecret" => $accessKeySecret ]); // 访问的域名 $config->endpoint = $endpoint; return new Dysmsapi($config); } /** * 发送短信验证码 * @param $mobile * @param string $type * @return bool */ public function send($mobile, $type='login') { $cacheKey = "caches:sms:{$mobile}:{$type}"; if(RedisService::get($cacheKey.'_lock')){ $this->error = '2011'; return false; } $config = ConfigService::make()->getConfigOptionByGroup(2); $accessKey = isset($config['ali_sms_access_key'])? trim($config['ali_sms_access_key']) : ''; $accessSecret = isset($config['ali_sms_access_secret'])? trim($config['ali_sms_access_secret']) : ''; $smsTemplateCode = isset($config['ali_sms_template_code'])? trim($config['ali_sms_template_code']) : ''; $smsSignName = isset($config['ali_sms_sign_name'])? trim($config['ali_sms_sign_name']) : ''; $endpoint = isset($config['sms_endpoint'])? trim($config['sms_endpoint']) : ''; if(empty($accessKey) || empty($accessSecret) || empty($smsTemplateCode) || empty($smsSignName) || empty($endpoint)){ $this->error = 2012; return false; } // 发送逻辑 $code = rand(1000,9999); $client = $this->createClient($accessKey, $accessSecret, $endpoint); $request = new SendSmsRequest(); $request->phoneNumbers = $mobile; $request->signName = $smsSignName; $request->templateCode = $smsTemplateCode; $request->templateParam = json_encode(['code'=> $code], 256); $runtime = new RuntimeOptions(); $runtime->maxIdleConns = 5; $runtime->connectTimeout = 10000; $runtime->readTimeout = 10000; try { // 复制代码运行请自行打印 API 的返回值 $response = $client->sendSms($request, $runtime); $resultCode = $response->body->code; if($resultCode == 'OK'){ $this->error = 2005; RedisService::set($cacheKey,['code'=> $code,'mobile'=>$mobile,'bizId'=>$response->body->bizId,'date'=> date('Y-m-d H:i:s')], 600); return true; }else{ $this->error = '发送失败:'.$response->body->message; RedisService::set($cacheKey.'_fail', ['mobile'=> $mobile,'config'=>$config,'error'=>$this->error,'date'=> date('Y-m-d H:i:s')], 6 * 3600); return false; } } catch (TeaUnableRetryError $e){ //$date = date('Y-m-d H:i:s'); //logger()->error("【{$date} SMS短信验证码】发送失败:".$e->getMessage()); RedisService::set($cacheKey.'_error', ['mobile'=> $mobile,'config'=>$config,'error'=>$e->getMessage()], 6 * 3600); } $this->error = 2006; return false; } /** * 短信验证码验证 * @param string $mobile 手机号 * @param string $code 当前验证码 * @param string $type 验证码场景类型,login-登录,reg-注册 * @return bool */ public function check($mobile, $code, $type='login') { // 测试 if(env('SMS_DEBUG') && $code == env('SMS_CODE','1100')){ return true; } $cacheKey = "caches:sms:{$mobile}:{$type}"; $data = RedisService::get($cacheKey); $smsCode = isset($data['code'])? $data['code'] : ''; if(empty($data) || empty($smsCode)){ $this->error = '2012'; return false; } if($smsCode != $code){ $this->error = '2013'; return false; } return true; } }