Răsfoiți Sursa

短信登录

shish 1 lună în urmă
părinte
comite
b5c13cb91f
2 a modificat fișierele cu 183 adăugiri și 78 ștergeri
  1. 5 78
      app-ghs/controllers/AuthController.php
  2. 178 0
      app-hd/controllers/AuthController.php

+ 5 - 78
app-ghs/controllers/AuthController.php

@@ -816,113 +816,40 @@ class AuthController extends PublicController
         $postParams = Yii::$app->request->post();
         $allParams = array_merge($getParams, $postParams);
         $mobile = $allParams['mobile'] ?? '';
-        $captchaVerifyParam = $allParams['captchaVerifyParam'] ?? '';
 
         if (!stringUtil::isMobile($mobile)) {
             util::fail('请填写正确手机号');
         }
 
-        // 1. 验证阿里云人机验证码(生产环境强制,本地环境若未传则容灾放行)
-        if (empty($captchaVerifyParam)) {
-            if (Yii::getAlias('@env') !== 'local') {
-                util::fail('请先完成人机验证');
-            }
-        } else {
-            if (!$this->verifyAliyunCaptcha($captchaVerifyParam)) {
-                util::fail('人机验证未通过,请重试');
-            }
-        }
-
-        // 2. 安全检查:单手机号 60 秒防刷
+        // 1. 安全检查:单手机号 60 秒防刷
         $lockKey = 'LOGIN_SMS_LOCK_' . $mobile;
         if (Yii::$app->redis->executeCommand('GET', [$lockKey])) {
             util::fail('发送过于频繁,请稍后再试');
         }
 
-        // 3. 安全检查:单手机号每日上限 5 条
+        // 2. 安全检查:单手机号每日上限 5 条
         $dayKey = 'LOGIN_SMS_COUNT_' . date('Ymd') . '_' . $mobile;
         $sendCount = (int)Yii::$app->redis->executeCommand('GET', [$dayKey]);
         if ($sendCount >= 5) {
             util::fail('该手机号今日获取验证码已达上限');
         }
 
-        // 4. 生成 6 位随机验证码并保存至 Redis(有效期 5 分钟)
+        // 3. 生成 6 位随机验证码并保存至 Redis(有效期 5 分钟)
         $code = (string)rand(100000, 999999);
         $codeCacheKey = 'LOGIN_SMS_CODE_' . $mobile;
         Yii::$app->redis->executeCommand('SETEX', [$codeCacheKey, 300, $code]);
 
-        // 5. 调用系统自带的限流发送组件 (内置了 IP 60秒锁和每日15条限制)
+        // 4. 调用系统自带的限流发送组件 (内置了 IP 60秒锁和每日15条限制)
         $minute = 5;
         sms::send($mobile . ',' . $code . ',' . $minute, '登录验证码:{$var},{$var}分钟内有效');
 
-        // 6. 写入单手机号限制锁
+        // 5. 写入单手机号限制锁
         Yii::$app->redis->executeCommand('SETEX', [$lockKey, 60, '1']);
         Yii::$app->redis->executeCommand('SETEX', [$dayKey, 86400, $sendCount + 1]);
 
         util::complete('验证码发送成功');
     }
 
