WokerTask/app/api/logic/LoginLogic.php

639 lines
22 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台PHP版
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用可去除界面版权logo
// | gitee下载https://gitee.com/likeshop_gitee/likeadmin
// | github下载https://github.com/likeshop-github/likeadmin
// | 访问官网https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\api\logic;
use app\common\cache\WebScanLoginCache;
use app\common\logic\BaseLogic;
use app\api\service\{UserTokenService, WechatUserService};
use app\common\enum\{LoginEnum, user\UserTerminalEnum, YesNoEnum};
use app\common\model\dict\DictData;
use app\common\service\{
ConfigService,
FileService,
wechat\WeChatConfigService,
wechat\WeChatMnpService,
wechat\WeChatOaService,
wechat\WeChatRequestService
};
use app\common\model\user\{User, UserAuth};
use think\facade\{Db, Config};
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use Firebase\JWT\SignatureInvalidException;
use Firebase\JWT\BeforeValidException;
use Firebase\JWT\ExpiredException;
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Exception\GuzzleException;
use Guzzle\Http\Exception\RequestException;
/**
* 登录逻辑
* Class LoginLogic
* @package app\api\logic
*/
class LoginLogic extends BaseLogic
{
/**
* @notes 账号密码注册
* @param array $params
* @return bool
* @author 段誉
* @date 2022/9/7 15:37
*/
public static function register(array $params)
{
try {
// 手机号已被使用
$mobileUser = User::where(['account' => $params['account']])->find();
if (!empty($mobileUser)) {
self::setError('手机号已被注册');
return false;
}
$count = User::where('company_id', $params['company_id'])->count();
$value = DictData::where('id', 28)->value('value');
if ($count >= $value) {
self::setError('你创建的账号已达上限');
return false;
}
$userSn = User::createUserSn();
$passwordSalt = Config::get('project.unique_identification');
$password = create_password($params['password'], $passwordSalt);
// if($params['qualification']){
// $params['qualification']=explode(',',$params['qualification']);
// }
if ($params['avatar'] != '') {
$avatar = $params['avatar'];
} else {
$avatar = ConfigService::get('default_image', 'user_avatar');
}
$group_id=1;
if ($params['is_captain']) {
$group_id=2;
}
// 镇农科公司服务部长
if ($params['is_service_manager'] == 1) {
$user = User::where(['company_id' => $params['company_id'], 'group_id' => 14])->find();
if (!empty($user)) {
self::setError('公司已创建服务部长账号');
return false;
}
$group_id=14;
}
User::create([
'sn' => $userSn,
'avatar' => $avatar,
'is_captain' => $params['is_captain'],
'nickname' => $params['nickname'],
'account' => $params['account'],
'mobile' => $params['account'],
'id_card' => $params['id_card'],
'password' => $password,
'channel' => 0,
'sex' => $params['sex'],
'province' => $params['province'],
'city' => $params['city'],
'area' => $params['area'],
'street' => $params['street'],
'village' => $params['village'],
'brigade' => $params['brigade'],
'address' => $params['address'],
'qualification' => json_encode($params['qualification']),
'company_id' => $params['company_id'],
'group_id' => $group_id,
]);
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('用户不存在');
}
if (isset($params['register_id']) && $params['register_id'] != '') {
$user->register_id = $params['register_id'];
}
if (isset($params['ytj_register_id']) && $params['ytj_register_id'] != '') {
$user->ytj_register_id = $params['ytj_register_id'];
}
//更新登录信息
$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);
if(isset($params['shop_token'])&&$params['shop_token']!=''){
$jwt = JWT::decode($params['shop_token'], new Key('ae47e94a7dcd1fdfacb499b60e361a8d', 'HS256'));
if ($jwt) {
$user_id = $jwt->jti[0];
Db::name('user_other')->insert(['user_id'=>$user->id,'other_user_id'=>$user_id,'type'=>'shop_user']);
}
}
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 shop($payload,$type=1){
$jwt = JWT::decode($payload, new Key('ae47e94a7dcd1fdfacb499b60e361a8d', 'HS256'));
if ($jwt) {
$user_id = $jwt->jti[0];
$find = Db::name('user_other')->where('other_user_id', $user_id)->where('type', 'shop_user')->find();
if ($find) {
$user = User::where('id', $find['user_id'])->findOrEmpty();
if ($user->isEmpty()) {
self::setError('无登录信息');
return false;
}
$terminal=3;
$Android=IndexLogic::isAndroid();
if($Android){
$terminal=5;
}
$ios=IndexLogic::isIOS();
if($ios){
$terminal=6;
}
$userInfo = UserTokenService::setToken($user->id, $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'],
];
}
}
self::setError('无登录信息');
return false;
}
public static function parseToken($token){
$app_key = 'ae47e94a7dcd1fdfacb499b60e361a8d';
try {
JWT::$leeway = 10; //当前时间减去10秒时间留点余地
$decoded = JWT::decode($token, new Key($app_key, 'HS256'));
$decodedArray = json_decode(json_encode($decoded), true);
$jwtData = $decodedArray['data'] ?? [];
if (empty($jwtData['uid']) || empty($jwtData['phone'])) {
self::setError('当前账号未授权,请手动登录');
return false;
}
$where = ['account|mobile' => $jwtData['phone']];
$user = User::where($where)->findOrEmpty();
if ($user->isEmpty()) {
try {
//适配解析商城token
$parseHostUrl = env('url.shop_prefix') . '/api/parse/token';
$client = new Client(['timeout' => 5]);
$requestBody['token'] = $token;
$response = $client->request('POST', $parseHostUrl, [
'json' => $requestBody,
'verify' => false
]);
$responseData = $response->getBody()->getContents();
$responseArray = json_decode($responseData, true);
if (empty($responseArray['data']['user']['uid'])) {
self::setError('用户不存在,请联系管理员开通供销系统账户');
return false;
} else {
$user_id = $responseArray['data']['user']['uid'];
$find = Db::name('user_other')->where('other_user_id', $user_id)->where('type', 'shop_user')->find();
if ($find) {
$user = User::where('id', $find['user_id'])->findOrEmpty();
if ($user->isEmpty()) {
self::setError('用户不存在,请联系管理员开通供销系统账户');
return false;
}
$terminal=3;
$Android=IndexLogic::isAndroid();
if($Android){
$terminal=5;
}
$ios=IndexLogic::isIOS();
if($ios){
$terminal=6;
}
$userInfo = UserTokenService::setToken($user->id, $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'],
];
} else {
self::setError('用户不存在,请联系管理员开通供销系统账户');
return false;
}
}
} catch (GuzzleException $e) {
//return $this->fail($e->getMessage());self::setError('用户不存在,请联系管理员开通供销系统账户');
return false;
}
}
//更新登录信息
$user->login_time = time();
$user->login_ip = request()->ip();
$user->save();
$terminal=3;
$Android=IndexLogic::isAndroid();
if($Android){
$terminal=5;
}
$ios=IndexLogic::isIOS();
if($ios){
$terminal=6;
}
//设置token
$userInfo = UserTokenService::setToken($user->id, $terminal);
//返回登录信息
$avatar = $user->avatar ?: Config::get('project.default_image.user_avatar');
$avatar = FileService::getFileUrl($avatar);
$user_id = $jwtData['uid'];
return [
'nickname' => $userInfo['nickname'],
'sn' => $userInfo['sn'],
'mobile' => $userInfo['mobile'],
'avatar' => $avatar,
'token' => $userInfo['token'],
];
} catch(\Firebase\JWT\SignatureInvalidException $e) {
self::setError('签名错误');
return false;
} catch(\Firebase\JWT\BeforeValidException $e) {
self::setError('token无效');
return false;
} catch(\Firebase\JWT\ExpiredException $e) {
self::setError('token已过期');
return false;
} catch(\Exception $e) {
self::setError('非法请求');
return false;
}
return false;
}
/**
* @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
]);
}
}