Преглед на файлове

邮箱注册和登录,需要加入邮箱验证码发送

zhangdehua преди 1 година
родител
ревизия
6172806ad3
променени са 4 файла, в които са добавени 284 реда и са изтрити 1 реда
  1. 17 1
      app/api/controller/Captcha.php
  2. 6 0
      app/api/service/passport/Login.php
  3. 215 0
      app/api/service/passport/MailCaptcha.php
  4. 46 0
      app/api/validate/passport/EmailCaptcha.php

+ 17 - 1
app/api/controller/Captcha.php

@@ -13,7 +13,9 @@ declare (strict_types=1);
 namespace app\api\controller;
 
 use think\response\Json;
-use app\api\service\passport\{Captcha as CaptchaService, SmsCaptcha as SmsCaptchaService};
+use app\api\service\passport\{Captcha as CaptchaService,
+    MailCaptcha as MailCaptchaService,
+    SmsCaptcha as SmsCaptchaService};
 use cores\exception\BaseException;
 
 /**
@@ -46,4 +48,18 @@ class Captcha extends Controller
         }
         return $this->renderError($SmsCaptchaService->getError() ?: '短信发送失败');
     }
+
+    /**
+     * 发送邮箱验证码
+     * @return Json
+     * @throws BaseException
+     */
+    public function sendEmailCaptcha(): Json
+    {
+        $MailCaptchaService = new MailCaptchaService;
+        if ($MailCaptchaService->handle($this->postForm())) {
+            return $this->renderSuccess('Sent Successful!Please check your new mails.');
+        }
+        return $this->renderError($MailCaptchaService->getError() ?: '短信发送失败');
+    }
 }

+ 6 - 0
app/api/service/passport/Login.php

@@ -287,6 +287,12 @@ class Login extends BaseService
 //        if (!CaptchaApi::checkSms($data['smsCode'], $data['mobile'])) {
 //            throwError('短信验证码不正确');
 //        }
