fix(core): harden settlement and wallet integration

This commit is contained in:
wchino
2026-07-22 01:40:37 +08:00
parent 150c3e7ebd
commit 35f6e46958
54 changed files with 2564 additions and 359 deletions

View File

@@ -1,21 +1,25 @@
<?php
use App\Events\BalanceUpdateBroadcast;
use App\Events\PlayCatalogUpdatedBroadcast;
use App\Events\RiskSoldOutBroadcast;
use App\Events\RiskWarningBroadcast;
use App\Services\Config\RiskCapStreamService;
use App\Models\Draw;
use App\Models\Player;
use App\Models\PlayerWallet;
use App\Models\RiskPool;
use App\Services\Ticket\RiskPoolService;
use App\Services\Wallet\LotteryTransferService;
use App\Services\Wallet\WalletBalanceRealtimeNotifier;
use App\Models\AdminUser;
use App\Models\PlayerWallet;
use App\Events\RiskSoldOutBroadcast;
use App\Events\RiskWarningBroadcast;
use Database\Seeders\CurrencySeeder;
use Database\Seeders\LotterySettingsSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Event;
use App\Events\BalanceUpdateBroadcast;
use App\Services\Ticket\RiskPoolService;
use Illuminate\Support\Facades\Broadcast;
use App\Events\PlayCatalogUpdatedBroadcast;
use Database\Seeders\LotterySettingsSeeder;
use Illuminate\Broadcasting\PrivateChannel;
use App\Services\Config\RiskCapStreamService;
use App\Services\Wallet\LotteryTransferService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use App\Services\Wallet\WalletBalanceRealtimeNotifier;
uses(RefreshDatabase::class);
@@ -26,6 +30,55 @@ beforeEach(function (): void {
$this->seed(LotterySettingsSeeder::class);
});
test('balance update broadcasts only on the player private channel', function (): void {
$event = new BalanceUpdateBroadcast(42, 'NPR', 10_000, -500, 'bet', 1_234_567);
$channels = $event->broadcastOn();
expect($channels)->toHaveCount(1)
->and($channels[0])->toBeInstanceOf(PrivateChannel::class)
->and($channels[0]->name)->toBe('private-player.42');
});
test('player private channel auth allows only the matching bearer player', function (): void {
config([
'broadcasting.default' => 'reverb',
'broadcasting.connections.reverb.key' => 'test-reverb-key',
'broadcasting.connections.reverb.secret' => 'test-reverb-secret',
'broadcasting.connections.reverb.app_id' => 'test-reverb-app',
]);
Broadcast::purge('reverb');
require base_path('routes/channels.php');
$player = Player::query()->create([
'site_code' => 'test',
'site_player_id' => 'ws-auth-owner',
'default_currency' => 'NPR',
'status' => 0,
]);
$otherPlayer = Player::query()->create([
'site_code' => 'test',
'site_player_id' => 'ws-auth-other',
'default_currency' => 'NPR',
'status' => 0,
]);
$payload = [
'socket_id' => '1234.5678',
'channel_name' => 'private-player.'.$player->id,
];
$this->postJson('/api/broadcasting/auth', $payload)
->assertUnauthorized();
$this->withHeader('Authorization', 'Bearer dev:'.$otherPlayer->id)
->postJson('/api/broadcasting/auth', $payload)
->assertForbidden();
$this->withHeader('Authorization', 'Bearer dev:'.$player->id)
->postJson('/api/broadcasting/auth', $payload)
->assertOk()
->assertJsonStructure(['auth']);
});
test('wallet balance notifier dispatches balance update broadcast', function (): void {
Event::fake([BalanceUpdateBroadcast::class]);
@@ -109,11 +162,11 @@ test('risk pool acquire dispatches warning and sold out broadcasts', function ()
test('risk cap publish dispatches play catalog updated broadcast', function (): void {
Event::fake([PlayCatalogUpdatedBroadcast::class]);
$admin = \App\Models\AdminUser::query()->create([
$admin = AdminUser::query()->create([
'username' => 'risk_cap_admin',
'name' => 'Risk Cap QA',
'email' => null,
'password' => \Illuminate\Support\Facades\Hash::make('secret-strong'),
'password' => Hash::make('secret-strong'),
'status' => 0,
]);
grantSuperAdminRole($admin);