Compare commits
10 Commits
1ff1dceab7
...
9a0d43ce89
Author | SHA1 | Date | |
---|---|---|---|
9a0d43ce89 | |||
5c203379d7 | |||
779237afcd | |||
463487b939 | |||
4ec5166f50 | |||
6b2eb3cff8 | |||
fe656375b4 | |||
e6266edc07 | |||
0b6f55b429 | |||
144caadd3f |
@ -25,5 +25,5 @@ class ErrorCode extends AbstractConstants
|
||||
/**
|
||||
* @Message("Something went wrong!")
|
||||
*/
|
||||
public const COMMON_ERROR = 1000000;
|
||||
public const COMMON_ERROR = 1200000;
|
||||
}
|
||||
|
@ -13,5 +13,10 @@ class AuthErrorCode extends AbstractConstants
|
||||
/**
|
||||
* @Message("请传入微信Code")
|
||||
*/
|
||||
public const CODE_EMPTY_ERROR = 2000001;
|
||||
public const CODE_EMPTY_ERROR = 1200001;
|
||||
|
||||
/**
|
||||
* @Message("授权失败")
|
||||
*/
|
||||
public const CODE_TO_AUTH_FAIL = 1200002;
|
||||
}
|
119
app/Controller/PunchCard/User/UserController.php
Normal file
119
app/Controller/PunchCard/User/UserController.php
Normal file
@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\PunchCard\User;
|
||||
|
||||
use App\Controller\BaseController;
|
||||
use App\JsonRpc\PunchCardSystemExternalServiceInterface;
|
||||
use App\JsonRpc\UserExternalServiceInterface;
|
||||
use App\Middleware\AuthMiddleware;
|
||||
use Hyperf\Di\Annotation\Inject;
|
||||
use Hyperf\HttpServer\Annotation\Controller;
|
||||
use Hyperf\HttpServer\Annotation\GetMapping;
|
||||
use Hyperf\HttpServer\Annotation\Middleware;
|
||||
use Hyperf\HttpServer\Annotation\PostMapping;
|
||||
|
||||
#[Middleware(AuthMiddleware::class)]
|
||||
#[Controller(prefix: "kq")]
|
||||
class UserController extends BaseController
|
||||
{
|
||||
/**
|
||||
* 用户中心对外RPC服务
|
||||
*
|
||||
* @var UserExternalServiceInterface
|
||||
*/
|
||||
#[Inject]
|
||||
protected UserExternalServiceInterface $userExternalService;
|
||||
|
||||
/**
|
||||
* 考勤系统设置对外RPC服务
|
||||
*
|
||||
* @var PunchCardSystemExternalServiceInterface
|
||||
*/
|
||||
#[Inject]
|
||||
protected PunchCardSystemExternalServiceInterface $punchCardSystemExternalService;
|
||||
|
||||
/**
|
||||
* 获取个人资料
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
#[GetMapping(path: "user/information")]
|
||||
public function information() : array
|
||||
{
|
||||
$user = $this->request->getAttribute('AuthUser');
|
||||
return $this->getServiceResult($this->userExternalService->getUserInfo($user['openid'], [
|
||||
'user_name',
|
||||
'user_phone',
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存个人资料
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
#[PostMapping(path: "user/save_information")]
|
||||
public function saveInformation() : void
|
||||
{
|
||||
$phone = $this->request->input('phone', '');
|
||||
// TODO 逻辑完善
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取问题反馈类型列表
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
#[GetMapping(path: "user/feedback_type")]
|
||||
public function getFeedbackTypeList() : array
|
||||
{
|
||||
return $this->getServiceResult($this->punchCardSystemExternalService->getFeedbackTypeList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存问题反馈
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
#[PostMapping(path: "user/save_feedback")]
|
||||
public function saveFeedback() : array
|
||||
{
|
||||
$user = $this->request->getAttribute('AuthUser');
|
||||
return $this->getServiceResult($this->punchCardSystemExternalService->saveFeedback($this->request, $user['user_id']));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取紧急联系人关系列表
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
#[GetMapping(path: "user/emergency_contact_kinship")]
|
||||
public function getEmergencyContactKinshipList() : array
|
||||
{
|
||||
return $this->getServiceResult($this->userExternalService->getEmergencyContactKinshipList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存紧急联系人
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
#[PostMapping(path: "user/add_emergency_contact")]
|
||||
public function addEmergencyContact() : array
|
||||
{
|
||||
return $this->getServiceResult($this->userExternalService->addEmergencyContact($this->request));
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试打印JWT认证信息
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
#[GetMapping(path: "user/test")]
|
||||
public function test() : array
|
||||
{
|
||||
return $this->request->getAttribute('AuthUser');
|
||||
}
|
||||
}
|
@ -2,24 +2,33 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\PunchCard\Wechat;
|
||||
namespace App\Controller\PunchCard\User;
|
||||
|
||||
use App\Controller\BaseController;
|
||||
use App\Exception\BusinessException;
|
||||
use app\Constants\Wechat\AuthErrorCode;
|
||||
use App\Service\Wechat\AuthService;
|
||||
use App\Middleware\AuthMiddleware;
|
||||
use App\Service\User\WechatAuthService;
|
||||
use Hyperf\Di\Annotation\Inject;
|
||||
use Hyperf\HttpServer\Annotation\Controller;
|
||||
use Hyperf\HttpServer\Annotation\GetMapping;
|
||||
use Hyperf\HttpServer\Annotation\Middleware;
|
||||
use Hyperf\HttpServer\Annotation\RequestMapping;
|
||||
use Phper666\JWTAuth\Middleware\JWTAuthDefaultSceneMiddleware;
|
||||
|
||||
/**
|
||||
* 微信授权处理控制器
|
||||
*/
|
||||
#[Controller(prefix: "kq")]
|
||||
class AuthController extends BaseController
|
||||
class WechatAuthController extends BaseController
|
||||
{
|
||||
/**
|
||||
* 微信授权服务
|
||||
*
|
||||
* @var WechatAuthService
|
||||
*/
|
||||
#[Inject]
|
||||
protected AuthService $service;
|
||||
protected WechatAuthService $service;
|
||||
|
||||
/**
|
||||
* 通过微信授权新建用户
|
||||
@ -37,4 +46,16 @@ class AuthController extends BaseController
|
||||
|
||||
return $this->service->codeToOpenID($code);
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新token
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
#[Middleware(AuthMiddleware::class)]
|
||||
#[GetMapping(path: "auth/refresh_token")]
|
||||
public function refreshToken() : array
|
||||
{
|
||||
return $this->service->refreshToken();
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@ namespace App\Controller;
|
||||
|
||||
use App\Exception\BusinessException;
|
||||
use App\JsonRpc\UserExternalServiceInterface;
|
||||
use App\Service\User\WechatAuthService;
|
||||
use Hyperf\Di\Annotation\Inject;
|
||||
use Hyperf\HttpServer\Annotation\AutoController;
|
||||
use Hyperf\Utils\Collection;
|
||||
@ -28,7 +29,7 @@ class TestController extends BaseController
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function index()
|
||||
public function index() : array
|
||||
{
|
||||
$data['user_id'] = 'test';
|
||||
return $data;
|
||||
@ -39,7 +40,7 @@ class TestController extends BaseController
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function empty()
|
||||
public function empty() : void
|
||||
{}
|
||||
|
||||
/**
|
||||
@ -47,7 +48,7 @@ class TestController extends BaseController
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function error()
|
||||
public function error(): mixed
|
||||
{
|
||||
throw new BusinessException(500, 'error');
|
||||
}
|
||||
@ -57,7 +58,7 @@ class TestController extends BaseController
|
||||
*
|
||||
* @return Paginator
|
||||
*/
|
||||
public function page()
|
||||
public function page() : Paginator
|
||||
{
|
||||
$currentPage = (int) $this->request->input('page', 1);
|
||||
$perPage = (int) $this->request->input('per_page', 2);
|
||||
@ -76,12 +77,20 @@ class TestController extends BaseController
|
||||
}
|
||||
|
||||
/**
|
||||
* RPC调用示例
|
||||
* 获取token(用于测试)
|
||||
*
|
||||
* @param WechatAuthService $wechatAuthService
|
||||
* @return array
|
||||
*/
|
||||
public function user_info()
|
||||
public function token(WechatAuthService $wechatAuthService) : array
|
||||
{
|
||||
return $this->getServiceResult($this->userService->getUserInfo());
|
||||
$openid = $this->request->input('openid', '1111111');
|
||||
$user = $this->getServiceResult($this->userService->getUserInfo($openid, ['user_id', 'user_nickname']));
|
||||
|
||||
if (!empty($user)) {
|
||||
return $wechatAuthService->getToken($user['user_id'], $user['user_nickname'], $openid);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
@ -11,6 +11,8 @@ declare(strict_types=1);
|
||||
*/
|
||||
namespace App\Exception\Handler;
|
||||
|
||||
use App\Constants\ErrorCode;
|
||||
use App\Helper\Result;
|
||||
use Hyperf\Contract\StdoutLoggerInterface;
|
||||
use Hyperf\ExceptionHandler\ExceptionHandler;
|
||||
use Hyperf\HttpMessage\Stream\SwooleStream;
|
||||
@ -25,9 +27,13 @@ class AppExceptionHandler extends ExceptionHandler
|
||||
|
||||
public function handle(Throwable $throwable, ResponseInterface $response)
|
||||
{
|
||||
$this->logger->error(sprintf('%s[%s] in %s', $throwable->getMessage(), $throwable->getLine(), $throwable->getFile()));
|
||||
$this->logger->error($throwable->getTraceAsString());
|
||||
return $response->withHeader('Server', 'Hyperf')->withStatus(500)->withBody(new SwooleStream('Internal Server Error.'));
|
||||
$message = $throwable->getMessage();
|
||||
$error = explode('|', $message, 2);
|
||||
$code = $error[1] ?? $throwable->getCode() ?: ErrorCode::COMMON_ERROR;
|
||||
$data = Result::error($code, $error[0]);
|
||||
$responseStr = json_encode($data, JSON_UNESCAPED_UNICODE);
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json')->withBody(new SwooleStream($responseStr));
|
||||
}
|
||||
|
||||
public function isValid(Throwable $throwable): bool
|
||||
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Helper;
|
||||
|
||||
use App\Exception\BusinessException;
|
||||
use GuzzleHttp\Client;
|
||||
use Hyperf\Guzzle\HandlerStackFactory;
|
||||
|
||||
@ -35,7 +36,6 @@ class Curl
|
||||
* @param string $url
|
||||
* @param array $headers
|
||||
* @return array
|
||||
* @throws \GuzzleHttp\Exception\GuzzleException
|
||||
*/
|
||||
public static function get(string $url, array $headers = []) : array
|
||||
{
|
||||
@ -46,7 +46,11 @@ class Curl
|
||||
$options['headers'] = $headers;
|
||||
}
|
||||
|
||||
try {
|
||||
$response = $client->get($url, $options);
|
||||
} catch (\Throwable $throwable) {
|
||||
throw new BusinessException($throwable->getCode(), $throwable->getMessage());
|
||||
}
|
||||
|
||||
if ($response->getStatusCode() === 200) {
|
||||
return json_decode($response->getBody()->getContents(), true);
|
||||
@ -62,7 +66,6 @@ class Curl
|
||||
* @param array $data
|
||||
* @param array $headers
|
||||
* @return array
|
||||
* @throws \GuzzleHttp\Exception\GuzzleException
|
||||
*/
|
||||
public static function post(string $url, array $data = [], array $headers = []) : array
|
||||
{
|
||||
@ -73,7 +76,11 @@ class Curl
|
||||
$options['headers'] = $headers;
|
||||
}
|
||||
|
||||
try {
|
||||
$response = $client->post($url, $options);
|
||||
} catch (\Throwable $throwable) {
|
||||
throw new BusinessException($throwable->getCode(), $throwable->getMessage());
|
||||
}
|
||||
|
||||
if ($response->getStatusCode() === 200) {
|
||||
return json_decode($response->getBody()->getContents(), true);
|
||||
|
36
app/JsonRpc/PunchCardSystemExternalServiceConsumer.php
Normal file
36
app/JsonRpc/PunchCardSystemExternalServiceConsumer.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace App\JsonRpc;
|
||||
|
||||
use Hyperf\RpcClient\AbstractServiceClient;
|
||||
use Hyperf\HttpServer\Contract\RequestInterface;
|
||||
|
||||
class PunchCardSystemExternalServiceConsumer extends AbstractServiceClient implements PunchCardSystemExternalServiceInterface
|
||||
{
|
||||
/**
|
||||
* 定义对应服务提供者的服务名称
|
||||
* @var string
|
||||
*/
|
||||
protected $serviceName = 'PunchCardSystemExternalService';
|
||||
|
||||
/**
|
||||
* 获取问题反馈类型列表
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getFeedbackTypeList() : array
|
||||
{
|
||||
return $this->__request(__FUNCTION__, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存问题反馈
|
||||
*
|
||||
* @param RequestInterface $request
|
||||
* @return array
|
||||
*/
|
||||
public function saveFeedback(RequestInterface $request) : array
|
||||
{
|
||||
return $this->__request(__FUNCTION__, [...$request->all(), ...['user_id' => $request->getAttribute('AuthUser')['user_id']]]);
|
||||
}
|
||||
}
|
23
app/JsonRpc/PunchCardSystemExternalServiceInterface.php
Normal file
23
app/JsonRpc/PunchCardSystemExternalServiceInterface.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\JsonRpc;
|
||||
|
||||
use Hyperf\HttpServer\Contract\RequestInterface;
|
||||
|
||||
interface PunchCardSystemExternalServiceInterface
|
||||
{
|
||||
/**
|
||||
* 获取问题反馈类型列表
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getFeedbackTypeList() : array;
|
||||
|
||||
/**
|
||||
* 保存问题反馈
|
||||
*
|
||||
* @param RequestInterface $request
|
||||
* @return array
|
||||
*/
|
||||
public function saveFeedback(RequestInterface $request) : array;
|
||||
}
|
59
app/JsonRpc/UserExternalServiceConsumer.php
Normal file
59
app/JsonRpc/UserExternalServiceConsumer.php
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace App\JsonRpc;
|
||||
|
||||
use Hyperf\RpcClient\AbstractServiceClient;
|
||||
use Hyperf\HttpServer\Contract\RequestInterface;
|
||||
|
||||
class UserExternalServiceConsumer extends AbstractServiceClient implements UserExternalServiceInterface
|
||||
{
|
||||
/**
|
||||
* 定义对应服务提供者的服务名称
|
||||
* @var string
|
||||
*/
|
||||
protected $serviceName = 'UserExternalService';
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*
|
||||
* @param string $openid
|
||||
* @param array $field
|
||||
* @return array
|
||||
*/
|
||||
public function getUserInfo(string $openid, array $field = []) : array
|
||||
{
|
||||
return $this->__request(__FUNCTION__, compact('openid', 'field'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过微信授权新建用户
|
||||
*
|
||||
* @param string $openid
|
||||
* @return array
|
||||
*/
|
||||
public function wechatNewUser(string $openid) : array
|
||||
{
|
||||
return $this->__request(__FUNCTION__, compact('openid'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取紧急联系人关系列表
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getEmergencyContactKinshipList() : array
|
||||
{
|
||||
return $this->__request(__FUNCTION__, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存紧急联系人
|
||||
*
|
||||
* @param RequestInterface $request
|
||||
* @return array
|
||||
*/
|
||||
public function addEmergencyContact(RequestInterface $request) : array
|
||||
{
|
||||
return $this->__request(__FUNCTION__, $request->all());
|
||||
}
|
||||
}
|
@ -2,15 +2,18 @@
|
||||
|
||||
namespace App\JsonRpc;
|
||||
|
||||
use Hyperf\HttpServer\Contract\RequestInterface;
|
||||
|
||||
interface UserExternalServiceInterface
|
||||
{
|
||||
/**
|
||||
* 获取用户信息
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $openid
|
||||
* @param array $field
|
||||
* @return array
|
||||
*/
|
||||
public function getUserInfo(string $name = 'test') : array;
|
||||
public function getUserInfo(string $openid, array $field = []) : array;
|
||||
|
||||
/**
|
||||
* 通过微信授权新建用户
|
||||
@ -19,4 +22,19 @@ interface UserExternalServiceInterface
|
||||
* @return array
|
||||
*/
|
||||
public function wechatNewUser(string $openid) : array;
|
||||
|
||||
/**
|
||||
* 获取紧急联系人关系列表
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getEmergencyContactKinshipList() : array;
|
||||
|
||||
/**
|
||||
* 保存紧急联系人
|
||||
*
|
||||
* @param RequestInterface $request
|
||||
* @return array
|
||||
*/
|
||||
public function addEmergencyContact(RequestInterface $request) : array;
|
||||
}
|
53
app/Middleware/AuthMiddleware.php
Normal file
53
app/Middleware/AuthMiddleware.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Middleware;
|
||||
|
||||
use App\Constants\ErrorCode;
|
||||
use Hyperf\Context\Context;
|
||||
use Hyperf\HttpServer\Contract\ResponseInterface as HttpResponse;
|
||||
use Phper666\JWTAuth\Exception\JWTException;
|
||||
use Phper666\JWTAuth\Util\JWTUtil;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\MiddlewareInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
use Phper666\JWTAuth\JWT;
|
||||
use Phper666\JWTAuth\Exception\TokenValidException;
|
||||
|
||||
/**
|
||||
* jwt token 校验的中间件,校验场景是否一致
|
||||
*/
|
||||
class AuthMiddleware implements MiddlewareInterface
|
||||
{
|
||||
public function __construct(protected HttpResponse $response, protected JWT $jwt)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ServerRequestInterface $request
|
||||
* @param RequestHandlerInterface $handler
|
||||
* @return ResponseInterface
|
||||
* @throws \Psr\SimpleCache\InvalidArgumentException
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
|
||||
{
|
||||
$token = $request->getHeaderLine('Authorization') ?? '';
|
||||
if ($token === "") {
|
||||
throw new JWTException('Missing token', ErrorCode::COMMON_ERROR);
|
||||
}
|
||||
|
||||
$token = JWTUtil::handleToken($token);
|
||||
if ($token !== false && $this->jwt->verifyTokenAndScene('default', $token)) {
|
||||
// 封装认证用户信息
|
||||
$request = $request->withAttribute('AuthUser', JWTUtil::getParserData($request));
|
||||
Context::set(ServerRequestInterface::class, $request);
|
||||
|
||||
return $handler->handle($request);
|
||||
}
|
||||
|
||||
throw new TokenValidException('Token authentication does not pass', ErrorCode::COMMON_ERROR);
|
||||
}
|
||||
}
|
133
app/Service/User/WechatAuthService.php
Normal file
133
app/Service/User/WechatAuthService.php
Normal file
@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
namespace App\Service\User;
|
||||
|
||||
use App\Constants\Wechat\AuthErrorCode;
|
||||
use App\Exception\BusinessException;
|
||||
use App\Helper\Curl;
|
||||
use App\JsonRpc\UserExternalServiceInterface;
|
||||
use Hyperf\Config\Annotation\Value;
|
||||
use Hyperf\Di\Annotation\Inject;
|
||||
use Phper666\JWTAuth\JWT;
|
||||
use Psr\SimpleCache\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* 微信授权处理服务层
|
||||
*/
|
||||
class WechatAuthService
|
||||
{
|
||||
/**
|
||||
* 考勤系统小程序APPID
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
#[Value("app.wechat_punch_card_appid")]
|
||||
protected string $appid;
|
||||
|
||||
/**
|
||||
* 考勤系统小程序APPSecret
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
#[Value("app.wechat_punch_card_secret")]
|
||||
protected string $secret;
|
||||
|
||||
/**
|
||||
* 用户中心对外RPC服务
|
||||
*
|
||||
* @var UserExternalServiceInterface
|
||||
*/
|
||||
#[Inject]
|
||||
protected UserExternalServiceInterface $userExternalService;
|
||||
|
||||
/**
|
||||
* JWT认证组件
|
||||
*
|
||||
* @var JWT
|
||||
*/
|
||||
#[Inject]
|
||||
protected JWT $jwt;
|
||||
|
||||
/**
|
||||
* 微信通过code获取session信息请求地址
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected string $wechat_auth_url = 'https://api.weixin.qq.com/sns/jscode2session';
|
||||
|
||||
/**
|
||||
* 通过微信授权新建用户
|
||||
*
|
||||
* @param string $code
|
||||
* @return array
|
||||
*/
|
||||
public function codeToOpenID(string $code) : array
|
||||
{
|
||||
$url = $this->wechat_auth_url . '?' . http_build_query([
|
||||
'appid' => $this->appid,
|
||||
'secret' => $this->secret,
|
||||
'js_code' => $code,
|
||||
'grant_type' => 'authorization_code'
|
||||
]);
|
||||
|
||||
$result = Curl::get($url);
|
||||
$res = $this->userExternalService->wechatNewUser($result['data']['openid']);
|
||||
|
||||
if (!$res['code'] !== 200) {
|
||||
throw new BusinessException($res['code'], $res['msg']);
|
||||
}
|
||||
|
||||
if (empty($res['data']['user'])) {
|
||||
throw new BusinessException(AuthErrorCode::CODE_TO_AUTH_FAIL);
|
||||
}
|
||||
|
||||
return $this->getToken($res['data']['user']['user_id'], $res['data']['user']['user_nickname'], $res['data']['user']['user_openid']);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取JWT认证token
|
||||
*
|
||||
* @param int $user_id
|
||||
* @param string $nickname
|
||||
* @param string $openid
|
||||
* @return array
|
||||
*/
|
||||
public function getToken(int $user_id, string $nickname, string $openid)
|
||||
{
|
||||
try {
|
||||
$token = $this->jwt->getToken('default', [
|
||||
'user_id' => $user_id,
|
||||
'nickname' => $nickname,
|
||||
'openid' => $openid
|
||||
]);
|
||||
} catch (InvalidArgumentException) {
|
||||
// TODO 记录日志
|
||||
throw new BusinessException(AuthErrorCode::CODE_TO_AUTH_FAIL);
|
||||
}
|
||||
|
||||
return [
|
||||
'token' => $token->toString(),
|
||||
'exp' => $this->jwt->getTTL($token->toString())
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新token
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function refreshToken() : array
|
||||
{
|
||||
try {
|
||||
$token = $this->jwt->refreshToken();
|
||||
} catch (InvalidArgumentException) {
|
||||
// TODO 记录日志
|
||||
throw new BusinessException(AuthErrorCode::CODE_TO_AUTH_FAIL);
|
||||
}
|
||||
|
||||
return [
|
||||
'token' => $token->toString(),
|
||||
'exp' => $this->jwt->getTTL($token->toString())
|
||||
];
|
||||
}
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Service\Wechat;
|
||||
|
||||
use App\Exception\BusinessException;
|
||||
use App\Helper\Curl;
|
||||
use App\JsonRpc\UserExternalServiceInterface;
|
||||
use Hyperf\Config\Annotation\Value;
|
||||
use Hyperf\Di\Annotation\Inject;
|
||||
|
||||
/**
|
||||
* 微信授权处理服务层
|
||||
*/
|
||||
class AuthService
|
||||
{
|
||||
/**
|
||||
* 考勤系统小程序APPID
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
#[Value("app.wechat_punch_card_appid")]
|
||||
protected string $appid;
|
||||
|
||||
/**
|
||||
* 考勤系统小程序APPSecret
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
#[Value("app.wechat_punch_card_secret")]
|
||||
protected string $secret;
|
||||
|
||||
/**
|
||||
* 用户中心对外RPC服务
|
||||
*
|
||||
* @var UserExternalServiceInterface
|
||||
*/
|
||||
#[Inject]
|
||||
protected UserExternalServiceInterface $userExternalService;
|
||||
|
||||
/**
|
||||
* 微信通过code获取session信息请求地址
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected string $wechat_auth_url = 'https://api.weixin.qq.com/sns/jscode2session';
|
||||
|
||||
/**
|
||||
* 通过微信授权新建用户
|
||||
*
|
||||
* @param string $code
|
||||
* @return array
|
||||
*/
|
||||
public function codeToOpenID(string $code) : array
|
||||
{
|
||||
$url = $this->wechat_auth_url . '?' . http_build_query([
|
||||
'appid' => $this->appid,
|
||||
'secret' => $this->secret,
|
||||
'js_code' => $code,
|
||||
'grant_type' => 'authorization_code'
|
||||
]);
|
||||
|
||||
$result = Curl::get($url);
|
||||
$res = $this->userExternalService->wechatNewUser($result['data']['openid']);
|
||||
|
||||
if (!$res['code'] !== 200) {
|
||||
throw new BusinessException($res['code'], $res['msg']);
|
||||
}
|
||||
|
||||
return ['openid' => $result['data']['openid']];
|
||||
}
|
||||
}
|
@ -34,7 +34,8 @@
|
||||
"hyperf/rpc-client": "~2.2.0",
|
||||
"hyperf/rpc-server": "~2.2.0",
|
||||
"hyperf/service-governance-consul": "~2.2.0",
|
||||
"hyperf/validation": "^2.2"
|
||||
"hyperf/validation": "^2.2",
|
||||
"phper666/jwt-auth": "~4.0.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^3.0",
|
||||
|
184
composer.lock
generated
184
composer.lock
generated
@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "7cc40bd39d6d590a4e06bfb1d56c0abb",
|
||||
"content-hash": "7f8915491bc01099466689096453ac63",
|
||||
"packages": [
|
||||
{
|
||||
"name": "doctrine/annotations",
|
||||
@ -2515,6 +2515,101 @@
|
||||
],
|
||||
"time": "2022-10-10T19:10:24+00:00"
|
||||
},
|
||||
{
|
||||
"name": "lcobucci/clock",
|
||||
"version": "2.2.0",
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://mirrors.cloud.tencent.com/repository/composer/lcobucci/clock/2.2.0/lcobucci-clock-2.2.0.zip",
|
||||
"reference": "fb533e093fd61321bfcbac08b131ce805fe183d3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^8.0",
|
||||
"stella-maris/clock": "^0.1.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"infection/infection": "^0.26",
|
||||
"lcobucci/coding-standard": "^8.0",
|
||||
"phpstan/extension-installer": "^1.1",
|
||||
"phpstan/phpstan": "^0.12",
|
||||
"phpstan/phpstan-deprecation-rules": "^0.12",
|
||||
"phpstan/phpstan-phpunit": "^0.12",
|
||||
"phpstan/phpstan-strict-rules": "^0.12",
|
||||
"phpunit/phpunit": "^9.5"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Lcobucci\\Clock\\": "src"
|
||||
}
|
||||
},
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Luís Cobucci",
|
||||
"email": "lcobucci@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Yet another clock abstraction",
|
||||
"time": "2022-04-19T19:34:17+00:00"
|
||||
},
|
||||
{
|
||||
"name": "lcobucci/jwt",
|
||||
"version": "4.1.5",
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://mirrors.cloud.tencent.com/repository/composer/lcobucci/jwt/4.1.5/lcobucci-jwt-4.1.5.zip",
|
||||
"reference": "fe2d89f2eaa7087af4aa166c6f480ef04e000582",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-hash": "*",
|
||||
"ext-json": "*",
|
||||
"ext-mbstring": "*",
|
||||
"ext-openssl": "*",
|
||||
"ext-sodium": "*",
|
||||
"lcobucci/clock": "^2.0",
|
||||
"php": "^7.4 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"infection/infection": "^0.21",
|
||||
"lcobucci/coding-standard": "^6.0",
|
||||
"mikey179/vfsstream": "^1.6.7",
|
||||
"phpbench/phpbench": "^1.0",
|
||||
"phpstan/extension-installer": "^1.0",
|
||||
"phpstan/phpstan": "^0.12",
|
||||
"phpstan/phpstan-deprecation-rules": "^0.12",
|
||||
"phpstan/phpstan-phpunit": "^0.12",
|
||||
"phpstan/phpstan-strict-rules": "^0.12",
|
||||
"phpunit/php-invoker": "^3.1",
|
||||
"phpunit/phpunit": "^9.5"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Lcobucci\\JWT\\": "src"
|
||||
}
|
||||
},
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Luís Cobucci",
|
||||
"email": "lcobucci@gmail.com",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "A simple library to work with JSON Web Token and JSON Web Signature",
|
||||
"keywords": [
|
||||
"JWS",
|
||||
"jwt"
|
||||
],
|
||||
"time": "2021-09-28T19:34:56+00:00"
|
||||
},
|
||||
{
|
||||
"name": "markrogoyski/math-php",
|
||||
"version": "v2.6.0",
|
||||
@ -3020,6 +3115,56 @@
|
||||
],
|
||||
"time": "2020-10-12T12:39:22+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phper666/jwt-auth",
|
||||
"version": "v4.0.7",
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://mirrors.cloud.tencent.com/repository/composer/phper666/jwt-auth/v4.0.7/phper666-jwt-auth-v4.0.7.zip",
|
||||
"reference": "c42e1ef968d300e7e74e449e5e93cda7d22de33f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-swoole": ">=4.4",
|
||||
"lcobucci/jwt": "4.1.5",
|
||||
"nesbot/carbon": "^1.0 || ^2.0",
|
||||
"php": ">=7.4"
|
||||
},
|
||||
"suggest": {
|
||||
"hyperf/cache": "required hyperf/cache ~2.2.0",
|
||||
"hyperf/command": "required hyperf/command ~2.2.0",
|
||||
"hyperf/config": "required hyperf/config ~2.2.0",
|
||||
"hyperf/di": "required hyperf/di ~2.2.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"hyperf": {
|
||||
"config": "Phper666\\JWTAuth\\ConfigProvider"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Phper666\\JWTAuth\\": "src/"
|
||||
}
|
||||
},
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Li Yuzhao",
|
||||
"email": "562405704@qq.com",
|
||||
"homepage": "https://github.com/phper666/jwt-auth",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "jwt-auth Component",
|
||||
"keywords": [
|
||||
"hyperf",
|
||||
"php"
|
||||
],
|
||||
"time": "2022-04-19T11:54:50+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpoption/phpoption",
|
||||
"version": "1.9.0",
|
||||
@ -3628,6 +3773,43 @@
|
||||
"description": "A polyfill for getallheaders.",
|
||||
"time": "2019-03-08T08:55:37+00:00"
|
||||
},
|
||||
{
|
||||
"name": "stella-maris/clock",
|
||||
"version": "0.1.6",
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://mirrors.cloud.tencent.com/repository/composer/stella-maris/clock/0.1.6/stella-maris-clock-0.1.6.zip",
|
||||
"reference": "a94228dac03c9a8411198ce8c8dacbbe99c930c3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.0|^8.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"StellaMaris\\Clock\\": "src"
|
||||
}
|
||||
},
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Andreas Heigl",
|
||||
"role": "Maintainer"
|
||||
}
|
||||
],
|
||||
"description": "A pre-release of the proposed PSR-20 Clock-Interface",
|
||||
"homepage": "https://gitlab.com/stella-maris/clock",
|
||||
"keywords": [
|
||||
"clock",
|
||||
"datetime",
|
||||
"point in time",
|
||||
"psr20"
|
||||
],
|
||||
"time": "2022-09-27T15:03:11+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v5.4.11",
|
||||
|
@ -14,4 +14,6 @@ use Hyperf\JsonRpc\JsonRpcTransporter;
|
||||
|
||||
return [
|
||||
JsonRpcTransporter::class => JsonRpcPoolTransporter::class,
|
||||
App\JsonRpc\UserExternalServiceInterface::class => App\JsonRpc\UserExternalServiceConsumer::class,
|
||||
App\JsonRpc\PunchCardSystemExternalServiceInterface::class => App\JsonRpc\PunchCardSystemExternalServiceConsumer::class,
|
||||
];
|
||||
|
93
config/autoload/jwt.php
Normal file
93
config/autoload/jwt.php
Normal file
@ -0,0 +1,93 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
return [
|
||||
/**
|
||||
* 不需要检查的路由,如果使用jwt提供的默认中间件,可以对某些不用做检验的路由进行配置,例如登录等
|
||||
* 具体的逻辑可以效仿JWT提供的默认中间件
|
||||
* [
|
||||
* ["GET", "/index/test"],
|
||||
* ["**", "/test"]
|
||||
* ]
|
||||
*
|
||||
* 第一个填写请求方法('**'代表支持所有的请求方法),第二个填写路由路径('/**'代表支持所有的路径)
|
||||
* 如果数组中存在["**", "/**"],则默认所有的请求路由都不做jwt token的校验,直接放行,如果no_check_route为一个空数组,则
|
||||
* 所有的请求路由都需要做jwt token校验
|
||||
* 路由路径支持正则的写法
|
||||
* 正则写法:["**", "/api/{name:.+}"] 支持模块化不做jwt token的校验,例如:/api/login/login
|
||||
*/
|
||||
'no_check_route' => [
|
||||
// ["**", "/**"],
|
||||
],
|
||||
|
||||
'login_type' => env('JWT_LOGIN_TYPE', 'mpop'), // 登录方式,sso为单点登录,同一个用户只能登录一个端,mpop为多点登录
|
||||
|
||||
/**
|
||||
* 单点登录自定义数据中必须存在uid的键值,这个key你可以自行定义,只要自定义数据中存在该键即可
|
||||
*/
|
||||
'sso_key' => 'user_id',
|
||||
|
||||
/**
|
||||
* 只能用于Hmac包下的加密非对称算法,其它的都会使用公私钥
|
||||
*/
|
||||
'secret' => env('JWT_SECRET', 'juzhongGroup'),
|
||||
|
||||
/**
|
||||
* JWT 权限keys
|
||||
* 对称算法: HS256, HS384 & HS512 使用 `JWT_SECRET`.
|
||||
* 非对称算法: RS256, RS384 & RS512 / ES256, ES384 & ES512 使用下面的公钥私钥,需要自己去生成.
|
||||
*/
|
||||
'keys' => [
|
||||
'public' => env('JWT_PUBLIC_KEY'), // 公钥,例如:'file:///path/to/public/key'
|
||||
'private' => env('JWT_PRIVATE_KEY'), // 私钥,例如:'file:///path/to/private/key'
|
||||
|
||||
/**
|
||||
* 你的私钥的密码。不需要密码可以不用设置
|
||||
*/
|
||||
'passphrase' => env('JWT_PASSPHRASE'),
|
||||
],
|
||||
|
||||
'ttl' => env('JWT_TTL', 7200), // token过期时间,单位为秒
|
||||
|
||||
/**
|
||||
* 支持的对称算法:HS256、HS384、HS512
|
||||
* 支持的非对称算法:RS256、RS384、RS512、ES256、ES384、ES512
|
||||
*/
|
||||
'alg' => env('JWT_ALG', 'HS256'), // jwt的hearder加密算法
|
||||
|
||||
/**
|
||||
* jwt使用到的缓存前缀
|
||||
* 建议使用独立的redis做缓存,这样比较好做分布式
|
||||
*/
|
||||
'cache_prefix' => 'juzhong:jwt',
|
||||
|
||||
/**
|
||||
* 是否开启黑名单,单点登录和多点登录的注销、刷新使原token失效,必须要开启黑名单,目前黑名单缓存只支持hyperf缓存驱动
|
||||
*/
|
||||
'blacklist_enabled' => env('JWT_BLACKLIST_ENABLED', true),
|
||||
|
||||
/**
|
||||
* 黑名单的宽限时间 单位为:秒,注意:如果使用单点登录,该宽限时间无效
|
||||
*/
|
||||
'blacklist_grace_period' => env('JWT_BLACKLIST_GRACE_PERIOD', 0),
|
||||
|
||||
/**
|
||||
* 签发者
|
||||
*/
|
||||
'issued_by' => 'phper666/jwt',
|
||||
|
||||
/**
|
||||
* 区分不同场景的token,比如你一个项目可能会有多种类型的应用接口鉴权,下面自行定义,我只是举例子
|
||||
* 下面的配置会自动覆盖根配置,比如application1会里面的数据会覆盖掉根数据
|
||||
* 下面的scene会和根数据合并
|
||||
* scene必须存在一个default
|
||||
* 什么叫根数据,这个配置的一维数组,除了scene都叫根配置
|
||||
*/
|
||||
'scene' => [
|
||||
'default' => [
|
||||
'secret' => 'juzhongGroup', // 非对称加密使用字符串,请使用自己加密的字符串
|
||||
'login_type' => 'mpop', // 登录方式,sso为单点登录,mpop为多点登录
|
||||
'ttl' => 7200, // token过期时间,单位为秒
|
||||
]
|
||||
]
|
||||
];
|
@ -18,7 +18,8 @@ return [
|
||||
$consumers = [];
|
||||
// 这里示例自动创建代理消费者类的配置形式,顾存在 name 和 service 两个配置项,这里的做法不是唯一的,仅说明可以通过 PHP 代码来生成配置
|
||||
$services = [
|
||||
'UserExternalService' => App\JsonRpc\UserExternalServiceInterface::class,
|
||||
'UserExternalService' => '',
|
||||
'PunchCardSystemExternalService' => ''
|
||||
];
|
||||
foreach ($services as $name => $interface) {
|
||||
$consumers[] = [
|
||||
|
Loading…
Reference in New Issue
Block a user