Yahoo 4 лет назад
Родитель
Сommit
add5914a10
2 измененных файлов с 108 добавлено и 15 удалено
  1. 49 0
      app/api/controller/Captcha.php
  2. 59 15
      app/api/service/passport/SmsCaptcha.php

+ 49 - 0
app/api/controller/Captcha.php

@@ -0,0 +1,49 @@
+<?php
+// +----------------------------------------------------------------------
+// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2017~2021 https://www.yiovo.com All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
+// +----------------------------------------------------------------------
+// | Author: 萤火科技 <admin@yiovo.com>
+// +----------------------------------------------------------------------
+declare (strict_types=1);
+
+namespace app\api\controller;
+
+use think\response\Json;
+use app\api\service\passport\{Captcha as CaptchaService, SmsCaptcha as SmsCaptchaService};
+use cores\exception\BaseException;
+
+/**
+ * 验证码管理
+ * Class Cart
+ * @package app\api\controller
+ */
+class Captcha extends Controller
+{
+    /**
+     * 图形验证码
+     * @return Json
+     */
+    public function image(): Json
+    {
+        $CaptchaService = new CaptchaService;
+        return $this->renderSuccess($CaptchaService->create());
+    }
+
+    /**
+     * 发送短信验证码
+     * @return Json
+     * @throws BaseException
+     */
+    public function sendSmsCaptcha(): Json
+    {
+        $SmsCaptchaService = new SmsCaptchaService;
+        if ($SmsCaptchaService->handle($this->postForm())) {
+            return $this->renderSuccess('发送成功,请注意查收');
+        }
+        return $this->renderError($SmsCaptchaService->getError() ?: '短信发送失败');
+    }
+}

+ 59 - 15
app/api/service/passport/SmsCaptcha.php

@@ -8,14 +8,16 @@
 // +----------------------------------------------------------------------
 // | Author: 萤火科技 <admin@yiovo.com>
 // +----------------------------------------------------------------------
-declare (strict_types = 1);
+declare (strict_types=1);
 
 namespace app\api\service\passport;
 
+use yiovo\cache\facade\Cache;
+use yiovo\captcha\facade\CaptchaApi;
 use app\api\validate\passport\SmsCaptcha as ValidateSmsCaptcha;
 use app\common\service\BaseService;
 use app\common\service\Message as MessageService;
-use yiovo\captcha\facade\CaptchaApi;
+use cores\exception\BaseException;
 
 /**
  * 服务类:发送短信验证码
@@ -24,47 +26,89 @@ use yiovo\captcha\facade\CaptchaApi;
  */
 class SmsCaptcha extends BaseService
 {
+    // 最大发送次数,默认10次
+    protected $sendTimes = 10;
+
+    // 发送限制间隔时间,默认24小时
+    protected $safeTime = 86400;
+
     /**
      * 发送短信验证码
      * @param array $data
      * @return bool
+     * @throws BaseException
      */
-    public function sendSmsCaptcha(array $data): bool
+    public function handle(array $data): bool
     {
         // 数据验证
-        if (!$this->validate($data)) return false;
+        $this->validate($data);
+        // 执行发送短信
+        if (!$this->sendCaptcha($data['mobile'])) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * 执行发送短信
+     * @param string $mobile
+     * @return bool
+     */
+    private function sendCaptcha(string $mobile): bool
+    {
+        // 缓存发送记录并判断次数
+        if (!$this->record($mobile)) {
+            return false;
+        }
         // 生成验证码
-        $smsCaptcha = CaptchaApi::createSMS($data['mobile']);
+        $smsCaptcha = CaptchaApi::createSMS($mobile);
         // 发送短信
-        $status = MessageService::send('passport.captcha', [
+        MessageService::send('passport.captcha', [
             'code' => $smsCaptcha['code'],
             'mobile' => $smsCaptcha['key']
         ], $this->storeId);
-        if (!$status) {
-            $this->error = '短信发送失败';
+        return true;
+    }
+
+    /**
+     * 记录短信验证码发送记录并判断是否超出发送限制
+     * @param string $mobile
+     * @return bool
+     */
+    private function record(string $mobile): bool
+    {
+        // 获取发送记录缓存
+        $record = Cache::get("sendCaptchaSMS.$mobile");
+        // 写入缓存:记录剩余发送次数
+        if (empty($record)) {
+            Cache::set("sendCaptchaSMS.$mobile", ['times' => $this->sendTimes - 1], $this->safeTime);
+            return true;
+        }
+        // 判断发送次数是否合法
+        if ($record['times'] <= 0) {
+            $this->error = '很抱歉,已超出今日最大发送次数限制';
             return false;
         }
+        // 发送次数递减
+        Cache::update("sendCaptchaSMS.$mobile", ['times' => $record['times'] - 1]);
         return true;
     }
 
     /**
      * 数据验证
      * @param array $data
-     * @return bool
+     * @throws BaseException
      */
-    private function validate(array $data): bool
+    private function validate(array $data)
     {
         // 数据验证
         $validate = new ValidateSmsCaptcha;
         if (!$validate->check($data)) {
-            $this->error = $validate->getError();
-            return false;
+            throwError($validate->getError());
         }
         // 验证图形验证码
         if (!CaptchaApi::check($data['captchaCode'], $data['captchaKey'])) {
-            $this->error = '很抱歉,图形验证码不正确';
-            return false;
+            throwError('很抱歉,图形验证码不正确');
         }
-        return true;
     }
 }