2025-03-16 17:43:30 +08:00
|
|
|
|
<?php
|
2025-04-30 14:52:51 +08:00
|
|
|
|
|
2025-03-16 17:43:30 +08:00
|
|
|
|
namespace app\common\service;
|
|
|
|
|
|
|
2025-04-30 14:52:51 +08:00
|
|
|
|
use app\common\model\User as UserModel;
|
2025-03-16 17:43:30 +08:00
|
|
|
|
use app\common\util\JwtUtil;
|
2025-03-24 14:59:19 +08:00
|
|
|
|
use think\facade\Cache;
|
|
|
|
|
|
use think\facade\Env;
|
2025-04-30 14:52:51 +08:00
|
|
|
|
use think\facade\Log;
|
2025-03-16 17:43:30 +08:00
|
|
|
|
|
|
|
|
|
|
class AuthService
|
|
|
|
|
|
{
|
2025-05-09 09:22:31 +08:00
|
|
|
|
const TOKEN_EXPIRE = 86400;
|
2025-03-16 17:43:30 +08:00
|
|
|
|
|
2025-04-30 14:52:51 +08:00
|
|
|
|
protected $smsService;
|
|
|
|
|
|
|
2025-03-16 17:43:30 +08:00
|
|
|
|
/**
|
2025-04-30 14:52:51 +08:00
|
|
|
|
* 获取用户基本信息
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param string $account
|
|
|
|
|
|
* @param int $typeId
|
|
|
|
|
|
* @return UserModel
|
2025-03-16 17:43:30 +08:00
|
|
|
|
*/
|
2025-04-30 14:52:51 +08:00
|
|
|
|
protected function getUserProfileWithAccountAndType(string $account, int $typeId): UserModel
|
|
|
|
|
|
{
|
|
|
|
|
|
$user = UserModel::where(function ($query) use ($account) {
|
|
|
|
|
|
$query->where('phone', $account)->whereOr('account', $account);
|
|
|
|
|
|
})
|
|
|
|
|
|
->where(function ($query) use ($typeId) {
|
|
|
|
|
|
$query->where('status', 1)->where('typeId', $typeId);
|
|
|
|
|
|
})->find();
|
|
|
|
|
|
|
|
|
|
|
|
return $user;
|
|
|
|
|
|
}
|
2025-03-16 17:43:30 +08:00
|
|
|
|
|
2025-04-29 11:22:10 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 获取用户信息
|
2025-04-30 14:52:51 +08:00
|
|
|
|
*
|
2025-04-29 11:22:10 +08:00
|
|
|
|
* @param string $account 账号(手机号)
|
|
|
|
|
|
* @param string $password 密码(可能是加密后的)
|
|
|
|
|
|
* @param int $typeId 身份信息
|
|
|
|
|
|
* @return array|null
|
|
|
|
|
|
*/
|
2025-04-30 14:52:51 +08:00
|
|
|
|
protected function getUser(string $account, string $password, int $typeId): array
|
2025-04-29 11:22:10 +08:00
|
|
|
|
{
|
2025-04-30 14:52:51 +08:00
|
|
|
|
$user = $this->getUserProfileWithAccountAndType($account, $typeId);
|
2025-04-29 11:22:10 +08:00
|
|
|
|
|
|
|
|
|
|
if (!$user) {
|
2025-04-30 14:52:51 +08:00
|
|
|
|
throw new \Exception('用户不存在或已禁用', 403);
|
2025-04-29 11:22:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-04-30 14:52:51 +08:00
|
|
|
|
if ($user->passwordMd5 !== md5($password)) {
|
|
|
|
|
|
throw new \Exception('账号或密码错误', 403);
|
2025-04-29 11:22:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-04-30 14:52:51 +08:00
|
|
|
|
return $user->toArray();
|
2025-04-29 11:22:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-03-16 17:43:30 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 构造函数
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function __construct()
|
|
|
|
|
|
{
|
|
|
|
|
|
$this->smsService = new SmsService();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 用户登录
|
2025-04-30 14:52:51 +08:00
|
|
|
|
*
|
2025-03-27 15:28:38 +08:00
|
|
|
|
* @param string $account 账号(手机号)
|
2025-03-16 19:24:37 +08:00
|
|
|
|
* @param string $password 密码(可能是加密后的)
|
2025-03-16 17:43:30 +08:00
|
|
|
|
* @param string $ip 登录IP
|
|
|
|
|
|
* @return array
|
|
|
|
|
|
* @throws \Exception
|
|
|
|
|
|
*/
|
2025-04-30 14:52:51 +08:00
|
|
|
|
public function login(string $account, string $password, int $typeId, string $ip)
|
2025-03-16 17:43:30 +08:00
|
|
|
|
{
|
|
|
|
|
|
// 获取用户信息
|
2025-04-30 14:52:51 +08:00
|
|
|
|
$member = $this->getUser($account, $password, $typeId);
|
2025-03-27 15:28:38 +08:00
|
|
|
|
|
2025-03-16 17:43:30 +08:00
|
|
|
|
// 生成JWT令牌
|
|
|
|
|
|
$token = JwtUtil::createToken($user, self::TOKEN_EXPIRE);
|
2025-04-30 14:52:51 +08:00
|
|
|
|
$token_expired = time() + self::TOKEN_EXPIRE;
|
|
|
|
|
|
|
|
|
|
|
|
return compact('member', 'token', 'token_expired');
|
2025-03-16 17:43:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 手机号验证码登录
|
2025-04-30 14:52:51 +08:00
|
|
|
|
*
|
2025-03-27 15:28:38 +08:00
|
|
|
|
* @param string $account 手机号
|
2025-03-16 19:24:37 +08:00
|
|
|
|
* @param string $code 验证码(可能是加密后的)
|
2025-03-16 17:43:30 +08:00
|
|
|
|
* @param string $ip 登录IP
|
2025-03-16 19:24:37 +08:00
|
|
|
|
* @param bool $isEncrypted 验证码是否已加密
|
2025-03-16 17:43:30 +08:00
|
|
|
|
* @return array
|
|
|
|
|
|
* @throws \Exception
|
|
|
|
|
|
*/
|
2025-03-27 15:28:38 +08:00
|
|
|
|
public function mobileLogin($account, $code, $ip, $isEncrypted = false)
|
2025-03-16 17:43:30 +08:00
|
|
|
|
{
|
|
|
|
|
|
// 验证验证码
|
2025-03-27 15:28:38 +08:00
|
|
|
|
if (!$this->smsService->verifyCode($account, $code, 'login', $isEncrypted)) {
|
|
|
|
|
|
Log::info('验证码验证失败', ['account' => $account, 'ip' => $ip, 'is_encrypted' => $isEncrypted]);
|
2025-04-30 14:52:51 +08:00
|
|
|
|
throw new \Exception('验证码错误或已过期', 404);
|
2025-03-16 17:43:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取用户信息
|
2025-03-27 15:28:38 +08:00
|
|
|
|
$user = User::getUserByMobile($account);
|
2025-03-16 17:43:30 +08:00
|
|
|
|
if (empty($user)) {
|
2025-03-27 15:28:38 +08:00
|
|
|
|
Log::info('用户不存在', ['account' => $account, 'ip' => $ip]);
|
2025-04-30 14:52:51 +08:00
|
|
|
|
throw new \Exception('用户不存在', 404);
|
2025-03-16 17:43:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 生成JWT令牌
|
|
|
|
|
|
$token = JwtUtil::createToken($user, self::TOKEN_EXPIRE);
|
|
|
|
|
|
$expireTime = time() + self::TOKEN_EXPIRE;
|
|
|
|
|
|
|
|
|
|
|
|
// 记录登录成功
|
2025-03-27 15:28:38 +08:00
|
|
|
|
Log::info('手机号登录成功', ['account' => $account, 'ip' => $ip]);
|
2025-03-16 17:43:30 +08:00
|
|
|
|
|
|
|
|
|
|
return [
|
|
|
|
|
|
'token' => $token,
|
|
|
|
|
|
'token_expired' => $expireTime,
|
|
|
|
|
|
'member' => $user
|
|
|
|
|
|
];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 发送登录验证码
|
2025-04-30 14:52:51 +08:00
|
|
|
|
*
|
2025-03-27 15:28:38 +08:00
|
|
|
|
* @param string $account 手机号
|
2025-03-16 17:43:30 +08:00
|
|
|
|
* @param string $type 验证码类型
|
|
|
|
|
|
* @return array
|
|
|
|
|
|
* @throws \Exception
|
|
|
|
|
|
*/
|
2025-03-27 15:28:38 +08:00
|
|
|
|
public function sendLoginCode($account, $type)
|
2025-03-16 17:43:30 +08:00
|
|
|
|
{
|
2025-03-27 15:28:38 +08:00
|
|
|
|
return $this->smsService->sendCode($account, $type);
|
2025-03-16 17:43:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取用户信息
|
2025-04-30 14:52:51 +08:00
|
|
|
|
*
|
2025-03-16 17:43:30 +08:00
|
|
|
|
* @param array $userInfo JWT中的用户信息
|
|
|
|
|
|
* @return array
|
|
|
|
|
|
* @throws \Exception
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function getUserInfo($userInfo)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (empty($userInfo)) {
|
|
|
|
|
|
throw new \Exception('获取用户信息失败');
|
|
|
|
|
|
}
|
2025-04-30 14:52:51 +08:00
|
|
|
|
|
2025-03-16 17:43:30 +08:00
|
|
|
|
// 移除不需要返回的字段
|
|
|
|
|
|
unset($userInfo['exp']);
|
|
|
|
|
|
unset($userInfo['iat']);
|
2025-04-30 14:52:51 +08:00
|
|
|
|
|
2025-03-16 17:43:30 +08:00
|
|
|
|
return $userInfo;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 刷新令牌
|
2025-04-30 14:52:51 +08:00
|
|
|
|
*
|
2025-03-16 17:43:30 +08:00
|
|
|
|
* @param array $userInfo JWT中的用户信息
|
|
|
|
|
|
* @return array
|
|
|
|
|
|
* @throws \Exception
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function refreshToken($userInfo)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (empty($userInfo)) {
|
|
|
|
|
|
throw new \Exception('刷新令牌失败');
|
|
|
|
|
|
}
|
2025-04-30 14:52:51 +08:00
|
|
|
|
|
2025-03-16 17:43:30 +08:00
|
|
|
|
// 移除过期时间信息
|
|
|
|
|
|
unset($userInfo['exp']);
|
|
|
|
|
|
unset($userInfo['iat']);
|
2025-04-30 14:52:51 +08:00
|
|
|
|
|
2025-03-16 17:43:30 +08:00
|
|
|
|
// 生成新令牌
|
|
|
|
|
|
$token = JwtUtil::createToken($userInfo, self::TOKEN_EXPIRE);
|
|
|
|
|
|
$expireTime = time() + self::TOKEN_EXPIRE;
|
2025-04-30 14:52:51 +08:00
|
|
|
|
|
2025-03-16 17:43:30 +08:00
|
|
|
|
return [
|
|
|
|
|
|
'token' => $token,
|
|
|
|
|
|
'token_expired' => $expireTime
|
|
|
|
|
|
];
|
|
|
|
|
|
}
|
2025-03-24 14:59:19 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取系统授权信息,使用缓存存储10分钟
|
2025-04-30 14:52:51 +08:00
|
|
|
|
*
|
2025-03-24 14:59:19 +08:00
|
|
|
|
* @return string
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static function getSystemAuthorization()
|
|
|
|
|
|
{
|
|
|
|
|
|
// 定义缓存键名
|
|
|
|
|
|
$cacheKey = 'system_authorization_token';
|
2025-04-30 14:52:51 +08:00
|
|
|
|
|
2025-03-24 14:59:19 +08:00
|
|
|
|
// 尝试从缓存获取授权信息
|
|
|
|
|
|
$authorization = Cache::get($cacheKey);
|
2025-04-23 18:13:01 +08:00
|
|
|
|
//$authorization = 'mYpVVhPY7PxctvYw1pn1VCTS2ck0yZG8q11gAiJrRN_D3q7KXXBPAfXoAmqs7kKHeaAx-h4GB7DiqVIQJ09HiXVhaQT6PtgLX3w8YV16erThC-lG1fyJB4DJxu-QxA3Q8ogSs1WFOa8aAXD1QQUZ7Kbjkw_VMLL4lrfe0Yjaqy3DnO7aL1xGnNjjX8P5uqCAZgHKlN8NjuDEGyYvXygW1YyoK9pNpwvq-6DYKjLWdmbHvFaAybHf-hU1XyrFavZqcZYxIoVXjfJ5ASp4XxeCWqMCzwtSoz9RAvwLAlNxGweowtuyX9389ZaXI-zbqb2T0S8llg';
|
2025-04-30 14:52:51 +08:00
|
|
|
|
// 如果缓存中没有或已过期,则重新获取
|
2025-03-24 14:59:19 +08:00
|
|
|
|
if (empty($authorization)) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
// 从环境变量中获取API用户名和密码
|
|
|
|
|
|
$username = Env::get('api.username', '');
|
|
|
|
|
|
$password = Env::get('api.password', '');
|
2025-04-30 14:52:51 +08:00
|
|
|
|
|
2025-03-24 14:59:19 +08:00
|
|
|
|
if (empty($username) || empty($password)) {
|
|
|
|
|
|
Log::error('缺少API用户名或密码配置');
|
|
|
|
|
|
return '';
|
|
|
|
|
|
}
|
2025-04-30 14:52:51 +08:00
|
|
|
|
|
2025-03-24 14:59:19 +08:00
|
|
|
|
// 构建登录参数
|
|
|
|
|
|
$params = [
|
|
|
|
|
|
'grant_type' => 'password',
|
|
|
|
|
|
'username' => $username,
|
|
|
|
|
|
'password' => $password
|
|
|
|
|
|
];
|
2025-04-30 14:52:51 +08:00
|
|
|
|
|
2025-03-24 14:59:19 +08:00
|
|
|
|
// 获取API基础URL
|
|
|
|
|
|
$baseUrl = Env::get('api.wechat_url', '');
|
|
|
|
|
|
if (empty($baseUrl)) {
|
|
|
|
|
|
Log::error('缺少API基础URL配置');
|
|
|
|
|
|
return '';
|
|
|
|
|
|
}
|
2025-04-30 14:52:51 +08:00
|
|
|
|
|
2025-03-24 14:59:19 +08:00
|
|
|
|
// 调用登录接口获取token
|
|
|
|
|
|
// 设置请求头
|
|
|
|
|
|
$headerData = ['client:system'];
|
|
|
|
|
|
$header = setHeader($headerData, '', 'plain');
|
2025-04-30 14:52:51 +08:00
|
|
|
|
$result = requestCurl($baseUrl . 'token', $params, 'POST', $header);
|
2025-03-24 14:59:19 +08:00
|
|
|
|
$result_array = handleApiResponse($result);
|
|
|
|
|
|
|
|
|
|
|
|
if (isset($result_array['access_token']) && !empty($result_array['access_token'])) {
|
|
|
|
|
|
$authorization = $result_array['access_token'];
|
2025-04-30 14:52:51 +08:00
|
|
|
|
|
2025-03-24 14:59:19 +08:00
|
|
|
|
// 存入缓存,有效期10分钟(600秒)
|
|
|
|
|
|
Cache::set($cacheKey, $authorization, 600);
|
|
|
|
|
|
Cache::set('system_refresh_token', $result_array['refresh_token'], 600);
|
|
|
|
|
|
|
|
|
|
|
|
Log::info('已重新获取系统授权信息并缓存');
|
|
|
|
|
|
return $authorization;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
Log::error('获取系统授权信息失败:' . ($response['message'] ?? '未知错误'));
|
|
|
|
|
|
return '';
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
|
|
Log::error('获取系统授权信息异常:' . $e->getMessage());
|
|
|
|
|
|
return '';
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-04-30 14:52:51 +08:00
|
|
|
|
|
2025-03-24 14:59:19 +08:00
|
|
|
|
return $authorization;
|
|
|
|
|
|
}
|
2025-03-16 17:43:30 +08:00
|
|
|
|
}
|