200, 'message' => '', 'data' => []]; $lastDateKey = self::$cachePrefix . $type . ':' . $mobile . ':last_date'; $lastDate = $this->getCacheRepo()->get($lastDateKey); $lastDateObj = Carbon::parse($lastDate); $nowDateObj = Carbon::now(); //比较发送频率 if (!empty($lastDate) && abs($nowDateObj->diffInSeconds($lastDateObj)) <= 30) { $result['code'] = '601011'; $result['message'] = '请间隔30秒发送短信'; return $result; } $sentLogKey = self::$cachePrefix . $type . ':'. $mobile. ':log'; //去掉1小时前的发送记录 $sendLogs = $this->getCacheRepo()->get($sentLogKey, []); if (!empty($sendLogs)) { foreach ($sendLogs as $k => $logDate) { if (abs($nowDateObj->diffInMinutes(Carbon::parse($logDate))) >= 60) { // 剔除超过1小时的记录. unset($sendLogs[$k]); } } } // 1小时3次限制 if (count($sendLogs) >= 3) { $result['code'] = '601012'; $result['message'] = '一小时之内验证码的发送次数不得超过3次'; return $result; } if (!self::isChinaMobile($mobile)) { $result['code'] = '600012'; $result['message'] = '仅限发送中国大陆手机号'; return $result; } $code = $this->createCode($mobile, $type,$code); // 记录会话时间 $this->getCacheRepo()->set($lastDateKey, Carbon::now()->toDateTimeString(), 2 * 60 * 60); //发送短信 + 1 if ($result['code'] == 200) { $arrConfig = $this->getConfigRepo()->gets(['tg_api_token', 'tg_msg_server'], 'sys', []); $token = data_get($arrConfig, 'tg_api_token', ''); $sendLogs[] = Carbon::now()->toDateTimeString(); $this->getCacheRepo()->set($sentLogKey, $sendLogs, 24 * 60 * 60); $uri = '/api/sms/send/verify'; $options = [ 'query' => [ 'AUTH-TOKEN' => $token, ], 'json' => [ 'mobile' => $mobile, 'code' => $code, ], ]; $ret = $this->getHttpClient()->post($uri, $options); $httpStatus = $ret->getStatusCode(); if ($httpStatus == 200) { $arrResp = json_decode($ret->getBody()->getContents(), true); $result['code'] = $arrResp['code']; $result['message'] = $arrResp['message']; $result['data'] = $arrResp['data']; } } return $result; } /** * 创建CODE * @param int|string $mobile 手机号 * @param string $type 类型 * @param number $code 短信验验证码 * @return mixed */ public function createCode($mobile, $type, $code) { $cacheKey = self::$cachePrefix . $type . ':' . $mobile; $this->getCacheRepo()->set($cacheKey, $code, self::$cacheTimeoutMinutes * 60); return $code; } /** * 获取Code * @param int|string $mobile 手机号 * @param string $type 类型 * @return mixed */ public function getCode($mobile, $type) { $cacheKey = self::$cachePrefix . $type . ':' . $mobile; return $this->getCacheRepo()->get($cacheKey, null); } /** * 检查Code * @param int|string $code 校验码 * @param int|string $mobile 手机号 * @param string $type 类型 * @return bool */ public function checkCode($code, $mobile, $type) { $cacheCode = $this->getCode($mobile, $type); if ($cacheCode) { $cacheCode = (string)$cacheCode; if ($cacheCode === (string)($code)) { // 认证了就马上删除. $this->deleteCode($mobile, $type); return true; } } return false; } /** * 检查Code但不删除code * @param int|string $code 校验码 * @param int|string $mobile 手机号 * @param string $type 类型 * @return bool */ public function checkCodeNotDelete($code, $mobile, $type) { $cache_code = $this->getCode($mobile, $type); if ($cache_code) { $cache_code = (string)$cache_code; if ($cache_code === (string)($code)) { return true; } } return false; } /** * 删除Code * @param int|string $mobile 手机号 * @param string $type 类型 */ public function deleteCode($mobile, $type) { $cacheKey = self::$cachePrefix . $type . ':' . $mobile; $this->getCacheRepo()->forget($cacheKey); } /** * 是否是中国手机号. * @param string $number * @return bool */ public function isChinaMobile($number) :bool { return boolval(preg_match(PatternConstant::CHINA_MOBILE, $number)); } /** * 获取缓存仓库. * @return mixed|CacheInterface */ private function getCacheRepo() { if (!$this->cacheRepo instanceof CacheInterface) { $this->cacheRepo = make(CacheInterface::class); } return $this->cacheRepo; } /** * @return \GuzzleHttp\Client|ClientFactory|null */ public function getHttpClient() { if (!$this->httpClient instanceof ClientFactory) { $arrConfig = $this->getConfigRepo()->gets(['tg_api_token', 'tg_msg_server'], 'sys', []); $token = data_get($arrConfig, 'tg_api_token', ''); $baseUrl = rtrim(data_get($arrConfig, 'tg_msg_server', ''), '/'); $options = array( 'base_uri' => $baseUrl, 'timeout' => 15, // 超时,单位秒. 'verify' => false, // 是否校验SSL证书. 'http_errors' => false, // 如果跟随http异常头部是否中断. 'debug' => false, // 是否启用调试模式. 'allow_redirects' => false, // 不跟随301/302跳转. 'headers' => [ 'AUTH-TOKEN' => $token, ], ); $this->httpClient = make(ClientFactory::class)->create($options); } return $this->httpClient; } /** * @return ConfigRepoistory|mixed */ private function getConfigRepo() { if (!$this->configRepo instanceof ConfigRepoistory) { $this->configRepo = make(ConfigRepoistory::class); } return $this->configRepo; } }