This commit is contained in:
Hankin 2026-04-27 11:15:42 +08:00
parent 1019889dfd
commit d884aa658e
9 changed files with 362 additions and 3 deletions

View File

@ -0,0 +1,91 @@
<?php
namespace App\Helpers;
use DateTimeImmutable;
class TokenHelper
{
private static $secret = 'ufutx_love_util';
/**
* 生成 token
* @param int $userId 用户ID
* @param int $expiresIn 过期时间(分钟)
* @return string
*/
public static function generate($userId, $expiresIn = 60)
{
$now = time();
$expires = $now + ($expiresIn * 60);
$payload = [
'user_id' => $userId,
'iat' => $now,
'exp' => $expires
];
// 使用更简单的方式base64 编码(避免版本兼容问题)
$encoded = base64_encode(json_encode($payload));
// 添加签名
$signature = hash_hmac('sha256', $encoded, self::$secret);
return $encoded . '.' . $signature;
}
/**
* 验证 token
* @return array|false
*/
public static function verify($tokenString)
{
try {
$parts = explode('.', $tokenString);
if (count($parts) != 2) {
return false;
}
list($payloadEncoded, $signature) = $parts;
// 验证签名
$expectedSignature = hash_hmac('sha256', $payloadEncoded, self::$secret);
if (!hash_equals($expectedSignature, $signature)) {
return false;
}
// 解码 payload
$payload = json_decode(base64_decode($payloadEncoded), true);
if (!$payload) {
return false;
}
// 检查是否过期
$now = time();
if (isset($payload['exp']) && $payload['exp'] < $now) {
return false;
}
return [
'user_id' => $payload['user_id'],
'expires_at' => $payload['exp']
];
} catch (\Exception $e) {
return false;
}
}
/**
* 刷新 token
*/
public static function refresh($oldToken, $expiresIn = 60)
{
$payload = self::verify($oldToken);
if (!$payload) {
return false;
}
return self::generate($payload['user_id'], $expiresIn);
}
}

View File

@ -4,10 +4,12 @@ namespace App\Http\Controllers;
use App\Facades\UtilService; use App\Facades\UtilService;
use App\Facades\WechatPayService; use App\Facades\WechatPayService;
use App\Helpers\TokenHelper;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs; use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController; use Illuminate\Routing\Controller as BaseController;
use Log;
class Controller extends BaseController class Controller extends BaseController
{ {
@ -25,5 +27,12 @@ class Controller extends BaseController
// // $res = WechatPayService::transferBatches($trade_no1, $trade_no2, $openid, $amount, $remark); // // $res = WechatPayService::transferBatches($trade_no1, $trade_no2, $openid, $amount, $remark);
// $res = WechatPayService::mchTransfer($trade_no1, $scene_id, $openid, $amount, $remark); // $res = WechatPayService::mchTransfer($trade_no1, $scene_id, $openid, $amount, $remark);
// dd($res); // dd($res);
$token = TokenHelper::generate(123);
Log::info($token);
$res = TokenHelper::verify($token);
dd($res);
} }
} }

View File

@ -65,5 +65,7 @@ class Kernel extends HttpKernel
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'merchant' => \App\Http\Middleware\CheckMerchant::class, 'merchant' => \App\Http\Middleware\CheckMerchant::class,
'merchant_user' => \App\Http\Middleware\CheckMerchantUser::class, 'merchant_user' => \App\Http\Middleware\CheckMerchantUser::class,
'checkAdmin' => \App\Http\Middleware\CheckAdmin::class,
]; ];
} }

View File

@ -14,7 +14,7 @@ class Authenticate extends Middleware
*/ */
protected function redirectTo($request) protected function redirectTo($request)
{ {
if (! $request->expectsJson()) { if (!$request->expectsJson()) {
return route('login'); return route('login');
} }
} }

View File

@ -0,0 +1,53 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use App\Helpers\TokenHelper;
class CheckAdmin
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
try {
$token = $request->bearerToken();
if (!$token) {
return response()->json(['code' => 2, 'message' => '请登录后访问.'], 200);
}
$payload = TokenHelper::verify($token);
if (!$payload) {
return response()->json(['code' => 2, 'message' => '请登录后访问.'], 200);
}
return $next($request);
} catch (\Exception $e) {
return $this->fail('信息有误,请重新登录', 2);
}
}
//接口返回失败
public function fail($msg, $code = 5, $path = '', $operate = '', $notice = '')
{
$result = [
'code' => $code,
'path' => $path,
'message' => $msg,
'operate' => $operate,
'notice' => $notice,
];
return Response()->json($result);
}
}

View File

@ -15,4 +15,6 @@ class UtilService
$mix_2 = rand(100, 999); $mix_2 = rand(100, 999);
return $dateline . $mix_1 . $mix_2; return $dateline . $mix_1 . $mix_2;
} }
} }

View File

