2026-01-05 14:33:21 +08:00
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
|
|
namespace app\common\service;
|
|
|
|
|
|
|
|
|
|
|
|
use app\common\logic\AuthLogic;
|
|
|
|
|
|
use app\common\model\User;
|
|
|
|
|
|
use app\common\utils\Feishu;
|
|
|
|
|
|
use support\Db;
|
|
|
|
|
|
|
|
|
|
|
|
class AuthService
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 飞书授权
|
|
|
|
|
|
*/
|
2026-01-13 17:24:14 +08:00
|
|
|
|
public function feishuAuthorize(string $app_id, string $systemCcode, $is_pc)
|
2026-01-05 14:33:21 +08:00
|
|
|
|
{
|
|
|
|
|
|
$logic = new AuthLogic();
|
|
|
|
|
|
$certificate = $logic->feishuAppInfo($app_id, $systemCcode);
|
|
|
|
|
|
$feishu = new Feishu($certificate['app_id'], $certificate['app_secret'], 'xinyouhe');
|
2026-01-13 17:24:14 +08:00
|
|
|
|
return ['auth_url' => $feishu->authorize($certificate, $is_pc)];
|
2026-01-05 14:33:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-08 14:30:42 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* JSAPI鉴权签名
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function feishuSignature(string $app_id, string $url = '')
|
|
|
|
|
|
{
|
|
|
|
|
|
$logic = new AuthLogic();
|
|
|
|
|
|
$certificate = $logic->feishuAppInfo($app_id);
|
|
|
|
|
|
$feishu = new Feishu($certificate['app_id'], $certificate['app_secret'], 'xinyouhe');
|
|
|
|
|
|
|
|
|
|
|
|
// 获取 jsapi_ticket
|
|
|
|
|
|
$jsapiTicket = $feishu->jsapiTicket();
|
|
|
|
|
|
|
|
|
|
|
|
// 处理 URL:移除 # 和 ? 后面的参数
|
|
|
|
|
|
$url = $this->cleanUrl($url);
|
|
|
|
|
|
|
|
|
|
|
|
// 生成随机字符串
|
|
|
|
|
|
$noncestr = $this->generateNonceStr();
|
|
|
|
|
|
|
|
|
|
|
|
// 获取毫秒级时间戳
|
2026-01-08 16:53:09 +08:00
|
|
|
|
$timestamp = (int)round(microtime(true) * 1000);
|
|
|
|
|
|
// $timestamp = time();
|
2026-01-08 16:18:01 +08:00
|
|
|
|
|
2026-01-08 14:30:42 +08:00
|
|
|
|
// 拼接签名字符串
|
|
|
|
|
|
$verifyStr = "jsapi_ticket={$jsapiTicket}&noncestr={$noncestr}×tamp={$timestamp}&url={$url}";
|
|
|
|
|
|
|
|
|
|
|
|
// 生成 SHA1 签名
|
|
|
|
|
|
$signature = sha1($verifyStr);
|
|
|
|
|
|
|
|
|
|
|
|
return [
|
|
|
|
|
|
'jsapi_ticket' => $jsapiTicket,
|
|
|
|
|
|
'noncestr' => $noncestr,
|
|
|
|
|
|
'timestamp' => $timestamp,
|
|
|
|
|
|
'url' => $url,
|
|
|
|
|
|
'signature' => $signature
|
|
|
|
|
|
];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 清理 URL,移除 # 和 ? 后面的参数
|
|
|
|
|
|
*/
|
|
|
|
|
|
private function cleanUrl(string $url): string
|
|
|
|
|
|
{
|
|
|
|
|
|
// 移除 # 后面的内容
|
|
|
|
|
|
$pos = strpos($url, '#');
|
|
|
|
|
|
if ($pos !== false) {
|
|
|
|
|
|
$url = substr($url, 0, $pos);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 移除 ? 后面的内容
|
|
|
|
|
|
$pos = strpos($url, '?');
|
|
|
|
|
|
if ($pos !== false) {
|
|
|
|
|
|
$url = substr($url, 0, $pos);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return $url;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 生成随机字符串(由数字、字母组成)
|
|
|
|
|
|
*/
|
|
|
|
|
|
private function generateNonceStr(int $length = 16): string
|
|
|
|
|
|
{
|
|
|
|
|
|
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
|
|
|
|
|
$noncestr = '';
|
|
|
|
|
|
for ($i = 0; $i < $length; $i++) {
|
|
|
|
|
|
$noncestr .= $chars[mt_rand(0, strlen($chars) - 1)];
|
|
|
|
|
|
}
|
|
|
|
|
|
return $noncestr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-05 14:33:21 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 登录,支持多类型
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function login(array $data): array
|
|
|
|
|
|
{
|
|
|
|
|
|
$loginType = $data['login_type'] ?? 'feishu';
|
|
|
|
|
|
$logic = new AuthLogic();
|
|
|
|
|
|
|
|
|
|
|
|
return match ($loginType) {
|
|
|
|
|
|
'feishu' => $logic->feishuLogin($data),
|
|
|
|
|
|
// 'qrcode' => $logic->qrCodeLogin($data),
|
|
|
|
|
|
default => $logic->uPwdLogin($data),
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 用户注册
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function register(array $data)
|
|
|
|
|
|
{
|
|
|
|
|
|
$logic = new AuthLogic();
|
|
|
|
|
|
try {
|
|
|
|
|
|
Db::beginTransaction();
|
|
|
|
|
|
$result = $logic->register($data);
|
|
|
|
|
|
Db::commit();
|
|
|
|
|
|
return $result;
|
|
|
|
|
|
} catch (\Throwable $e) {
|
|
|
|
|
|
Db::rollback();
|
|
|
|
|
|
throw $e;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 校验token
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function verifyToken(string $token, string $systemCode): array
|
|
|
|
|
|
{
|
|
|
|
|
|
return (new AuthLogic())->verifyToken($token, $systemCode);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 刷新token
|
|
|
|
|
|
* @param string $refreshToken
|
|
|
|
|
|
* @param string|null $systemCode
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function refreshToken(string $refreshToken, string $systemCode): array
|
|
|
|
|
|
{
|
|
|
|
|
|
return (new AuthLogic())->refreshToken($refreshToken, $systemCode);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 登出(失效token)
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function logout(?string $token, string $systemCode): void
|
|
|
|
|
|
{
|
|
|
|
|
|
(new AuthLogic())->logout($token, $systemCode);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 强制拉黑token
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function blockToken(string $token, string $systemCode): void
|
|
|
|
|
|
{
|
|
|
|
|
|
(new AuthLogic())->blockToken($token, $systemCode);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|