chore: 重写初始提交(清空历史,整理后全量提交)

This commit is contained in:
ywxapp
2026-08-16 16:54:14 +08:00
commit 6c1a106bc1
1808 changed files with 238144 additions and 0 deletions
+348
View File
@@ -0,0 +1,348 @@
<?php
// +----------------------------------------------------------------------
// | YwxApp [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2026-2036 http://ywxapp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: ywxapp<admin@ywxapp.cn>
// +----------------------------------------------------------------------
declare (strict_types = 1);
namespace addon\wxchat\middleware;
use addon\wxchat\model\WxchatAppVersion as AppVersion;
use think\facade\Log;
use think\facade\Request;
use think\Response;
/**
* AppVersionCheck 类
*
* @author ywxapp <admin@ywxapp.cn>
*/
class AppVersionCheck
{
/**
* 处理请求
*
* @param \think\Request $request
* @param \Closure $next
* @return Response
*/
// 需要跳过的路由(不需要版本检查的接口)
protected array $except = [
'app/version/check',
'app/version/latest',
'api/auth/login',
'api/auth/register',
'api/public/*',
];
// 需要强制版本检查的路由(版本过低直接拒绝)
protected array $forceCheck = [
'api/user/*',
'api/order/*',
'api/payment/*',
'api/wallet/*',
];
// 最低支持的版本号(硬性要求)
protected array $minVersions = [
'android' => 100,
'ios' => 100,
'harmony' => 100,
];
/**
* 版本检查结果
*/
protected array $result = [
'need_update' => false, // 是否需要更新
'is_force_update' => false, // 是否强制更新
'is_compatible' => true, // 是否兼容
'update_type' => 'none', // 更新类型: none/optional/recommended/required
'current_version' => null, // 当前版本信息
'latest_version' => null, // 最新版本信息
'min_support_version' => 0, // 最低支持版本
'version_diff' => 0, // 版本差异
'message' => '', // 提示信息
'download_url' => '', // 下载地址
'update_content' => '', // 更新内容
'size' => '', // 安装包大小
];
public function handle($request, \Closure $next)
{
// 获取Header信息
$platform = Request::header('App-Platform', Request::header('X-App-Platform', ''));
$versionCode = (int) Request::header('App-Version-Code', Request::header('X-App-Version-Code', 0));
$versionName = Request::header('App-Version-Name', Request::header('X-App-Version-Name', ''));
$channel = Request::header('App-Channel', Request::header('X-App-Channel', ''));
// 记录请求信息(用于日志分析)
// $this->logRequestInfo($platform, $versionCode, $versionName, $channel);
// 检查是否需要跳过版本检查
// if ($this->shouldExcept()) {
// return $next($request);
// }
// 验证Header必填字段
if (empty($platform) || $versionCode <= 0) {
// 如果是强制检查的接口,直接拒绝
if ($this->isForceCheck()) {
return $this->errorResponse(
400,
'缺少APP版本信息,请升级到最新版本',
['required_headers' => ['App-Platform', 'App-Version-Code']]
);
}
// 非强制检查,记录警告但继续
Log::warning('请求缺少版本信息', [
'path' => Request::url(),
'ip' => Request::ip(),
]);
return $next($request);
}
// 验证平台合法性
if (! in_array($platform, ['android', 'ios', 'harmony', 'web'])) {
return $this->errorResponse(400, '无效的平台类型');
}
// 检查最低版本要求
if ($versionCode < ($this->minVersions[$platform] ?? 0)) {
return $this->errorResponse(
426, // Upgrade Required
"当前版本过低,请升级到最新版本",
[
'min_version_code' => $this->minVersions[$platform],
'current_version_code' => $versionCode,
'platform' => $platform,
]
);
}
// 执行版本检查逻辑
$checkResult = $this->checkVersion($platform, $versionCode);
// 如果版本不兼容且是强制检查接口,拒绝访问
if (! $checkResult['is_compatible'] && $this->isForceCheck()) {
return $this->errorResponse(
426,
$checkResult['message'] ?? '版本不兼容,请升级到最新版本',
[
'need_update' => true,
'is_force_update' => true,
'latest_version' => $checkResult['latest_version'],
'download_url' => $checkResult['download_url'] ?? '',
]
);
}
// 将版本信息存入Request,供后续控制器使用
$request->appPlatform = $platform;
$request->appVersionCode = $versionCode;
$request->appVersionName = $versionName;
$request->appChannel = $channel;
// 继续执行
$response = $next($request);
// 在响应Header中返回版本检查结果(可选)
if ($checkResult['need_update']) {
$response->header([
'X-App-Need-Update' => 'true',
'X-App-Update-Type' => $checkResult['update_type'] ?? 'optional',
'X-App-Latest-Version' => $checkResult['latest_version']['version_name'] ?? '',
]);
}
return $response;
}
/**
* 检查版本
* @param string $platform 平台: android/ios/harmony
* @param int $currentVersionCode 当前版本号
* @return array
* @throws Exception
*/
public function checkVersion(string $platform, int $currentVersionCode): array
{
// 验证平台
$validPlatforms = ['android', 'ios', 'harmony'];
if (! in_array($platform, $validPlatforms)) {
throw new Exception('无效的平台类型');
}
// 获取最新版本
$latestVersion = AppVersion::getLatestVersion($platform);
if (! $latestVersion) {
throw new Exception('未找到该平台的版本信息');
}
// 获取当前版本信息
$currentVersion = AppVersion::getVersion($platform, $currentVersionCode);
// 设置最新版本信息
$this->result['latest_version'] = [
'version_code' => $latestVersion->version_code,
'version_name' => $latestVersion->version_name,
'release_time' => $latestVersion->release_time,
];
// 设置当前版本信息
$this->result['current_version'] = $currentVersion ? [
'version_code' => $currentVersion->version_code,
'version_name' => $currentVersion->version_name,
] : null;
// 设置最低支持版本
$this->result['min_support_version'] = $latestVersion->min_support_version;
// 计算版本差异
$this->result['version_diff'] = $latestVersion->version_code - $currentVersionCode;
// 判断是否需要更新
if ($currentVersionCode < $latestVersion->version_code) {
$this->result['need_update'] = true;
$this->result['is_force_update'] = (bool) $latestVersion->is_force_update;
$this->result['is_compatible'] = (bool) $latestVersion->is_compatible;
$this->result['update_type'] = $latestVersion->update_type;
$this->result['download_url'] = $latestVersion->download_url;
$this->result['update_content'] = $latestVersion->update_content;
$this->result['size'] = $latestVersion->size;
// 生成提示信息
$this->generateMessage($latestVersion, $currentVersionCode);
} else {
$this->result['message'] = '当前已是最新版本';
}
// 检查是否低于最低支持版本
if ($currentVersionCode < $latestVersion->min_support_version) {
$this->result['need_update'] = true;
$this->result['is_force_update'] = true;
$this->result['is_compatible'] = false;
$this->result['update_type'] = 'required';
$this->result['message'] = '当前版本过低,必须升级到最新版本才能继续使用';
}
return $this->result;
}
/**
* 判断是否需要跳过版本检查
*/
protected function shouldExcept(): bool
{
$path = Request::path();
foreach ($this->except as $except) {
if ($except === $path || fnmatch($except, $path)) {
return true;
}
}
return false;
}
/**
* 判断是否需要强制版本检查
*/
protected function isForceCheck(): bool
{
$path = Request::controller() . '/' . Request::action();
foreach ($this->forceCheck as $check) {
if ($check === $path || fnmatch($check, $path)) {
return true;
}
}
return false;
}
/**
* 记录请求信息
*/
protected function logRequestInfo(string $platform, int $versionCode, string $versionName, string $channel): void
{
// 只记录特定接口的日志(避免日志过多)
$logPaths = [
'api/user/*',
'api/order/*',
'api/payment/*',
];
$path = Request::path();
foreach ($logPaths as $logPath) {
if (fnmatch($logPath, $path)) {
Log::info('APP请求', [
'path' => $path,
'method' => Request::method(),
'platform' => $platform,
'version_code' => $versionCode,
'version_name' => $versionName,
'channel' => $channel,
'ip' => Request::ip(),
'user_agent' => Request::header('Member-Agent', ''),
]);
break;
}
}
}
/**
* 错误响应
*/
protected function errorResponse(int $code, string $message, array $data = []): Response
{
return json([
'code' => $code,
'message' => $message,
'data' => $data,
'timestamp' => time(),
], $code);
}
/**
* 生成提示信息
* @param AppVersion $latestVersion 最新版本
* @param int $currentVersionCode 当前版本号
*/
protected function generateMessage(AppVersion $latestVersion, int $currentVersionCode): void
{
$versionName = $latestVersion->version_name;
if ($latestVersion->is_force_update) {
$this->result['message'] = "发现新版本 {$versionName},请立即升级";
} elseif ($latestVersion->update_type === 'required') {
$this->result['message'] = "发现重要更新 {$versionName},建议立即升级";
} elseif ($latestVersion->update_type === 'recommended') {
$this->result['message'] = "发现新版本 {$versionName},建议升级";
} else {
$this->result['message'] = "发现新版本 {$versionName},可选择升级";
}
// 如果不兼容,添加警告
if (!$latestVersion->is_compatible) {
$this->result['message'] .= "(当前版本将无法继续使用)";
}
}
/**
* 版本号转换为版本名称
* @param int $versionCode 版本号 101
* @return string 版本名称 1.0.1
*/
public static function versionCodeToName(int $versionCode): string
{
$major = floor($versionCode / 100);
$minor = floor(($versionCode % 100) / 10);
$patch = $versionCode % 10;
return "{$major}.{$minor}.{$patch}";
}
/**
* 版本名称转换为版本号
* @param string $versionName 版本名称 1.0.1
* @return int 版本号 101
*/
public static function versionNameToCode(string $versionName): int
{
$parts = explode('.', $versionName);
$parts = array_pad($parts, 3, 0);
return (int)($parts[0] * 100 + $parts[1] * 10 + $parts[2]);
}
}