@ -11,6 +11,7 @@
"laravel/framework": "^9.19", "laravel/framework": "^9.19",
"laravel/sanctum": "^3.0", "laravel/sanctum": "^3.0",
"laravel/tinker": "^2.7", "laravel/tinker": "^2.7",
"lcobucci/jwt": "^4.3",
"wechatpay/wechatpay": "^1.4" "wechatpay/wechatpay": "^1.4"
}, },
"require-dev": { "require-dev": {

202
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "9824f12aeda8b0dc6d475ee5d9fb8ba9", "content-hash": "abd6a268741333599457876ecbc1a4b6",
"packages": [ "packages": [
{ {
"name": "alibabacloud/oss-v2", "name": "alibabacloud/oss-v2",
@ -1650,6 +1650,153 @@
}, },
"time": "2024-09-23T13:32:56+00:00" "time": "2024-09-23T13:32:56+00:00"
}, },
{
"name": "lcobucci/clock",
"version": "2.2.0",
"source": {
"type": "git",
"url": "https://github.com/lcobucci/clock.git",
"reference": "fb533e093fd61321bfcbac08b131ce805fe183d3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/lcobucci/clock/zipball/fb533e093fd61321bfcbac08b131ce805fe183d3",
"reference": "fb533e093fd61321bfcbac08b131ce805fe183d3",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"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"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Luís Cobucci",
"email": "lcobucci@gmail.com"
}
],
"description": "Yet another clock abstraction",
"support": {
"issues": "https://github.com/lcobucci/clock/issues",
"source": "https://github.com/lcobucci/clock/tree/2.2.0"
},
"funding": [
{
"url": "https://github.com/lcobucci",
"type": "github"
},
{
"url": "https://www.patreon.com/lcobucci",
"type": "patreon"
}
],
"time": "2022-04-19T19:34:17+00:00"
},
{
"name": "lcobucci/jwt",
"version": "4.3.0",
"source": {
"type": "git",
"url": "https://github.com/lcobucci/jwt.git",
"reference": "4d7de2fe0d51a96418c0d04004986e410e87f6b4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/lcobucci/jwt/zipball/4d7de2fe0d51a96418c0d04004986e410e87f6b4",
"reference": "4d7de2fe0d51a96418c0d04004986e410e87f6b4",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"ext-hash": "*",
"ext-json": "*",
"ext-mbstring": "*",
"ext-openssl": "*",
"ext-sodium": "*",
"lcobucci/clock": "^2.0 || ^3.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.2",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^1.4",
"phpstan/phpstan-deprecation-rules": "^1.0",
"phpstan/phpstan-phpunit": "^1.0",
"phpstan/phpstan-strict-rules": "^1.0",
"phpunit/php-invoker": "^3.1",
"phpunit/phpunit": "^9.5"
},
"type": "library",
"autoload": {
"psr-4": {
"Lcobucci\\JWT\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"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"
],
"support": {
"issues": "https://github.com/lcobucci/jwt/issues",
"source": "https://github.com/lcobucci/jwt/tree/4.3.0"
},
"funding": [
{
"url": "https://github.com/lcobucci",
"type": "github"
},
{
"url": "https://www.patreon.com/lcobucci",
"type": "patreon"
}
],
"time": "2023-01-02T13:28:00+00:00"
},
{ {
"name": "league/commonmark", "name": "league/commonmark",
"version": "2.6.0", "version": "2.6.0",
@ -3451,6 +3598,59 @@
}, },
"time": "2025-06-01T06:28:46+00:00" "time": "2025-06-01T06:28:46+00:00"
}, },
{
"name": "stella-maris/clock",
"version": "0.1.7",
"source": {
"type": "git",
"url": "https://github.com/stella-maris-solutions/clock.git",
"reference": "fa23ce16019289a18bb3446fdecd45befcdd94f8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/stella-maris-solutions/clock/zipball/fa23ce16019289a18bb3446fdecd45befcdd94f8",
"reference": "fa23ce16019289a18bb3446fdecd45befcdd94f8",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": "^7.0|^8.0",
"psr/clock": "^1.0"
},
"type": "library",
"autoload": {
"psr-4": {
"StellaMaris\\Clock\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"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"
],
"support": {
"source": "https://github.com/stella-maris-solutions/clock/tree/0.1.7"
},
"time": "2022-11-25T16:15:06+00:00"
},
{ {
"name": "symfony/console", "name": "symfony/console",
"version": "v6.0.19", "version": "v6.0.19",

View File

@ -4,4 +4,5 @@ use App\Http\Controllers\WechatPayController;
//发起转账 //发起转账
Route::post('saas/mch/transfer', [WechatPayController::class, "mchTransfer"])->middleware('merchant_user'); Route::post('saas/mch/transfer', [WechatPayController::class, "mchTransfer"])->middleware('merchant_user');
Route::post('saas/mch/transfer/callback', [WechatPayController::class, "mchTransferCallback"]); Route::post('admin/mch/transfer', [WechatPayController::class, "mchTransfer"]);
Route::post('saas/mch/transfer/callback', [WechatPayController::class, "mchTransferCallback"])->middleware("checkAdmin");