ThirdGameCommissionRatesTest.php 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. <?php
  2. namespace Tests\Integration;
  3. use App\Services\ThirdGameBalanceService;
  4. use App\Services\ThirdGameCommissionService;
  5. use Carbon\Carbon;
  6. use Illuminate\Cache\ArrayStore;
  7. use Illuminate\Cache\Repository as CacheRepository;
  8. use Illuminate\Config\Repository;
  9. use Illuminate\Foundation\Application;
  10. use Illuminate\Http\Client\Factory;
  11. use Illuminate\Support\Facades\Facade;
  12. use Illuminate\Support\Facades\Http;
  13. use PHPUnit\Framework\TestCase;
  14. class ThirdGameCommissionRatesTest extends TestCase
  15. {
  16. protected function setUp(): void
  17. {
  18. Facade::clearResolvedInstances();
  19. $app = new Application(dirname(__DIR__, 2));
  20. $app->instance('config', new Repository(['third_game' => [
  21. 'api_url' => 'https://supplier.test', 'sn' => 'test-merchant', 'key' => 'test-secret', 'currency' => 'CNY',
  22. ]]));
  23. $app->instance('cache', new CacheRepository(new ArrayStore()));
  24. $app->instance(Factory::class, new Factory());
  25. $app->instance('log', new \Psr\Log\NullLogger());
  26. Facade::setFacadeApplication($app);
  27. Carbon::setTestNow(Carbon::parse('2026-11-04 12:00:00', 'Asia/Shanghai'));
  28. Http::preventStrayRequests();
  29. }
  30. protected function tearDown(): void
  31. {
  32. Carbon::setTestNow(); Facade::clearResolvedInstances(); parent::tearDown();
  33. }
  34. public function test_documented_platform_spelling_zero_rates_and_daily_refresh(): void
  35. {
  36. Http::fake(['https://supplier.test/api/server/quota' => Http::sequence()
  37. ->push(['code' => 10000, 'data' => ['ratios' => [
  38. ['platfrom' => ' AG ', 'ratio' => 0.09], ['platfrom' => 'pg', 'ratio' => '0'],
  39. ]]])
  40. ->push(['code' => 10000, 'data' => ['ratios' => [['platfrom' => 'ag', 'ratio' => '0.10']]]])]);
  41. $service = new ThirdGameCommissionService();
  42. $first = $service->rates();
  43. $this->assertSame(['ag' => '0.0900000000', 'pg' => '0.0000000000'], $first['ratios']);
  44. $this->assertSame($first, (new ThirdGameCommissionService())->rates());
  45. Http::assertSentCount(1);
  46. Http::assertSent(fn ($request) => $request->method() === 'POST' && $request['currency'] === 'CNY'
  47. && $request->hasHeader('sn', 'test-merchant') && $request->hasHeader('sign'));
  48. Carbon::setTestNow(Carbon::parse('2026-11-05 00:00:01', 'Asia/Shanghai'));
  49. $this->assertSame('0.1000000000', $service->rates()['ratios']['ag']);
  50. Http::assertSentCount(2);
  51. }
  52. public function test_provider_failure_is_cached_for_the_day_and_does_not_turn_into_a_zero_rate(): void
  53. {
  54. Http::fake(['*' => Http::response(['code' => 10404, 'data' => null])]);
  55. $service = new ThirdGameCommissionService();
  56. $this->assertFalse($service->rates()['available']);
  57. $this->assertSame([], $service->rates()['ratios']);
  58. Http::assertSentCount(1);
  59. }
  60. public function test_merchant_balance_shares_the_quota_request_and_preserves_the_last_success_on_failure(): void
  61. {
  62. Http::fake(['https://supplier.test/api/server/quota' => Http::sequence()
  63. ->push(['code' => 10000, 'data' => ['CNY' => '100.125', 'ratios' => []]])
  64. ->push(['code' => 10009, 'data' => null])
  65. ->push(['code' => 10000, 'data' => ['CNY' => '0', 'ratios' => []]])]);
  66. $service = new ThirdGameBalanceService();
  67. $start = now();
  68. $this->assertNull($service->merchantBalance()['balance']);
  69. Http::assertNothingSent();
  70. $service->refreshMerchantBalance();
  71. $this->assertTrue($service->quotaRatios()['ok']);
  72. $this->assertSame(['balance' => '100.1250000000', 'currency' => 'CNY', 'stale' => false], $service->merchantBalance());
  73. Carbon::setTestNow($start->copy()->addSeconds(59));
  74. $service->refreshMerchantBalance();
  75. Http::assertSentCount(1);
  76. Carbon::setTestNow($start->copy()->addSeconds(60));
  77. $service->refreshMerchantBalance();
  78. $service->refreshMerchantBalance();
  79. $this->assertSame(['balance' => '100.1250000000', 'currency' => 'CNY', 'stale' => true], $service->merchantBalance());
  80. Http::assertSentCount(2);
  81. Carbon::setTestNow($start->copy()->addSeconds(120));
  82. $service->refreshMerchantBalance();
  83. $this->assertSame(['balance' => '0.0000000000', 'currency' => 'CNY', 'stale' => false], $service->merchantBalance());
  84. Http::assertSentCount(3);
  85. }
  86. public function test_the_shared_quota_cooldown_does_not_reuse_yesterdays_rates(): void
  87. {
  88. Http::fake(['*' => Http::sequence()
  89. ->push(['code' => 10000, 'data' => ['CNY' => '10', 'ratios' => [['platfrom' => 'ag', 'ratio' => '0.1']]]])
  90. ->push(['code' => 10000, 'data' => ['CNY' => '10', 'ratios' => [['platfrom' => 'ag', 'ratio' => '0.2']]]])]);
  91. Carbon::setTestNow(Carbon::parse('2026-11-04 23:59:50', 'Asia/Shanghai'));
  92. (new ThirdGameBalanceService())->refreshMerchantBalance();
  93. Carbon::setTestNow(Carbon::parse('2026-11-05 00:00:00', 'Asia/Shanghai'));
  94. $service = new ThirdGameCommissionService();
  95. $this->assertFalse($service->rates()['available']);
  96. Http::assertSentCount(1);
  97. Carbon::setTestNow(Carbon::parse('2026-11-05 00:01:00', 'Asia/Shanghai'));
  98. $this->assertSame(['ag' => '0.2000000000'], $service->rates()['ratios']);
  99. Http::assertSentCount(2);
  100. }
  101. public function test_malformed_and_conflicting_rates_are_not_accepted_and_merchant_caches_are_isolated(): void
  102. {
  103. Http::fake(['*' => Http::response(['code' => 10000, 'data' => ['ratios' => [
  104. ['platfrom' => 'negative', 'ratio' => '-0.1'], ['platfrom' => 'large', 'ratio' => '1.01'],
  105. ['platfrom' => 'bad', 'ratio' => 'NaN'], ['platfrom' => 'ag', 'ratio' => '.09'],
  106. ['platfrom' => 'pg', 'ratio' => '0.1'], ['platfrom' => 'PG', 'ratio' => '0.2'],
  107. ['platform' => 'pp', 'ratio' => '0.1234567891'],
  108. ]]])]);
  109. $service = new ThirdGameCommissionService();
  110. $this->assertSame(['pp' => '0.1234567891'], $service->rates()['ratios']);
  111. config(['third_game.sn' => 'another-merchant']);
  112. $service->rates(); Http::assertSentCount(2);
  113. config(['third_game.currency' => 'USD']);
  114. $service->rates(); Http::assertSentCount(3);
  115. }
  116. }