feat: add note module and route fixes
This commit is contained in:
@@ -0,0 +1,164 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\note\service;
|
||||
|
||||
use app\api\common\Jwt;
|
||||
use app\note\model\NoteUser;
|
||||
|
||||
/**
|
||||
* note 模块认证服务
|
||||
*/
|
||||
class AuthService
|
||||
{
|
||||
/**
|
||||
* 微信小程序登录
|
||||
*
|
||||
* @param string $code
|
||||
* @param string|null $nickname
|
||||
* @param string|null $avatarUrl
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function wechatLogin(string $code, ?string $nickname = null, ?string $avatarUrl = null): array
|
||||
{
|
||||
$session = $this->fetchWechatSession($code);
|
||||
$openid = trim((string) ($session['openid'] ?? ''));
|
||||
|
||||
if ($openid === '') {
|
||||
throw new \Exception('微信登录失败,未获取到 openid', 500);
|
||||
}
|
||||
|
||||
$now = time();
|
||||
$user = NoteUser::findByOpenid($openid);
|
||||
$isNewUser = false;
|
||||
|
||||
if (!$user) {
|
||||
$user = new NoteUser();
|
||||
$user->openid = $openid;
|
||||
$user->created_at = $now;
|
||||
$isNewUser = true;
|
||||
}
|
||||
|
||||
if (!$isNewUser && (int) $user->status === 0) {
|
||||
throw new \Exception('小程序账号已被禁用', 403);
|
||||
}
|
||||
|
||||
$user->unionid = (string) ($session['unionid'] ?? '');
|
||||
$user->session_key = (string) ($session['session_key'] ?? '');
|
||||
$user->nickname = $nickname !== null ? trim($nickname) : (string) $user->nickname;
|
||||
$user->avatar_url = $avatarUrl !== null ? trim($avatarUrl) : (string) $user->avatar_url;
|
||||
$user->status = 1;
|
||||
$user->last_login_ip = (string) request()->ip();
|
||||
$user->last_login_time = $now;
|
||||
$user->updated_at = $now;
|
||||
$user->deleted_at = 0;
|
||||
|
||||
if (!$user->save()) {
|
||||
throw new \Exception('小程序用户登录保存失败', 500);
|
||||
}
|
||||
|
||||
$token = Jwt::encode([
|
||||
'userid' => (int) $user->id,
|
||||
'guard' => 'note',
|
||||
'openid' => $user->openid,
|
||||
]);
|
||||
|
||||
$refreshToken = Jwt::encode([
|
||||
'userid' => (int) $user->id,
|
||||
'guard' => 'note',
|
||||
'type' => 'refresh',
|
||||
'openid' => $user->openid,
|
||||
]);
|
||||
|
||||
return [
|
||||
'token' => $token,
|
||||
'refresh_token' => $refreshToken,
|
||||
'expires_in' => config('jwt.expire', 604800),
|
||||
'user' => [
|
||||
'id' => (int) $user->id,
|
||||
'member_id' => (int) ($user->member_id ?? 0),
|
||||
'openid' => (string) $user->openid,
|
||||
'nickname' => (string) $user->nickname,
|
||||
'avatar_url' => (string) $user->avatar_url,
|
||||
'mobile' => (string) $user->mobile,
|
||||
'is_new_user' => $isNewUser,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前小程序用户信息
|
||||
*
|
||||
* @param int $noteUserId
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getUserInfo(int $noteUserId): array
|
||||
{
|
||||
$user = NoteUser::findActiveById($noteUserId);
|
||||
if (!$user) {
|
||||
throw new \Exception('小程序用户不存在', 404);
|
||||
}
|
||||
|
||||
return [
|
||||
'id' => (int) $user->id,
|
||||
'member_id' => (int) ($user->member_id ?? 0),
|
||||
'openid' => (string) $user->openid,
|
||||
'nickname' => (string) $user->nickname,
|
||||
'avatar_url' => (string) $user->avatar_url,
|
||||
'mobile' => (string) $user->mobile,
|
||||
'status' => (int) $user->status,
|
||||
'last_login_time' => (int) $user->last_login_time,
|
||||
'created_at' => (int) $user->created_at,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求微信 code2Session
|
||||
*
|
||||
* @param string $code
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function fetchWechatSession(string $code): array
|
||||
{
|
||||
$appId = (string) env('WECHAT_MINI_APPID', '');
|
||||
$appSecret = (string) env('WECHAT_MINI_SECRET', '');
|
||||
|
||||
if ($appId === '' || $appSecret === '') {
|
||||
throw new \Exception('缺少微信小程序配置 WECHAT_MINI_APPID / WECHAT_MINI_SECRET', 500);
|
||||
}
|
||||
|
||||
$url = sprintf(
|
||||
'https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code',
|
||||
urlencode($appId),
|
||||
urlencode($appSecret),
|
||||
urlencode($code)
|
||||
);
|
||||
|
||||
$ch = curl_init($url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
|
||||
$response = curl_exec($ch);
|
||||
$error = curl_error($ch);
|
||||
curl_close($ch);
|
||||
|
||||
if ($response === false || $response === '' || $error) {
|
||||
throw new \Exception('微信登录请求失败', 502);
|
||||
}
|
||||
|
||||
$data = json_decode($response, true);
|
||||
if (!is_array($data)) {
|
||||
throw new \Exception('微信登录响应解析失败', 502);
|
||||
}
|
||||
|
||||
if (!empty($data['errcode'])) {
|
||||
throw new \Exception(sprintf('微信登录失败:%s', (string) ($data['errmsg'] ?? 'unknown error')), 400);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user