feat: 增强钱包 API URL 验证与配置
- 在 AdminIntegrationSiteStoreRequest 和 AdminIntegrationSiteUpdateRequest 中引入 WalletApiUrlRule,确保 wallet_api_url 字段符合 HTTPS 公开域名要求。 - 更新 HttpMainSiteWalletBalanceClient 和 HttpMainSiteWalletGateway,使用 WalletApiUrlSanitizer 进行 URL 规范化与验证,防止 SSRF 攻击。 - 新增测试用例,验证 wallet_api_url 的有效性,确保系统安全性与稳定性。 - 更新 .env.example 文件,添加 LOTTERY_RISK_POOL_USE_REDIS_LUA 配置项以支持 Redis Lua 原子扣减功能。 - 修改 package-lock.json 中的项目名称,确保一致性。 - 在 API 路由中新增 integration/runtime-origins 路由,提供运行时白名单功能。
This commit is contained in:
@@ -6,6 +6,7 @@ use App\Models\Player;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use GuzzleHttp\Exception\ConnectException;
|
||||
use App\Services\Integration\PartnerSiteConfigResolver;
|
||||
use App\Support\Integration\WalletApiUrlSanitizer;
|
||||
|
||||
/**
|
||||
* 通过 HTTP 调用主站钱包 API(路径见 config lottery.main_site.wallet_*_path)。
|
||||
@@ -61,7 +62,7 @@ final class HttpMainSiteWalletGateway implements MainSiteWalletGateway
|
||||
\App\Services\Integration\PartnerSiteConfig $config,
|
||||
): MainSiteWalletResult {
|
||||
if (! $config->hasWalletApi()) {
|
||||
return MainSiteWalletResult::success(null, ['stub' => true, 'reason' => 'wallet_api_not_configured'], [
|
||||
$requestSnapshot = [
|
||||
'site_code' => $player->site_code,
|
||||
'site_player_id' => $player->site_player_id,
|
||||
'player_id' => $player->id,
|
||||
@@ -69,10 +70,44 @@ final class HttpMainSiteWalletGateway implements MainSiteWalletGateway
|
||||
'amount_minor' => $amountMinor,
|
||||
'idempotent_key' => $idempotentKey,
|
||||
'_meta' => ['stub' => true],
|
||||
]);
|
||||
];
|
||||
|
||||
// 生产环境不允许把“主站未配置钱包 API”当作成功,从而避免资金链路失真。
|
||||
if (app()->environment(['production'])) {
|
||||
return MainSiteWalletResult::failure(
|
||||
'wallet_api_not_configured',
|
||||
['stub' => false, 'reason' => 'wallet_api_not_configured'],
|
||||
false,
|
||||
$requestSnapshot,
|
||||
);
|
||||
}
|
||||
|
||||
// 本地/测试环境允许 stub 成功,方便联调与自动化用例覆盖资金链路流程。
|
||||
return MainSiteWalletResult::success(
|
||||
null,
|
||||
['stub' => true, 'reason' => 'wallet_api_not_configured'],
|
||||
$requestSnapshot,
|
||||
);
|
||||
}
|
||||
|
||||
$base = WalletApiUrlSanitizer::normalizeAndValidate($config->walletApiUrl);
|
||||
if ($base === null) {
|
||||
return MainSiteWalletResult::failure(
|
||||
'wallet_api_url_invalid',
|
||||
['reason' => 'invalid_base_url'],
|
||||
false,
|
||||
[
|
||||
'site_code' => $player->site_code,
|
||||
'site_player_id' => $player->site_player_id,
|
||||
'player_id' => $player->id,
|
||||
'currency_code' => $currencyCode,
|
||||
'amount_minor' => $amountMinor,
|
||||
'idempotent_key' => $idempotentKey,
|
||||
'_meta' => ['stub' => true, 'operation' => 'invalid_wallet_api_url'],
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
$base = rtrim((string) $config->walletApiUrl, '/');
|
||||
$url = $base.'/'.ltrim($path, '/');
|
||||
$timeout = $config->walletTimeoutSeconds;
|
||||
$apiKey = $config->walletApiKey;
|
||||
|
||||
Reference in New Issue
Block a user