feat : login wx
This commit is contained in:
82
app/Aspect/Api/ApiReturnAspect.php
Normal file
82
app/Aspect/Api/ApiReturnAspect.php
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace App\Aspect\Api;
|
||||
|
||||
use App\Extend\SystemUtil;
|
||||
use App\Lib\ApiReturn;
|
||||
use App\Lib\Crypto\CryptoFactory;
|
||||
use App\Lib\Log;
|
||||
use Hyperf\Context\Context;
|
||||
use Hyperf\Di\Annotation\Aspect;
|
||||
use Hyperf\Di\Aop\AbstractAspect;
|
||||
use Hyperf\Di\Aop\ProceedingJoinPoint;
|
||||
use Hyperf\Di\Exception\Exception;
|
||||
use Hyperf\HttpServer\Contract\RequestInterface;
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
use Psr\Container\NotFoundExceptionInterface;
|
||||
|
||||
#[
|
||||
Aspect(
|
||||
classes: [
|
||||
ApiReturn::class,
|
||||
],
|
||||
annotations: []
|
||||
)
|
||||
]
|
||||
class ApiReturnAspect extends AbstractAspect
|
||||
{
|
||||
/**
|
||||
* @param RequestInterface $request
|
||||
* @param CryptoFactory $CryptoFactory
|
||||
* @param Log $log
|
||||
* @param int $userId
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly RequestInterface $request,
|
||||
private readonly CryptoFactory $CryptoFactory,
|
||||
private readonly Log $log,
|
||||
private int $userId = 0
|
||||
){}
|
||||
|
||||
/**
|
||||
* @param ProceedingJoinPoint $proceedingJoinPoint
|
||||
* @return mixed
|
||||
* @throws ContainerExceptionInterface
|
||||
* @throws NotFoundExceptionInterface
|
||||
* @throws Exception
|
||||
*/
|
||||
public function process(ProceedingJoinPoint $proceedingJoinPoint): mixed
|
||||
{
|
||||
// 在调用前进行处理
|
||||
$result = $proceedingJoinPoint->process();
|
||||
// 在调用后进行处理
|
||||
$this->userId = Context::get('user_id',0);
|
||||
|
||||
// 加密前写请求日志
|
||||
$this->writeResponseLog(json_encode($result));
|
||||
|
||||
//正式服加密 测试服不做处理
|
||||
if (SystemUtil::checkProEnv()) {
|
||||
$cryptoFactory = $this->CryptoFactory->cryptoClass('api', json_encode($result['data']));
|
||||
$result['data'] = $cryptoFactory->encrypt();
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求日志
|
||||
* @param string $result
|
||||
* @return void
|
||||
* @throws ContainerExceptionInterface
|
||||
* @throws NotFoundExceptionInterface
|
||||
*/
|
||||
private function writeResponseLog(string $result): void
|
||||
{
|
||||
$post = $this->request->all();
|
||||
$logParam = !$post ? '{}' : json_encode($post);
|
||||
$header = json_encode($this->request->getHeaders());
|
||||
|
||||
$this->log->requestApiLog("\napi==path:{$this->request->getPathInfo()}\nuserId:$this->userId\nrequestData:$logParam\nheader:$header\nresponseData:$result");
|
||||
}
|
||||
}
|
||||
26
app/Cache/Redis/Api/ApiRedisKey.php
Normal file
26
app/Cache/Redis/Api/ApiRedisKey.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\Cache\Redis\Api;
|
||||
|
||||
class ApiRedisKey
|
||||
{
|
||||
/**
|
||||
* 注册/登录的锁
|
||||
* @param string $mobile
|
||||
* @return string
|
||||
*/
|
||||
public static function LoginAndRegisterByMobileLock(string $mobile): string
|
||||
{
|
||||
return 'login:or:register:mobile:'.$mobile;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册/登录的锁
|
||||
* @param string $code
|
||||
* @return string
|
||||
*/
|
||||
public static function LoginAndRegisterByCodeLock(string $code): string
|
||||
{
|
||||
return 'login:or:register:code:'.$code;
|
||||
}
|
||||
}
|
||||
18
app/Constants/Common/UserCode.php
Normal file
18
app/Constants/Common/UserCode.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\Constants\Common;
|
||||
|
||||
class UserCode
|
||||
{
|
||||
/**
|
||||
* 是否绑定手机号 1=是 2=否
|
||||
*/
|
||||
const int IS_BIND_PHONE = 1;
|
||||
const int IS_NOT_BIND_PHONE = 2;
|
||||
|
||||
/**
|
||||
* 是否默认头像 1=不是 2=是
|
||||
*/
|
||||
const int IS_NOT_DEFAULT_AVATAR = 1;
|
||||
const int IS_DEFAULT_AVATAR = 2;
|
||||
}
|
||||
22
app/Controller/Api/LoginController.php
Normal file
22
app/Controller/Api/LoginController.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\Api;
|
||||
|
||||
use App\Request\Api\LoginRequest;
|
||||
use App\Service\Api\Login\LoginService;
|
||||
use Hyperf\HttpServer\Annotation\Controller;
|
||||
use Hyperf\HttpServer\Annotation\RequestMapping;
|
||||
use Hyperf\Validation\Annotation\Scene;
|
||||
|
||||
#[Controller(prefix: 'api/login')]
|
||||
class LoginController
|
||||
{
|
||||
#[RequestMapping(path: 'index',methods: 'post')]
|
||||
#[Scene(scene: 'login')]
|
||||
public function index(LoginRequest $request)
|
||||
{
|
||||
return (new LoginService)->handle();
|
||||
}
|
||||
}
|
||||
10
app/Exception/ApiException.php
Normal file
10
app/Exception/ApiException.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace App\Exception;
|
||||
|
||||
use Hyperf\Server\Exception\ServerException;
|
||||
|
||||
class ApiException extends ServerException
|
||||
{
|
||||
|
||||
}
|
||||
@@ -11,9 +11,11 @@ use Throwable;
|
||||
|
||||
class AdminExceptionHandler extends ExceptionHandler
|
||||
{
|
||||
public function __construct(protected AdminReturn $return)
|
||||
{
|
||||
}
|
||||
/**
|
||||
* 注入
|
||||
* @param AdminReturn $return
|
||||
*/
|
||||
public function __construct(private readonly AdminReturn $return) {}
|
||||
|
||||
/**
|
||||
* admin控制器异常处理
|
||||
|
||||
46
app/Exception/Handler/ApiExceptionHandler.php
Normal file
46
app/Exception/Handler/ApiExceptionHandler.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace App\Exception\Handler;
|
||||
|
||||
use App\Exception\ApiException;
|
||||
use App\Lib\ApiReturn;
|
||||
use Hyperf\ExceptionHandler\ExceptionHandler;
|
||||
use Hyperf\HttpMessage\Stream\SwooleStream;
|
||||
use Swow\Psr7\Message\ResponsePlusInterface;
|
||||
use Throwable;
|
||||
|
||||
class ApiExceptionHandler extends ExceptionHandler
|
||||
{
|
||||
/**
|
||||
* 注入
|
||||
* @param ApiReturn $return
|
||||
*/
|
||||
public function __construct(private readonly ApiReturn $return) {}
|
||||
|
||||
/**
|
||||
* @param Throwable $throwable
|
||||
* @param ResponsePlusInterface $response
|
||||
* @return ResponsePlusInterface
|
||||
*/
|
||||
public function handle(Throwable $throwable, ResponsePlusInterface $response): ResponsePlusInterface
|
||||
{
|
||||
if ($throwable instanceof ApiException) {
|
||||
$result = $this->return->error($throwable->getMessage(),$throwable->getCode());
|
||||
|
||||
// 阻止异常冒泡
|
||||
$this->stopPropagation();
|
||||
|
||||
return $response->withHeader("Content-Type", "application/json")
|
||||
->withStatus(200)
|
||||
->withBody(new SwooleStream(json_encode($result, JSON_UNESCAPED_UNICODE)));
|
||||
}
|
||||
|
||||
// 交给下一个异常处理器
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function isValid(Throwable $throwable): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
40
app/Lib/ApiReturn.php
Normal file
40
app/Lib/ApiReturn.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Lib;
|
||||
|
||||
use App\Constants\ReturnCode;
|
||||
|
||||
class ApiReturn
|
||||
{
|
||||
/**
|
||||
* 通用api返回
|
||||
* @param string $msg
|
||||
* @param array $data
|
||||
* @param int $code
|
||||
* @return array
|
||||
*/
|
||||
public function success(string $msg = 'success', array $data = [], int $code = ReturnCode::SUCCESS): array
|
||||
{
|
||||
return [
|
||||
'code' => $code,
|
||||
'msg' => $msg,
|
||||
'data' => $data
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用api返回
|
||||
* @param string $msg
|
||||
* @param array $data
|
||||
* @param int $code
|
||||
* @return array
|
||||
*/
|
||||
public function error(string $msg = 'error', int $code = ReturnCode::ERROR, array $data = []): array
|
||||
{
|
||||
return [
|
||||
'code' => $code,
|
||||
'msg' => $msg,
|
||||
'data' => $data
|
||||
];
|
||||
}
|
||||
}
|
||||
51
app/Model/User.php
Normal file
51
app/Model/User.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Model;
|
||||
|
||||
use Hyperf\DbConnection\Model\Model;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
* @property string $mobile
|
||||
* @property string $nickname
|
||||
* @property string $password
|
||||
* @property string $salt
|
||||
* @property int $avatar_id
|
||||
* @property int $gender
|
||||
* @property int $age
|
||||
* @property string $birthday
|
||||
* @property int $city
|
||||
* @property string $token
|
||||
* @property string $last_ip
|
||||
* @property string $reg_ip
|
||||
* @property string $last_time
|
||||
* @property string $create_time
|
||||
* @property string $update_time
|
||||
* @property int $is_del
|
||||
*/
|
||||
class User extends Model
|
||||
{
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*/
|
||||
protected ?string $table = 'user';
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*/
|
||||
protected array $fillable = [];
|
||||
|
||||
protected array $guarded = [];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast to native types.
|
||||
*/
|
||||
protected array $casts = ['id' => 'integer', 'avatar_id' => 'integer', 'gender' => 'integer', 'age' => 'integer', 'city' => 'integer', 'is_del' => 'integer'];
|
||||
|
||||
const CREATED_AT = 'create_time';
|
||||
const UPDATED_AT = 'update_time';
|
||||
|
||||
|
||||
}
|
||||
43
app/Model/UserThird.php
Normal file
43
app/Model/UserThird.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Model;
|
||||
|
||||
use Hyperf\Database\Model\Builder;
|
||||
use Hyperf\DbConnection\Model\Model;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
* @property int $user_id
|
||||
* @property string $open_id
|
||||
* @property int $type
|
||||
* @property string $union_id
|
||||
*/
|
||||
class UserThird extends Model
|
||||
{
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*/
|
||||
protected ?string $table = 'user_third';
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*/
|
||||
protected array $fillable = [];
|
||||
protected array $guarded = [];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast to native types.
|
||||
*/
|
||||
protected array $casts = ['id' => 'integer', 'user_id' => 'integer', 'type' => 'integer'];
|
||||
|
||||
/**
|
||||
* @param string $openId
|
||||
* @return Builder|\Hyperf\Database\Model\Model|null
|
||||
*/
|
||||
public function getThirdInfoByOpenId(string $openId): \Hyperf\Database\Model\Model|Builder|null
|
||||
{
|
||||
return $this->where('open_id', $openId)->first();
|
||||
}
|
||||
}
|
||||
28
app/Request/Api/LoginRequest.php
Normal file
28
app/Request/Api/LoginRequest.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Request\Api;
|
||||
|
||||
use Hyperf\Validation\Request\FormRequest;
|
||||
|
||||
class LoginRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
|
||||
];
|
||||
}
|
||||
}
|
||||
52
app/Service/Api/BaseService.php
Normal file
52
app/Service/Api/BaseService.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/**
|
||||
* This service file is part of item.
|
||||
*
|
||||
* @author ctexthuang
|
||||
* @contact ctexthuang@qq.com
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Service\Api;
|
||||
|
||||
use App\Lib\ApiReturn;
|
||||
use Hyperf\Context\Context;
|
||||
use Hyperf\Di\Annotation\Inject;
|
||||
use Hyperf\HttpServer\Contract\RequestInterface;
|
||||
|
||||
abstract class BaseService
|
||||
{
|
||||
/**
|
||||
* 请求对象
|
||||
* @var RequestInterface
|
||||
*/
|
||||
#[Inject]
|
||||
protected RequestInterface $request;
|
||||
|
||||
/**
|
||||
* 通用返回对象
|
||||
* @var ApiReturn $return
|
||||
*/
|
||||
#[Inject]
|
||||
protected ApiReturn $return;
|
||||
|
||||
/**
|
||||
* 用户id
|
||||
* @var int $userId
|
||||
*/
|
||||
protected int $userId = 0;
|
||||
|
||||
/**
|
||||
* 主构造函数(获取请求对象)
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->userId = Context::get("user_id",0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 主体函数抽象类
|
||||
*/
|
||||
abstract public function handle();
|
||||
}
|
||||
164
app/Service/Api/Login/LoginBaseService.php
Normal file
164
app/Service/Api/Login/LoginBaseService.php
Normal file
@@ -0,0 +1,164 @@
|
||||
<?php
|
||||
/**
|
||||
* This service file is part of item.
|
||||
*
|
||||
* @author ctexthuang
|
||||
* @contact ctexthuang@qq.com
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Service\Api\Login;
|
||||
|
||||
use App\Cache\Redis\Api\ApiRedisKey;
|
||||
use App\Cache\Redis\RedisCache;
|
||||
use App\Constants\Common\UserCode;
|
||||
use App\Exception\ApiException;
|
||||
use App\Extend\StringUtil;
|
||||
use App\Extend\SystemUtil;
|
||||
use App\Lib\Crypto\CryptoFactory;
|
||||
use App\Model\User;
|
||||
use App\Model\UserThird;
|
||||
use App\Service\Api\BaseService;
|
||||
use Hyperf\Di\Annotation\Inject;
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
use Psr\Container\NotFoundExceptionInterface;
|
||||
|
||||
abstract class LoginBaseService extends BaseService
|
||||
{
|
||||
/**
|
||||
* 注入缓存类
|
||||
* @var RedisCache
|
||||
*/
|
||||
#[Inject]
|
||||
protected RedisCache $redis;
|
||||
|
||||
/**
|
||||
* 注入加密工厂
|
||||
* @var CryptoFactory
|
||||
*/
|
||||
#[Inject]
|
||||
protected CryptoFactory $cryptoFactory;
|
||||
|
||||
/**
|
||||
* 注入三方用户
|
||||
* @var UserThird
|
||||
*/
|
||||
#[Inject]
|
||||
protected UserThird $userThirdModel;
|
||||
|
||||
|
||||
/**
|
||||
* 锁定注册
|
||||
* @var string
|
||||
*/
|
||||
protected string $lockKey;
|
||||
|
||||
/**
|
||||
* 登录code login_type = wx_login 必填
|
||||
* @var string
|
||||
*/
|
||||
protected string $jsCode = '';
|
||||
|
||||
/**
|
||||
* 手机号 login_type = mobile_code 必填
|
||||
* @var string
|
||||
*/
|
||||
protected string $mobile = '';
|
||||
|
||||
/**
|
||||
* 获取的用户信息
|
||||
* @var
|
||||
*/
|
||||
protected mixed $userInfo;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected string $openId = '';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected string $unionId = '';
|
||||
|
||||
/**
|
||||
* 登录
|
||||
* @return void
|
||||
*/
|
||||
protected function login(): void
|
||||
{
|
||||
$this->userId = empty($this->userId) ? $this->userInfo->id : $this->userId;
|
||||
|
||||
if (empty($this->userId)) {
|
||||
throw new ApiException('登录失败');
|
||||
}
|
||||
|
||||
//todo 判断注销 判断封号
|
||||
|
||||
//todo 更新登录时间
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 返回值
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function getReturn():array
|
||||
{
|
||||
$loginReturn = [
|
||||
'id' => $this->userId,
|
||||
'is_bind_mobile' => $this->userInfo->mobile ? UserCode::IS_BIND_PHONE : UserCode::IS_NOT_BIND_PHONE,
|
||||
'nickName' => $this->userInfo->nickName,
|
||||
'is_default_avatar' => $this->userInfo->avatar_id == 0 ? UserCode::IS_DEFAULT_AVATAR : UserCode::IS_NOT_DEFAULT_AVATAR,
|
||||
];
|
||||
|
||||
$loginReturn['token'] = $this->cryptoFactory->cryptoClass('jwt', json_encode($loginReturn))->encrypt();
|
||||
|
||||
|
||||
return $loginReturn;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 判断是不是没有加锁
|
||||
* @param $type
|
||||
* @return void
|
||||
* @throws ContainerExceptionInterface
|
||||
* @throws NotFoundExceptionInterface
|
||||
* @throws \RedisException
|
||||
*/
|
||||
protected function checkLock($type): void
|
||||
{
|
||||
$this->lockKey = match ($type){
|
||||
1 => ApiRedisKey::LoginAndRegisterByMobileLock($this->mobile),
|
||||
2 => ApiRedisKey::LoginAndRegisterByCodeLock($this->jsCode)
|
||||
};
|
||||
|
||||
if (0 == ($this->redis->addLock($this->lockKey))){
|
||||
throw new ApiException('请勿重复点击');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加用户
|
||||
* @return void
|
||||
*/
|
||||
protected function addUser(): void
|
||||
{
|
||||
$model = new User();
|
||||
|
||||
//默认头像和默认名称
|
||||
$model->nickname = '用户'.StringUtil::randStr(6);
|
||||
$model->avatar_id = 0;
|
||||
$model->reg_ip = SystemUtil::getClientIp();
|
||||
|
||||
if (!$model->save()) throw new ApiException('数据保存失败-注册失败');
|
||||
|
||||
$this->userId = $model->id;
|
||||
$this->userInfo = $model;
|
||||
}
|
||||
|
||||
abstract protected function register();
|
||||
}
|
||||
36
app/Service/Api/Login/LoginService.php
Normal file
36
app/Service/Api/Login/LoginService.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/**
|
||||
* This service file is part of item.
|
||||
*
|
||||
* @author ctexthuang
|
||||
* @contact ctexthuang@qq.com
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Service\Api\Login;
|
||||
|
||||
use App\Exception\AdminException;
|
||||
use App\Service\Api\BaseService;
|
||||
|
||||
class LoginService extends BaseService
|
||||
{
|
||||
protected string $loginType = '';
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$this->loginType = $this->request->input('login_type','');
|
||||
|
||||
$factory = new LoginTypeFactory();
|
||||
$service = match ($this->request->input('login_type',''))
|
||||
{
|
||||
'wx_login' => $factory->wxFastLogin(),
|
||||
'mobile_code' => $factory->mobileCodeLogin(),
|
||||
default => throw new AdminException('登录类型错误'),
|
||||
};
|
||||
|
||||
$loginInfo = $service->handle();
|
||||
|
||||
return $this->return->success('登录成功',$loginInfo);
|
||||
}
|
||||
}
|
||||
32
app/Service/Api/Login/LoginTypeFactory.php
Normal file
32
app/Service/Api/Login/LoginTypeFactory.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/**
|
||||
* This service file is part of item.
|
||||
*
|
||||
* @author ctexthuang
|
||||
* @contact ctexthuang@qq.com
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Service\Api\Login;
|
||||
|
||||
class LoginTypeFactory
|
||||
{
|
||||
/**
|
||||
* 验证码登录
|
||||
* @return MobileCodeLoginService
|
||||
*/
|
||||
public function mobileCodeLogin(): MobileCodeLoginService
|
||||
{
|
||||
return new MobileCodeLoginService();
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信快速组件登录
|
||||
* @return WxFastLoginService
|
||||
*/
|
||||
public function wxFastLogin(): WxFastLoginService
|
||||
{
|
||||
return new WxFastLoginService();
|
||||
}
|
||||
}
|
||||
23
app/Service/Api/Login/MobileCodeLoginService.php
Normal file
23
app/Service/Api/Login/MobileCodeLoginService.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* This service file is part of item.
|
||||
*
|
||||
* @author ctexthuang
|
||||
* @contact ctexthuang@qq.com
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Service\Api\Login;
|
||||
|
||||
class MobileCodeLoginService extends LoginBaseService
|
||||
{
|
||||
|
||||
|
||||
public function handle()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
protected function register() {}
|
||||
}
|
||||
81
app/Service/Api/Login/WxFastLoginService.php
Normal file
81
app/Service/Api/Login/WxFastLoginService.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
/**
|
||||
* This service file is part of item.
|
||||
*
|
||||
* @author ctexthuang
|
||||
* @contact ctexthuang@qq.com
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Service\Api\Login;
|
||||
|
||||
use App\Exception\ApiException;
|
||||
use App\Model\UserThird;
|
||||
use App\Service\ServiceTrait\Api\WxMiniTrait;
|
||||
use Hyperf\DbConnection\Db;
|
||||
|
||||
class WxFastLoginService extends LoginBaseService
|
||||
{
|
||||
use WxMiniTrait;
|
||||
|
||||
/**
|
||||
* 登录类型 2=微信小程序
|
||||
*/
|
||||
const int LOGIN_TYPE = 2;
|
||||
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$this->jsCode = $this->request->input('js_code');
|
||||
|
||||
if (empty($this->jsCode)) throw new ApiException('登录参数错误');
|
||||
|
||||
$wxInfo = $this->jsCodeGetOpenId($this->jsCode);
|
||||
$this->openId = $wxInfo['openid'];
|
||||
$this->unionId = $wxInfo['unionid'];
|
||||
|
||||
$this->checkLock(self::LOGIN_TYPE);
|
||||
|
||||
$this->register();
|
||||
|
||||
$this->login();
|
||||
|
||||
$this->redis->delLock($this->lockKey);
|
||||
|
||||
return $this->getReturn();
|
||||
}
|
||||
|
||||
protected function register(): void
|
||||
{
|
||||
$thirdInfo = $this->userThirdModel->getThirdInfoByOpenId($this->openId);
|
||||
if (!empty($thirdInfo)) {
|
||||
$this->userId = $thirdInfo->user_id;
|
||||
return;
|
||||
}
|
||||
|
||||
// todo 设备封禁不可注册 注册限制
|
||||
|
||||
Db::transaction(function () {
|
||||
$this->addUser();
|
||||
|
||||
$this->addUserThird();
|
||||
|
||||
//todo 要不要生成邀请码 有没有注册奖励
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
private function addUserThird(): void
|
||||
{
|
||||
$model = new UserThird();
|
||||
|
||||
$model->user_id = $this->userId;
|
||||
$model->open_id = $this->openId;
|
||||
$model->union_id = $this->unionId;
|
||||
|
||||
if (!$model->save()) throw new ApiException('注册失败-00001');
|
||||
}
|
||||
}
|
||||
79
app/Service/ServiceTrait/Api/WxMiniTrait.php
Normal file
79
app/Service/ServiceTrait/Api/WxMiniTrait.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
/**
|
||||
* This service file is part of item.
|
||||
*
|
||||
* @author ctexthuang
|
||||
* @contact ctexthuang@qq.com
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Service\ServiceTrait\Api;
|
||||
|
||||
use App\Exception\ApiException;
|
||||
use App\Lib\Log;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use Hyperf\Di\Annotation\Inject;
|
||||
use Hyperf\Guzzle\ClientFactory;
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
use Psr\Container\NotFoundExceptionInterface;
|
||||
use function Hyperf\Config\config;
|
||||
|
||||
trait WxMiniTrait
|
||||
{
|
||||
/**
|
||||
* 注入请求工厂类
|
||||
* @var ClientFactory $clientFactory
|
||||
*/
|
||||
#[Inject]
|
||||
protected ClientFactory $clientFactory;
|
||||
|
||||
/**
|
||||
* 注入日志类
|
||||
* @var Log
|
||||
*/
|
||||
#[Inject]
|
||||
protected Log $log;
|
||||
|
||||
/**
|
||||
* baseUri
|
||||
* @var string
|
||||
*/
|
||||
protected string $BaseUri = 'https://api.weixin.qq.com';
|
||||
|
||||
/**
|
||||
* @param string $code
|
||||
* @return mixed
|
||||
* @throws ContainerExceptionInterface
|
||||
* @throws NotFoundExceptionInterface
|
||||
*/
|
||||
public function jsCodeGetOpenId(string $code): mixed
|
||||
{
|
||||
$url = sprintf(
|
||||
'/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code',
|
||||
config('system.wx_appid'),
|
||||
config('system.wx_secret'),
|
||||
$code
|
||||
);
|
||||
|
||||
try {
|
||||
$tencentResponse = $this->clientFactory->create([
|
||||
'base_uri' => $this->BaseUri,
|
||||
'timeout' => 5
|
||||
])->get($url);
|
||||
|
||||
$contents = $tencentResponse->getBody()->getContents();
|
||||
|
||||
$this->log->info(__class__.':微信服务器返回token信息:', [$contents]);
|
||||
|
||||
$res = json_decode($contents,true);
|
||||
|
||||
if (empty($res['errcode']) || $res['errcode'] != 0) throw new ApiException($res['errmsg'] ?? '系统繁忙');
|
||||
|
||||
return $res;
|
||||
}catch (GuzzleException $e) {
|
||||
$this->log->debug(__CLASS__.':debug:'.$e->getMessage());
|
||||
throw new ApiException($e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user