-    /**
-     * 【用途】校验阿里云验证码2.0
-     * 【为什么】利用已安装的 alibabacloud/client 进行通用 RPC 调用,校验前端传来的验证参数
-     */
-    private function verifyAliyunCaptcha($captchaVerifyParam)
-    {
-        if (empty($captchaVerifyParam)) {
-            return false;
-        }
-
-        try {
-            $accessKeyId = Yii::$app->params['aliyun']['accessKeyId'] ?? Yii::$app->params['accessKeyId'] ?? '';
-            $accessKeySecret = Yii::$app->params['aliyun']['accessKeySecret'] ?? Yii::$app->params['accessKeySecret'] ?? '';
-            $sceneId = Yii::$app->params['aliyun']['captchaSceneId'] ?? Yii::$app->params['aliyunCaptchaSceneId'] ?? 'YOUR_SCENE_ID';
-
-            if (empty($accessKeyId) || empty($accessKeySecret)) {
-                Yii::error("阿里云验证码校验失败:未配置 AccessKey");
-                return false;
-            }
-
-            // 初始化阿里云客户端
-            \AlibabaCloud\Client\AlibabaCloud::accessKeyClient($accessKeyId, $accessKeySecret)
-                ->regionId('cn-hangzhou')
-                ->asDefaultClient();
-
-            // 发起通用 RPC 请求调用 VerifyIntelligentCaptcha
-            $result = \AlibabaCloud\Client\AlibabaCloud::rpc()
-                ->product('Captcha')
-                ->version('2023-03-05')
-                ->action('VerifyIntelligentCaptcha')
-                ->method('POST')
-                ->scheme('https')
-                ->options([
-                    'query' => [
-                        'CaptchaVerifyParam' => $captchaVerifyParam,
-                        'SceneId' => $sceneId,
-                    ],
-                ])
-                ->request();
-
-            $data = $result->toArray();
-            
-            Yii::info("阿里云验证码返回结果: " . json_encode($data), 'captcha');
-
-            // 兼容可能包裹在 Result 节点下或扁平结构
-            $verifyResult = $data['Result']['VerifyResult'] ?? $data['VerifyResult'] ?? null;
-            if ($verifyResult === true) {
-                return true;
-            }
-
-            return false;
-        } catch (\Exception $e) {
-            Yii::error("阿里云验证码校验异常: " . $e->getMessage());
-            // 容灾策略:如果是本地环境,可以放行
-            if (Yii::getAlias('@env') === 'local') {
-                return true;
-            }
-            return false;
-        }
-    }
-
     /**
      * 【用途】短信验证码登录
      * 【为什么】提供免密码快捷登录方式,验证通过后自动签发 JWT Token 并返回商家后台所需的所有初始化数据

+ 178 - 0
app-hd/controllers/AuthController.php

@@ -16,6 +16,7 @@ use common\components\dict;
 use common\components\httpUtil;
 use common\components\imgUtil;
 use common\components\jwt;
+use common\components\sms;
 use common\components\util;
 use Yii;
 use common\components\stringUtil;
@@ -813,4 +814,181 @@ class AuthController extends PublicController
         util::success(['html' => $html]);
     }
 
+    /**
+     * 【用途】发送登录短信验证码
+     * 【为什么】供短信登录功能获取验证码,并包含防刷安全限制(单手机号60秒锁、每日上限5条)
+     */
+    public function actionSendLoginSms()
+    {
+        $getParams = Yii::$app->request->get();
+        $postParams = Yii::$app->request->post();
+        $allParams = array_merge($getParams, $postParams);
+        $mobile = $allParams['mobile'] ?? '';
+
+        if (!stringUtil::isMobile($mobile)) {
+            util::fail('请填写正确手机号');
+        }
+
+        // 1. 安全检查:单手机号 60 秒防刷
+        $lockKey = 'LOGIN_SMS_LOCK_' . $mobile;
+        if (Yii::$app->redis->executeCommand('GET', [$lockKey])) {
+            util::fail('发送过于频繁,请稍后再试');
+        }
+
+        // 2. 安全检查:单手机号每日上限 5 条
+        $dayKey = 'LOGIN_SMS_COUNT_' . date('Ymd') . '_' . $mobile;
+        $sendCount = (int)Yii::$app->redis->executeCommand('GET', [$dayKey]);
+        if ($sendCount >= 5) {
+            util::fail('该手机号今日获取验证码已达上限');
+        }
+
+        // 3. 生成 6 位随机验证码并保存至 Redis(有效期 5 分钟)
+        $code = (string)rand(100000, 999999);
+        $codeCacheKey = 'LOGIN_SMS_CODE_' . $mobile;
+        Yii::$app->redis->executeCommand('SETEX', [$codeCacheKey, 300, $code]);
+
+        // 4. 调用系统自带的限流发送组件 (内置了 IP 60秒锁和每日15条限制)
+        $minute = 5;
+        sms::send($mobile . ',' . $code . ',' . $minute, '登录验证码:{$var},{$var}分钟内有效');
+
+        // 5. 写入单手机号限制锁
+        Yii::$app->redis->executeCommand('SETEX', [$lockKey, 60, '1']);
+        Yii::$app->redis->executeCommand('SETEX', [$dayKey, 86400, $sendCount + 1]);
+
+        util::complete('验证码发送成功');
+    }
+
+    /**
+     * 【用途】短信验证码登录
+     * 【为什么】提供免密码快捷登录方式,验证通过后自动签发 JWT Token 并返回商家后台所需的所有初始化数据
+     */
+    public function actionSmsLogin()
+    {
+        $getParams = Yii::$app->request->get();
+        $postParams = Yii::$app->request->post();
+        $allParams = array_merge($getParams, $postParams);
+        $mobile = $allParams['mobile'] ?? '';
+        $code = $allParams['code'] ?? '';
+
+        if (empty($mobile) || empty($code)) {
+            util::fail('手机号和验证码不能为空');
+        }
+
+        if (!stringUtil::isMobile($mobile)) {
+            util::fail('请填写正确手机号');
+        }
+
+        // 1. 校验验证码
+        $codeCacheKey = 'LOGIN_SMS_CODE_' . $mobile;
+        $savedCode = Yii::$app->redis->executeCommand('GET', [$codeCacheKey]);
+
+        if (empty($savedCode) || $savedCode !== $code) {
+            util::fail('验证码错误或已过期');
+        }
+
+        // 2. 验证通过,立即销毁验证码以确保一次性使用
+        Yii::$app->redis->executeCommand('DEL', [$codeCacheKey]);
+
+        // 3. 查找用户并执行登录
+        $admin = AdminService::getByCondition(['mobile' => $mobile]);
+        if (empty($admin)) {
+            util::fail('请先注册哦...');
+        }
+
+        $openShop = $admin['openShop'] ?? 1;
+        $currentShopId = $admin['currentShopId'] ?? 0;
+        if (empty($currentShopId)) {
+            if ($openShop == 2) {
+                util::fail('审核中');
+            }
+            util::fail('请先注册');
+        }
+        $currentShop = \bizHd\shop\classes\ShopClass::getById($currentShopId, true);
+        if (empty($currentShop)) {
+            util::fail('没有找到门店37');
+        }
+        $mainId = $currentShop->mainId ?? 0;
+        $pfShopId = $currentShop->pfShopId ?? 0;
+        $onlyCg = $currentShop->onlyCg ?? 1;
+        $shopExt = ShopExtClass::getByCondition(['shopId' => $currentShop->id], false, false, 'reachVip');
+
+        $shareLogo = imgUtil::groupImg('buy_logo.jpg');
+        if (isset($currentShop->shareLogo) && !empty($currentShop->shareLogo)) {
+            $shareLogo = imgUtil::groupImg($currentShop->shareLogo);
+        }
+
+        $adminId = $admin['id'];
+        $shopAdmin = ShopAdminService::getByCondition(['mainId' => $mainId, 'adminId' => $adminId], true);
+        if (empty($shopAdmin)) {
+            util::fail('无法操作');
+        }
+        if ($shopAdmin->status == 0) {
+            util::fail("您的账号已被冻结");
+        }
+        if ($shopAdmin->delStatus == 1) {
+            util::fail("您的账号已删除");
+        }
+        $token = jwt::getNewToken($adminId);
+        $shopAdmin->lastLogin = date("Y-m-d H:i:s");
+        $shopAdmin->save();
+        $shopAdminId = $shopAdmin->id ?? 0;
+        //是否有切换门店的权限
+        $switchShop = \biz\shop\classes\ShopAdminClass::hasSwitchShopRight($shopAdmin);
+        $prefix = imgUtil::getPrefix();
+        $avatar = isset($admin['avatar']) && !empty($admin['avatar']) ? $prefix . $admin['avatar'] : $prefix . '/retail/default-img.png';
+        $admin['avatar'] = $avatar;
+        $showDemo = 1;
+        $remind = getenv('HD_UPDATE_REMIND') == false ? 0 : getenv('HD_UPDATE_REMIND');
+
+        $hdUpgrading = getenv('HD_UPGRADING') == false ? 0 : getenv('HD_UPGRADING');
+        if ($hdUpgrading == 1) {
+            $allowShopAdminIdsStr = getenv('HD_UPGRADE_ALLOW_SHOP_ADMIN_IDS') ?: '';
+            $allowShopAdminIds = !empty($allowShopAdminIdsStr) ? explode(',', $allowShopAdminIdsStr) : [];
+            if (!in_array($shopAdminId, $allowShopAdminIds)) {
+                util::fail('系统升级中,稍后再试');
+            }
+        }
+
+        $apiHost = Yii::$app->params['hdHost'];
+        $imgUploadApi = $apiHost . '/upload/save-file';
+
+        //惠雅鲜花员工不能看收入情况
+        if (in_array($adminId, [2366, 2812, 4004])) {
+            $shopAdmin->super = 0;
+        }
+
+        //充值送钱有没设置,没有设置则进行设置,临时方法,后面需要去掉,有多处,关键词recharge_sq_init ssh 20251229
+        RechargeSqClass::initData($currentShop);
+        //会员等级有没设置,没有设置则进行设置,临时方法,后面需要去掉,有多处,关键词member_level_init ssh 20251229
+        MemberLevelClass::initData($currentShop);
+
+        //把设备状态更新为登录
+        if (isset($allParams['deviceId']) && $allParams['deviceId'] != '') {
+            $device = \bizHd\device\classes\HdDeviceClass::getByCondition(['shopId' => $currentShopId, 'deviceId' => $allParams['deviceId']], true);
+            if ($device) {
+                $device->status = 1;
+                $device->save();
+            }
+        }
+
+        unset($admin['password']); //返回的用户数据删除密码字段,防止密码加密方法被反查
+        //涉及几个登录的地方,需要同步修改,请搜索关键词uni_login_info
+        util::success([
+            'token' => $token,
+            'admin' => $admin,
+            'shopId' => $currentShopId,
+            'shopAdminId' => $shopAdminId,
+            'switchShop' => $switchShop,
+            'pfShopId' => $pfShopId,
+            'onlyCg' => $onlyCg,
+            'shareLogo' => $shareLogo,
+            'imgUploadApi' => $imgUploadApi,
+            'showDemo' => $showDemo,
+            //有小程序新版本提示更新
+            'update' => $remind,
+            'staff' => $shopAdmin,
+            'reachVip' => $shopExt['reachVip'] //用于判断是否开启vip
+        ]);
+    }
+
 }