1.重构实时消息WebSocket连接

2.MySQL备份
This commit is contained in:
2026-04-24 13:49:38 +08:00
parent d69412a0f7
commit fd324f2882
54 changed files with 2396 additions and 2638 deletions

View File

@@ -1,12 +0,0 @@
<?php
return [
'enable' => true,
'websocket' => 'websocket://0.0.0.0:3131',
'api' => 'http://0.0.0.0:3232',
/** 浏览器连接的 WebSocket 基址(不含 /app/)。生产/前后端分离必填,如 wss://api.example.com */
'websocket_client' => env('PUSH_WEBSOCKET_CLIENT_URL', ''),
'app_key' => '6d0af5971ad191f2dc8a500885cb79c7',
'app_secret' => 'c457f0be89cd48d481b37f16c0a97f5f',
'channel_hook' => 'http://127.0.0.1:7979/plugin/webman/push/hook',
'auth' => '/plugin/webman/push/auth'
];

View File

@@ -1,21 +0,0 @@
<?php
use Webman\Push\Server;
return [
'server' => [
'handler' => Server::class,
'listen' => config('plugin.webman.push.app.websocket'),
'count' => 1, // 必须是1
'reloadable' => false, // 执行reload不重启
'constructor' => [
'api_listen' => config('plugin.webman.push.app.api'),
'app_info' => [
config('plugin.webman.push.app.app_key') => [
'channel_hook' => config('plugin.webman.push.app.channel_hook'),
'app_secret' => config('plugin.webman.push.app.app_secret'),
],
]
]
]
];

View File

@@ -1,98 +0,0 @@
<?php
/**
* This file is part of webman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
use support\Request;
use Webman\Route;
use Webman\Push\Api;
/**
* 推送 js 客户端
* - 生产环境 Nginx 常把 root 指到 public/:须存在 public/plugin/webman/push/push.js与 vendor 同步)
* - 若请求进入 Webman则优先读 public其次 vendor
*/
Route::get('/plugin/webman/push/push.js', function (Request $request) {
$publicFile = public_path() . DIRECTORY_SEPARATOR . 'plugin' . DIRECTORY_SEPARATOR . 'webman' . DIRECTORY_SEPARATOR . 'push' . DIRECTORY_SEPARATOR . 'push.js';
if (is_file($publicFile)) {
return response()->file($publicFile);
}
$vendorFile = base_path() . '/vendor/webman/push/src/push.js';
if (is_file($vendorFile)) {
return response()->file($vendorFile);
}
return response('push.js not found. Run: copy vendor/webman/push/src/push.js to public/plugin/webman/push/push.js', 404);
});
/**
* 私有频道鉴权这里应该使用session辨别当前用户身份然后确定该用户是否有权限监听channel_name
*/
Route::post(config('plugin.webman.push.app.auth'), function (Request $request) {
$pusher = new Api(str_replace('0.0.0.0', '127.0.0.1', config('plugin.webman.push.app.api')), config('plugin.webman.push.app.app_key'), config('plugin.webman.push.app.app_secret'));
$channel_name = $request->post('channel_name');
$session = $request->session();
// 这里应该通过session和channel_name判断当前用户是否有权限监听channel_name
$has_authority = true;
if ($has_authority) {
return response($pusher->socketAuth($channel_name, $request->post('socket_id')));
} else {
return response('Forbidden', 403);
}
});
/**
* 当频道上线以及下线时触发的回调
* 频道上线:是指某个频道从没有连接在线到有连接在线的事件
* 频道下线:是指某个频道的所有连接都断开触发的事件
*/
Route::post(parse_url(config('plugin.webman.push.app.channel_hook'), PHP_URL_PATH), function (Request $request) {
// 没有x-pusher-signature头视为伪造请求
if (!$webhook_signature = $request->header('x-pusher-signature')) {
return response('401 Not authenticated', 401);
}
$body = $request->rawBody();
// 计算签名,$app_secret 是双方使用的密钥,是保密的,外部无从得知
$expected_signature = hash_hmac('sha256', $body, config('plugin.webman.push.app.app_secret'), false);
// 安全校验如果签名不一致可能是伪造的请求返回401状态码
if ($webhook_signature !== $expected_signature) {
return response('401 Not authenticated', 401);
}
// 这里存储这上线 下线的channel数据
$payload = json_decode($body, true);
$channels_online = $channels_offline = [];
foreach ($payload['events'] as $event) {
if ($event['name'] === 'channel_added') {
$channels_online[] = $event['channel'];
} else if ($event['name'] === 'channel_removed') {
$channels_offline[] = $event['channel'];
}
}
// 业务根据需要处理上下线的channel例如将在线状态写入数据库通知其它channel等
// 上线的所有channel
echo 'online channels: ' . implode(',', $channels_online) . "\n";
// 下线的所有channel
echo 'offline channels: ' . implode(',', $channels_offline) . "\n";
return 'OK';
});

View File

@@ -64,6 +64,13 @@ return [
'count' => 1,
'reloadable' => false,
],
// 后台测试页 WebSocket 连接服务(供 /admin/test/gameCurrentStatus 联调)
'gameWebSocketServer' => [
'handler' => app\process\GameWebSocketServer::class,
'listen' => env('H5_WEBSOCKET_LISTEN', 'websocket://0.0.0.0:3131'),
'count' => 1,
'reloadable' => false,
],
// File update detection and automatic reload
'monitor' => [

View File

@@ -131,6 +131,9 @@ Route::add(['GET', 'POST'], '/api/game/periodHistory', [\app\api\controller\Game
Route::add(['GET', 'POST'], '/api/game/periodCurrent', [\app\api\controller\Game::class, 'periodCurrent']);
Route::post('/api/game/betPlace', [\app\api\controller\Game::class, 'betPlace']);
Route::add(['GET', 'POST'], '/api/game/betMyOrders', [\app\api\controller\Game::class, 'betMyOrders']);
Route::add(['GET', 'POST'], '/api/game/currentStatus', [\app\api\controller\Game::class, 'currentStatus']);
Route::post('/api/game/placeBet', [\app\api\controller\Game::class, 'placeBet']);
Route::post('/api/game/autoSpin', [\app\api\controller\Game::class, 'autoSpin']);
Route::add(['GET', 'POST'], '/api/wallet/balanceSummary', [\app\api\controller\Wallet::class, 'balanceSummary']);
Route::add(['GET', 'POST'], '/api/wallet/recordList', [\app\api\controller\Wallet::class, 'recordList']);