getMessage(); return false; } // 将openid返回给前端缓存 支付的时候降openid传给后端 if (empty($user_id)) { //系统中没有用户-调用authlogin接口生成新用户 return ['openid' => $response['openid'] ?? '']; } else { $user_info = UserServer::updateUser($response, Client_::mnp, $user_id); $user_info['openid'] = $response['openid'] ?? ''; } //验证用户信息 $check_res = self::checkUserInfo($user_info); if (true !== $check_res) { self::$error = $check_res; return false; } //创建会话 $user_info['token'] = self::createSession($user_info['id'], Client_::mnp); unset($user_info['id'], $user_info['disable']); return $user_info->toArray(); } /** * Notes: 新用户登录 * @param $post * @author 段誉(2021/4/19 16:57) * @return array * @throws \think\Exception * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException * @throws \think\exception\PDOException */ 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::$error = $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) { self::$error = $check_res; return false; } //创建会话 $user_info['token'] = self::createSession($user_info['id'], Client_::mnp); unset($user_info['id'], $user_info['disable']); return $user_info->toArray(); } /** * 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(); $app = Factory::miniProgram($config); $response = $app->auth->session($post['code']); if (!isset($response['openid']) || empty($response['openid'])) { throw new \think\Exception('获取openID失败'); } return $response; } /** * Notes: 根据微信返回信息查询当前用户id * @param $response * @author 段誉(2021/4/19 16:52) * @return mixed */ public static function getUserByWechatResponse($response) { $user_id = UserAuth::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; } /** * Notes: 检查用户信息 * @param $user_info * @author 段誉(2021/4/19 16:54) * @return bool|string */ 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 = SessionModel::where(['user_id' => $user_id, 'client' => $client]) ->value('token'); if($token) { Cache::delete($token); } $result = SessionModel::where(['user_id' => $user_id, 'client' => $client]) ->findOrEmpty(); $time = time(); $expire_time = $time + Config::get('project.token_expire_time'); // 新token $token = md5($user_id . $client . $time); $data = [ 'user_id' => $user_id, 'token' => $token, 'client' => $client, 'update_time' => $time, 'expire_time' => $expire_time, ]; if ($result->isEmpty()) { SessionModel::create($data); } else { SessionModel::where(['user_id' => $user_id, 'client' => $client]) ->update($data); } //更新登录信息 $login_ip = $ip = request()->ip(); User::where(['id' => $user_id]) ->update(['login_time' => $time, 'login_ip' => $login_ip]); // 获取最新的用户信息 $user_info = User::alias('u') ->join('session s', 'u.id=s.user_id') ->where(['s.token' => $token]) ->field('u.*,s.token,s.client') ->find(); $user_info = $user_info ? $user_info->toArray() : []; //创建新的缓存 $ttl = 0 + Config::get('project.token_expire_time'); Cache::set($token, $user_info, $ttl); return $token; } public static function register($post) { Db::startTrans(); try{ $time = time(); $salt = substr(md5($time . $post['mobile']), 0, 4);//随机4位密码盐 $password = create_password($post['password'], $salt);//生成密码 $user_data = [ 'avatar' => ConfigServer::get('website', 'user_image'), 'sn' => create_user_sn(), 'mobile' => $post['mobile'], 'salt' => $salt, 'password' => $password, 'create_time' => $time, 'distribution_code' => generate_invite_code(),//分销邀请码 'is_distribution' => DistributionLogic::isDistributionMember(),//是否为分销会员 'client' => $post['client'] ]; $user_data['nickname'] = '用户'.$user_data['sn']; $user = User::create($user_data); $token = self::createSession($user->id, $post['client']); //生成会员分销扩展表 DistributionLogic::createUserDistribution($user->id); // 生成分销基础信息表 \app\common\logic\DistributionLogic::add($user->id); //注册赠送 self::registerAward($user->id); Db::commit(); return ['token' => $token]; }catch(\Exception $e){ Db::rollback(); self::$error = $e->getMessage(); return false; } } 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){ $user = User::findOrEmpty($user_id); $user->user_integral += $register_award_integral; $user->save(); 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); } // 赠送成长值 $register_growth = ConfigServer::get('register', 'growth', 0); if($register_growth > 0) { $user = User::findOrEmpty($user_id); $user->user_growth += $register_growth; $user->save(); AccountLogLogic::AccountRecord($user_id,$register_growth,1,AccountLog::register_give_growth,''); // 更新用户会员等级 LevelLogic::updateUserLevel([$user]); } } /** * 手机号密码登录 */ public static function mpLogin($post) { $user = User::field(['id', 'nickname', 'avatar', 'level', 'disable', 'distribution_code']) ->where(['mobile' => $post['mobile']]) ->findOrEmpty()->toArray(); $user['token'] = self::createSession($user['id'], $post['client']); if (empty($user['avatar'])) { $user['avatar'] = UrlServer::getFileUrl(ConfigServer::get('website', 'user_image')); } else { $user['avatar'] = UrlServer::getFileUrl($user['avatar']); } return $user; } /** * 获取code的url * @param $url * @return string */ public static function codeUrl($url) { $config = WeChatServer::getOaConfig(); $app = Factory::officialAccount($config); $response = $app ->oauth ->scopes(['snsapi_userinfo']) ->redirect($url) ->getTargetUrl(); return $response; } /*** * Desc: 微信公众号登录 * @param $post * @return array|string * @throws Exception * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException * @throws \think\exception\PDOException */ public static function oaLogin($post) { //微信调用 try { $config = WeChatServer::getOaConfig(); $app = Factory::officialAccount($config); $response = $app ->oauth ->scopes(['snsapi_userinfo']) ->getAccessToken($post['code']); if (!isset($response['openid']) || empty($response['openid'])) { throw new Exception(); } $user = $app->oauth->user($response); $user = $user->getOriginal(); } catch (Exception $e) { return $e->getMessage(); } //添加或更新用户 $user_id = UserAuth::alias('au') ->join('user u', 'au.user_id=u.id') ->where(['u.del' => 0]) ->where(function ($query) use ($user) { $query->whereOr(['au.openid' => $user['openid']]); if(isset($user['unionid']) && !empty($user['unionid'])){ $query->whereOr(['au.unionid' => $user['unionid']]); } }) ->value('user_id'); if (empty($user_id)) { $user_info = UserServer::createUser($user, Client_::oa); } else { $user_info = UserServer::updateUser($user, Client_::oa, $user_id); } if (empty($user_info)) { return '登录失败:user'; } if ($user_info['disable']) { return '该用户被禁用'; } //创建会话 $user_info['token'] = self::createSession($user_info['id'], Client_::oa); unset($user_info['id']); unset($user_info['disable']); return $user_info->toArray(); // return $user_info; } /*** * app微信登录 * @param $post * @return array|\PDOStatement|string|\think\Model|null * @throws Exception * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException * @throws \think\exception\PDOException */ public static function uinAppLogin($post) { //微信调用 try { if (empty($post['openid']) || empty($post['access_token']) || empty($post['client'])){ throw new Exception('参数缺失'); } //sdk不支持app登录,直接调用微信接口 $requests = Requests::get('https://api.weixin.qq.com/sns/userinfo?openid=' . 'openid=' . $post['openid'] . '&access_token=' . $post['access_token']); $user = json_decode($requests->body, true); } catch (Exception $e) { return $e->getMessage(); } // dump($user); //添加或更新用户 $user_id = UserAuth::alias('au')->join('user u', 'au.user_id=u.id') ->where(['u.del' => 0]) ->where(function ($query) use ($user) { $query->whereOr(['au.openid' => $user['openid']]) ->whereOr(['au.unionid' => $user['unionid']]); }) ->value('user_id'); if (empty($user_id)) { $user_info = UserServer::createUser($user, $post['client']); } else { $user_info = UserServer::updateUser($user, $post['client'], $user_id); } if (empty($user_info)) { return '登录失败:user'; } if ($user_info['disable']) { return '该用户被禁用'; } //创建会话 $user_info['token'] = self::createSession($user_info['id'], $post['client']); unset($user_info['id']); unset($user_info['disable']); return $user_info; } //手机号密码登录 public static function login($post) { $user_info = User::field(['id', 'nickname', 'avatar', 'level', 'disable', 'distribution_code']) ->where(['account|mobile' => $post['mobile']]) ->find()->toArray(); $user_info['token'] = self::createSession($user_info['id'], $post['client']); if (empty($user_info['avatar'])) { $user_info['avatar'] = UrlServer::getFileUrl(ConfigServer::get('website', 'user_image')); } else { $user_info['avatar'] = UrlServer::getFileUrl($user_info['avatar']); } return $user_info; } //退出登录 public static function logout($user_id, $client) { return self::expirationSession($user_id, $client); } /** * 设置会话过期 * @param $user_id * @param $client * @throws \think\Exception * @throws \think\exception\PDOException */ public static function expirationSession($user_id, $client) { $time = time(); $token = Db::name('session') ->where(['user_id' => $user_id, 'client' => $client]) ->value('token'); $token_cache = new TokenCache($token); $token_cache->del(); return Db::name('session') ->where(['user_id' => $user_id, 'client' => $client]) ->update(['update_time' => $time, 'expire_time' => $time]); } /** * @notes PC扫码登录, 二维码链接 * @return false|string * @author 段誉 * @date 2021/10/29 11:47 */ public static function scanCode() { try { $config = WeChatServer::getOpWebConfig(); $appid = $config['app_id']; $domain = request()->domain(); $url = $domain.'/pc/account/login'; $redirect_uri = UrlEncode($url); $state = MD5(time().rand(10000, 99999)); cache($state, $state, 600); //缓存600 $url = "https://open.weixin.qq.com/connect/qrconnect?appid=$appid&redirect_uri=$redirect_uri&response_type=code&scope=snsapi_login&state=$state#wechat_redirect"; return $url; } catch (\Exception $e) { self::$error = $e->getMessage(); return false; } } /** * @notes PC端扫码登录 * @param $params * @return array|false * @author 段誉 * @date 2021/10/29 18:00 */ public static function scanLogin($params) { try { //验证参数 if (empty($params['code']) || empty($params['state'])) { throw new \Exception('参数缺失'); } //验证state $state = cache($params['state']); if (empty($state)) { throw new \Exception('二维码已失效或不存在,请重新扫码'); } $config = WeChatServer::getOpWebConfig(); $appid = $config['app_id']; $secret = $config['secret']; //通过code获取access_token,openid,unionid $requests = Requests::get('https://api.weixin.qq.com/sns/oauth2/access_token?appid=' . $appid . '&secret=' . $secret . '&code=' . $params['code'] . '&grant_type=authorization_code'); $user_auth = json_decode($requests->body, true); if (empty($user_auth['openid']) || empty($user_auth['access_token'])) { throw new \think\Exception('获取openID失败'); } //获取用户信息 $response = Requests::get('https://api.weixin.qq.com/sns/userinfo?access_token='. $user_auth['access_token'] . '&openid=' . $user_auth['openid']); $response = json_decode($response->body, true); //在系统中查找openid和unionid是否存在 $user_id = self::getUserByWechatResponse($response); if (empty($user_id)) { $user_info = UserServer::createUser($response,ClientEnum::pc); } else { $user_info = UserServer::updateUser($response, ClientEnum::pc, $user_id); } //验证用户信息 $check_res = self::checkUserInfo($user_info); if (true !== $check_res) { throw new \Exception($check_res); } //创建会话 $user_info['token'] = self::createSession($user_info['id'], ClientEnum::pc); unset($user_info['id']); unset($user_info['disable']); return $user_info->toArray(); } catch (\Exception $e) { self::$error = $e->getMessage(); return false; } } /** * 第三方接口登录 APPID和appSecret */ public static function apiLogin($post) { try { if (!$userApi = UserApi::where('app_id', $post['app_id'])->where('app_secret', $post['app_secret'])->find()) { throw new \Exception('账号错误'); } $user = User::field(['id', 'nickname', 'avatar', 'level', 'disable', 'distribution_code', 'is_api', 'del']) ->where(['id' => $userApi['id']]) ->findOrEmpty()->toArray(); if ($user['disable'] > 0) { throw new \Exception('账号已禁用'); } if ($user['del'] == 1) { throw new \Exception('账号异常,请联系管理员'); } if ($user['is_api'] != 1) { throw new \Exception('账号API授权已关闭'); } unset($user['del']); $user['token'] = self::createSession($user['id'], ClientEnum::api); if (empty($user['avatar'])) { $user['avatar'] = UrlServer::getFileUrl(ConfigServer::get('website', 'user_image')); } else { $user['avatar'] = UrlServer::getFileUrl($user['avatar']); } return $user; } catch (\Exception $e) { self::$error = $e->getMessage(); return false; } } }