$userSn, 'avatar' => $avatar, 'nickname' => '用户' . $userSn, 'account' => $params['account'], 'password' => $password, 'channel' => $params['channel'], ]); return true; } catch (\Exception $e) { self::setError($e->getMessage()); return false; } } /** * @notes 账号/手机号登录,手机号验证码 * @param $params * @return array|false * @author 段誉 * @date 2022/9/6 19:26 */ public static function login($params) { try { // 账号/手机号 密码登录 $where = ['account|mobile' => $params['account']]; if ($params['scene'] == LoginEnum::MOBILE_CAPTCHA) { //手机验证码登录 $where = ['mobile' => $params['account']]; } $user = User::where($where)->findOrEmpty(); if ($user->isEmpty()) { throw new \Exception('用户不存在'); } //更新登录信息 $user->login_time = time(); $user->login_ip = request()->ip(); $user->save(); //设置token $userInfo = UserTokenService::setToken($user->id, $params['terminal']); //返回登录信息 $avatar = $user->avatar ?: Config::get('project.default_image.user_avatar'); $avatar = FileService::getFileUrl($avatar); return [ 'nickname' => $userInfo['nickname'], 'sn' => $userInfo['sn'], 'mobile' => $userInfo['mobile'], 'avatar' => $avatar, 'token' => $userInfo['token'], ]; } catch (\Exception $e) { self::setError($e->getMessage()); return false; } } public static function authLogin($post) { try { //通过code获取微信 openid $response = self::getWechatResByCode($post); $response['headimgurl'] = $post['headimgurl'] ?? ''; $response['nickname'] = $post['nickname'] ?? ''; //通过获取到的openID或unionid获取当前 系统 用户id $user_id = self::getUserByWechatResponse($response); } catch (Exception $e) { self::setError('登录失败:' . $e->getMessage()); return false; } // catch (\think\Exception $e) { // self::setError('登录失败:' . $e->getMessage()); // return false; // } if (empty($user_id)) { $user_info = UserServer::createUser($response, Client_::mnp); } else { $user_info = UserServer::updateUser($response, Client_::mnp, $user_id); } //验证用户信息 $check_res = self::checkUserInfo($user_info); if (true !== $check_res) { return self::setError($check_res); } //创建会话 $user_info['token'] = self::createSession($user_info['id'], Client_::mnp); unset($user_info['id'], $user_info['disable']); return $user_info; } public static function registerAward($user_id){ $register_award_integral_status = ConfigServer::get('marketing','register_award_integral_status',0); $register_award_coupon_status = ConfigServer::get('marketing','register_award_coupon_status',0); //赠送积分 if($register_award_integral_status){ $register_award_integral = ConfigServer::get('marketing','register_award_integral',0); //赠送的积分 if($register_award_integral > 0){ Db::name('user')->where(['id'=>$user_id])->setInc('user_integral',$register_award_integral); AccountLogLogic::AccountRecord($user_id,$register_award_integral,1,AccountLog::register_add_integral,''); } } //注册账号,首次进入首页时领取优惠券 $register_award_coupon = ConfigServer::get('marketing','register_award_coupon',''); if($register_award_coupon_status && $register_award_coupon){ Cache::tag('register_coupon')->set('register_coupon_'.$user_id,$register_award_coupon); } //会员等级 $user_level = Db::name('user_level')->where(['del'=>0,'growth_value'=>0])->find(); if($user_level){ Db::name('user')->where(['id'=>$user_id])->update(['level'=>$user_level['id']]); } } /** * Notes: 根据code 获取微信信息(openid, unionid) * @param $post * @author 段誉(2021/4/19 16:52) * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * @throws Exception * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException */ public static function getWechatResByCode($post) { // $config = WeChatServer::getMnpConfig(); $response = (new WeChatMnpService())->getMnpResByCode($post['code']); // $app = Factory::miniProgram($config); // $response = $app->auth->session($post['code']); if (!isset($response['openid']) || empty($response['openid'])) { throw new Exception('获取openID失败'); } return $response; } /** * Notes: 根据微信返回信息查询当前用户id * @param $response * @author 段誉(2021/4/19 16:52) * @return mixed */ public static function getUserByWechatResponse($response) { $user_id = Db::name('user_auth')->alias("au") ->join('user u', 'au.user_id=u.id') ->where(['u.del' => 0]) ->where(function ($query) use ($response) { $query->whereOr(['au.openid' => $response['openid']]); if(isset($response['unionid']) && !empty($response['unionid'])){ $query->whereOr(['au.unionid' => $response['unionid']]); } }) ->value('user_id'); return $user_id; } public static function checkUserInfo($user_info) { if (empty($user_info)) { return '登录失败:user'; } if ($user_info['disable']) { return '账号已被禁用'; } return true; } /** * 创建会话 * @param $user_id * @param $client * @return string * @throws \think\Exception * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException * @throws \think\exception\PDOException */ public static function createSession($user_id, $client) { //清除之前缓存 $token = Db::name('session') ->where(['user_id' => $user_id, 'client' => $client]) ->value('token'); if($token) { $token_cache = new TokenCache($token); $token_cache->del(); } $result = Db::name('session') ->where(['user_id' => $user_id, 'client' => $client]) ->find(); $time = time(); $expire_time = $time + Config::get('project.token_expire_time'); $token = md5($user_id . $client . $time); $data = [ 'user_id' => $user_id, 'token' => $token, 'client' => $client, 'update_time' => $time, 'expire_time' => $expire_time, ]; if (empty($result)) { Db::name('session')->insert($data); } else { Db::name('session') ->where(['user_id' => $user_id, 'client' => $client]) ->update($data); } //更新登录信息 $login_ip = $ip = request()->ip(); Db::name('user') ->where(['id' => $user_id]) ->update(['login_time' => $time, 'login_ip' => $login_ip]); //创建新的缓存 (new TokenCache($token, ['token' => $token]))->set(300); return $token; } /** * @notes 退出登录 * @param $userInfo * @return bool * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException * @author 段誉 * @date 2022/9/16 17:56 */ public static function logout($userInfo) { //token不存在,不注销 if (!isset($userInfo['token'])) { return false; } //设置token过期 return UserTokenService::expireToken($userInfo['token']); } /** * @notes 获取微信请求code的链接 * @param string $url * @return string * @author 段誉 * @date 2022/9/20 19:47 */ public static function codeUrl(string $url) { return (new WeChatOaService())->getCodeUrl($url); } /** * @notes 公众号登录 * @param array $params * @return array|false * @throws \GuzzleHttp\Exception\GuzzleException * @author 段誉 * @date 2022/9/20 19:47 */ public static function oaLogin(array $params) { Db::startTrans(); try { //通过code获取微信 openid $response = (new WeChatOaService())->getOaResByCode($params['code']); $userServer = new WechatUserService($response, UserTerminalEnum::WECHAT_OA); $userInfo = $userServer->getResopnseByUserInfo()->authUserLogin()->getUserInfo(); // 更新登录信息 self::updateLoginInfo($userInfo['id']); Db::commit(); return $userInfo; } catch (\Exception $e) { Db::rollback(); self::$error = $e->getMessage(); return false; } } /** * @notes 小程序-静默登录 * @param array $params * @return array|false * @author 段誉 * @date 2022/9/20 19:47 */ public static function silentLogin(array $params) { try { //通过code获取微信 openid $response = (new WeChatMnpService())->getMnpResByCode($params['code']); $userServer = new WechatUserService($response, UserTerminalEnum::WECHAT_MMP); $userInfo = $userServer->getResopnseByUserInfo('silent')->getUserInfo(); if (!empty($userInfo)) { // 更新登录信息 self::updateLoginInfo($userInfo['id']); } return $userInfo; } catch (\Exception $e) { self::$error = $e->getMessage(); return false; } } /** * @notes 小程序-授权登录 * @param array $params * @return array|false * @author 段誉 * @date 2022/9/20 19:47 */ public static function mnpLogin(array $params) { Db::startTrans(); try { //通过code获取微信 openid $response = (new WeChatMnpService())->getMnpResByCode($params['code']); $userServer = new WechatUserService($response, UserTerminalEnum::WECHAT_MMP); $userInfo = $userServer->getResopnseByUserInfo()->authUserLogin()->getUserInfo(); // 更新登录信息 self::updateLoginInfo($userInfo['id']); Db::commit(); return $userInfo; } catch (\Exception $e) { Db::rollback(); self::$error = $e->getMessage(); return false; } } /** * @notes 更新登录信息 * @param $userId * @throws \Exception * @author 段誉 * @date 2022/9/20 19:46 */ public static function updateLoginInfo($userId) { $user = User::findOrEmpty($userId); if ($user->isEmpty()) { throw new \Exception('用户不存在'); } $time = time(); $user->login_time = $time; $user->login_ip = request()->ip(); $user->update_time = $time; $user->save(); } /** * @notes 小程序端绑定微信 * @param array $params * @return bool * @author 段誉 * @date 2022/9/20 19:46 */ public static function mnpAuthLogin(array $params) { try { //通过code获取微信openid $response = (new WeChatMnpService())->getMnpResByCode($params['code']); $response['user_id'] = $params['user_id']; $response['terminal'] = UserTerminalEnum::WECHAT_MMP; return self::createAuth($response); } catch (\Exception $e) { self::$error = $e->getMessage(); return false; } } /** * @notes 公众号端绑定微信 * @param array $params * @return bool * @throws \GuzzleHttp\Exception\GuzzleException * @author 段誉 * @date 2022/9/16 10:43 */ public static function oaAuthLogin(array $params) { try { //通过code获取微信openid $response = (new WeChatOaService())->getOaResByCode($params['code']); $response['user_id'] = $params['user_id']; $response['terminal'] = UserTerminalEnum::WECHAT_OA; return self::createAuth($response); } catch (\Exception $e) { self::$error = $e->getMessage(); return false; } } /** * @notes 生成授权记录 * @param $response * @return bool * @throws \Exception * @author 段誉 * @date 2022/9/16 10:43 */ public static function createAuth($response) { //先检查openid是否有记录 $isAuth = UserAuth::where('openid', '=', $response['openid'])->findOrEmpty(); if (!$isAuth->isEmpty()) { throw new \Exception('该微信已被绑定'); } if (isset($response['unionid']) && !empty($response['unionid'])) { //在用unionid找记录,防止生成两个账号,同个unionid的问题 $userAuth = UserAuth::where(['unionid' => $response['unionid']]) ->findOrEmpty(); if (!$userAuth->isEmpty() && $userAuth->user_id != $response['user_id']) { throw new \Exception('该微信已被绑定'); } } //如果没有授权,直接生成一条微信授权记录 UserAuth::create([ 'user_id' => $response['user_id'], 'openid' => $response['openid'], 'unionid' => $response['unionid'] ?? '', 'terminal' => $response['terminal'], ]); return true; } /** * @notes 获取扫码登录地址 * @return array|false * @author 段誉 * @date 2022/10/20 18:23 */ public static function getScanCode($redirectUri) { try { $config = WeChatConfigService::getOpConfig(); $appId = $config['app_id']; $redirectUri = UrlEncode($redirectUri); // 设置有效时间标记状态, 超时扫码不可登录 $state = MD5(time().rand(10000, 99999)); (new WebScanLoginCache())->setScanLoginState($state); // 扫码地址 $url = WeChatRequestService::getScanCodeUrl($appId, $redirectUri, $state); return ['url' => $url]; } catch (\Exception $e) { self::$error = $e->getMessage(); return false; } } /** * @notes 网站扫码登录 * @param $params * @return array|false * @author 段誉 * @date 2022/10/21 10:28 */ public static function scanLogin($params) { Db::startTrans(); try { // 通过code 获取 access_token,openid,unionid等信息 $userAuth = WeChatRequestService::getUserAuthByCode($params['code']); if (empty($userAuth['openid']) || empty($userAuth['access_token'])) { throw new \Exception('获取用户授权信息失败'); } // 获取微信用户信息 $response = WeChatRequestService::getUserInfoByAuth($userAuth['access_token'], $userAuth['openid']); // 生成用户或更新用户信息 $userServer = new WechatUserService($response, UserTerminalEnum::PC); $userInfo = $userServer->getResopnseByUserInfo()->authUserLogin()->getUserInfo(); // 更新登录信息 self::updateLoginInfo($userInfo['id']); Db::commit(); return $userInfo; } catch (\Exception $e) { Db::rollback(); self::$error = $e->getMessage(); return false; } } /** * @notes 更新用户信息 * @param $params * @param $userId * @return User * @author 段誉 * @date 2023/2/22 11:19 */ public static function updateUser($params, $userId) { return User::where(['id' => $userId])->update([ 'nickname' => $params['nickname'], 'avatar' => FileService::setFileUrl($params['avatar']), 'is_new_user' => YesNoEnum::NO ]); } }