+
+        //todo 电子烟校验邮箱mobile的验证码是否匹配
+        $mailCaptcha = new MailCaptcha();
+        $mailCaptcha->checkCaptcha($data['smsCode'], $data['mobile']);
+
+
     }
 
     /**

+ 215 - 0
app/api/service/passport/MailCaptcha.php

@@ -0,0 +1,215 @@
+<?php
+// +----------------------------------------------------------------------
+// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2017~2024 https://www.yiovo.com All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
+// +----------------------------------------------------------------------
+// | Author: 萤火科技 <admin@yiovo.com>
+// +----------------------------------------------------------------------
+declare (strict_types=1);
+
+namespace app\api\service\passport;
+
+use think\facade\Log;
+use yiovo\cache\facade\Cache;
+use yiovo\captcha\facade\CaptchaApi;
+use app\api\validate\passport\EmailCaptcha as ValidateEmailCaptcha;
+use app\common\service\BaseService;
+use cores\exception\BaseException;
+use PHPMailer\PHPMailer\PHPMailer;
+use PHPMailer\PHPMailer\SMTP;
+use PHPMailer\PHPMailer\Exception;
+
+/**
+ * 服务类:发送邮箱验证码
+ * Class MailCaptcha
+ * @package app\api\service\passport
+ */
+class MailCaptcha extends BaseService
+{
+    // 最大发送次数,默认10次
+    protected int $sendTimes = 10;
+
+    // 发送限制间隔时间,默认24小时
+    protected int $safeTime = 86400;
+
+    /**
+     * 发送邮件验证码
+     * @param array $data
+     * @return bool
+     * @throws BaseException
+     */
+    public function handle(array $data): bool
+    {
+        // 数据验证
+        $this->validate($data);
+        // 执行发送短信
+        if (!$this->sendCaptcha($data['email'])) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * 执行发送邮箱验证码
+     * @param string $email
+     * @return bool
+     */
+    public function sendCaptcha(string $email): bool
+    {
+        // 缓存发送记录并判断次数
+        if (!$this->record($email)) {
+            return false;
+        }
+        // 生成验证码
+        $smsCaptcha = CaptchaApi::createSMS($email);
+
+        $mail = new PHPMailer(true);
+        try {
+            //Server settings
+            $mail->SMTPDebug = SMTP::DEBUG_SERVER;//DEBUG_OFF                   //Enable verbose debug output
+            $mail->SMTPOptions = array(
+                'ssl' => array(
+                    'verify_peer' => false,
+                    'verify_peer_name' => false,
+                    'allow_self_signed' => true
+                )
+            );
+            $mail->isSMTP();                                            //Send using SMTP
+            $mail->Host = 'smtp.163.com';                     //Set the SMTP server to send through
+            $mail->SMTPAuth = true;                                   //Enable SMTP authentication
+            $mail->Username = 'zhangdehua814@163.com';                     //SMTP username
+            $mail->Password = 'SGPMIQCKVKGIJUGQ';                               //SMTP password
+            $mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;            //Enable implicit TLS encryption
+            $mail->Port = 465;                                    //TCP port to connect to; use 587 if you have set `SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS`
+
+            //Recipients
+            $mail->setFrom('zhangdehua814@163.com', 'Mailer');
+            $mail->addAddress($email, 'Gold');     //Add a recipient
+            //$mail->addAddress('ellen@example.com');               //Name is optional
+            //$mail->addReplyTo('info@example.com', 'Information');
+            //$mail->addCC('cc@example.com');
+            //$mail->addBCC('bcc@example.com');
+
+            //Attachments
+            //$mail->addAttachment('/var/tmp/file.tar.gz');         //Add attachments
+            //$mail->addAttachment('/tmp/image.jpg', 'new.jpg');    //Optional name
+
+            //Content
+            //$mail->isHTML(true);                                  //Set email format to HTML
+            $mail->Subject = 'Captcha';
+            $mail->Body = 'Your captcha is ' . $smsCaptcha['code'] . '.Please use it in 15 minutes';
+            $mail->AltBody = 'This is the Your captcha for vapes';
+
+            $mail->send();
+            //echo 'Message has been sent';
+        } catch (Exception $e) {
+            //echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
+            Log::error(__CLASS__ . ':' . __METHOD__ . $e->getMessage() . '---' . $mail->ErrorInfo);
+            Log::error(__CLASS__ . ':' . __METHOD__, ['errMsg' => $e->getMessage(), 'mailError' => $mail->ErrorInfo]);
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * 发送营销文本邮件
+     * @param string $email
+     * @param string $subject
+     * @param string $body
+     * @param string $altBody
+     * @param bool $isHtml
+     * @param string $name
+     * @return bool
+     */
+    public function sendText(string $email, string $subject = '', string $body = '', string $altBody = '', bool $isHtml = false, string $name = 'vip'): bool
+    {
+        $mail = new PHPMailer(true);
+        try {
+            //Server settings
+            $mail->SMTPDebug = SMTP::DEBUG_SERVER;                      //Enable verbose debug output
+            $mail->isSMTP();                                            //Send using SMTP
+            $mail->Host = 'smtp.163.com';                     //Set the SMTP server to send through
+            $mail->SMTPAuth = true;                                   //Enable SMTP authentication
+            $mail->Username = 'zhangdehua814@163.com';                     //SMTP username
+            $mail->Password = 'SGPMIQCKVKGIJUGQ';                               //SMTP password
+            $mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;            //Enable implicit TLS encryption
+            $mail->Port = 465;                                    //TCP port to connect to; use 587 if you have set `SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS`
+
+            //Recipients
+            $mail->setFrom('zhangdehua814@163.com', 'Mailer');
+            $mail->addAddress($email, $name);     //Add a recipient
+
+            //Content
+            if ($isHtml) {
+                $mail->isHTML(true);                                  //Set email format to HTML
+            }
+            $mail->Subject = $subject;
+            $mail->Body = $body;
+            if (!empty($altBody)) {
+                $mail->AltBody = 'This is the body in plain text for non-HTML mail clients';
+            }
+
+            $mail->send();
+            echo 'Message has been sent';
+        } catch (Exception $e) {
+            echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
+            Log::error(__CLASS__ . ':' . __METHOD__, ['errMsg' => $e->getMessage(), 'mailError' => $mail->ErrorInfo]);
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * 记录短信验证码发送记录并判断是否超出发送限制
+     * @param string $mobile
+     * @return bool
+     */
+    private function record(string $email): bool
+    {
+        // 获取发送记录缓存
+        $record = Cache::get("sendCaptchaEmail.$email");
+        // 写入缓存:记录剩余发送次数
+        if (empty($record)) {
+            Cache::set("sendCaptchaEmail.$email", ['times' => $this->sendTimes - 1], $this->safeTime);
+            return true;
+        }
+        // 判断发送次数是否合法
+        if ($record['times'] <= 0) {
+            $this->error = '很抱歉,已超出今日最大发送次数限制';
+            return false;
+        }
+        // 发送次数递减
+        Cache::update("sendCaptchaEmail.$email", ['times' => $record['times'] - 1]);
+        return true;
+    }
+
+    /**
+     * 数据验证
+     * @param array $data
+     * @throws BaseException
+     */
+    public function validate(array $data)
+    {
+        // 数据验证
+        $validate = new ValidateEmailCaptcha;
+        if (!$validate->check($data)) {
+            throwError($validate->getError());
+        }
+        // 验证图形验证码
+//        if (!CaptchaApi::check($data['captchaCode'], $data['captchaKey'])) {
+//            throwError('很抱歉,图形验证码不正确');
+//        }
+    }
+
+    public function checkCaptcha($captchaCode = '', $email = '')
+    {
+        $localCode = Cache::get('captchaSMS.' . $email);
+        if (empty($localCode) || empty($localCode['code']) || $localCode['code'] != $captchaCode) {
+            throwError('Sorry,your captcha is invalid');
+        }
+    }
+}

+ 46 - 0
app/api/validate/passport/EmailCaptcha.php

@@ -0,0 +1,46 @@
+<?php
+// +----------------------------------------------------------------------
+// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2017~2024 https://www.yiovo.com All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
+// +----------------------------------------------------------------------
+// | Author: 萤火科技 <admin@yiovo.com>
+// +----------------------------------------------------------------------
+declare (strict_types=1);
+
+namespace app\api\validate\passport;
+
+use think\Validate;
+
+/**
+ * 验证类:发送邮件验证码
+ * Class SmsCaptcha
+ * @package app\api\validate\passport
+ */
+class EmailCaptcha extends Validate
+{
+    /**
+     * 验证规则
+     * @var array
+     */
+    protected $rule = [
+        // 图形验证码 (用户输入)
+        //'captchaCode' => ['require'],
+        // 图形验证码 (key)
+        //'captchaKey' => ['require'],
+        // 用户手机号
+        'email' => ['require'],
+    ];
+
+    /**
+     * 验证提示
+     * @var string[]
+     */
+    protected $message  =   [
+        'captchaCode.require' => '图形验证码code不能为空',
+        'captchaKey.require' => '图形验证码key不能为空',
+        'email.require' => '邮箱不能为空',
+    ];
+}