diff --git a/backend/bot/app/web/webapp/billing.py b/backend/bot/app/web/webapp/billing.py index c8ef1a6..dd629ba 100644 --- a/backend/bot/app/web/webapp/billing.py +++ b/backend/bot/app/web/webapp/billing.py @@ -655,7 +655,13 @@ async def _create_subscription_payment( provider_spec = get_provider_spec(method) if provider_spec and provider_spec.create_webapp_payment: - if not provider_spec.is_enabled(settings): + if not provider_spec.is_visible(settings, request.app): + logger.warning( + "WebApp payment method unavailable: method=%s enabled=%s configured=%s", + method, + provider_spec.is_enabled(settings), + provider_spec.is_service_configured(request.app), + ) return _json_error(400, "payment_unavailable", "Payment method unavailable") return await provider_spec.create_webapp_payment( WebAppPaymentContext( diff --git a/backend/bot/payment_providers/freekassa.py b/backend/bot/payment_providers/freekassa.py index 0e733a4..9940206 100644 --- a/backend/bot/payment_providers/freekassa.py +++ b/backend/bot/payment_providers/freekassa.py @@ -274,7 +274,18 @@ class FreeKassaService(HttpClientMixin): try: client_ip = request_client_ip(request, trusted_proxies=self.settings.trusted_proxies) - if not ip_in_allowlist(client_ip, self.config.trusted_ips_list): + trusted = self.config.trusted_ips_list + if not ip_in_allowlist(client_ip, trusted): + logging.warning( + "FreeKassa webhook denied from unauthorized IP source " + "(client_ip=%s remote=%s x_forwarded_for=%s trusted_ips=%s " + "trusted_proxies=%s).", + client_ip, + request.remote, + request.headers.get("X-Forwarded-For"), + trusted, + self.settings.trusted_proxies, + ) return web.Response(status=403) raw_body = await request.read() diff --git a/backend/bot/payment_providers/heleket.py b/backend/bot/payment_providers/heleket.py index d27708d..a14525e 100644 --- a/backend/bot/payment_providers/heleket.py +++ b/backend/bot/payment_providers/heleket.py @@ -308,7 +308,15 @@ class HeleketService(HttpClientMixin): client_ip = request_client_ip(request, trusted_proxies=self.settings.trusted_proxies) trusted = self.config.trusted_ips_list if trusted and not ip_in_allowlist(client_ip, trusted): - logging.warning("Heleket webhook denied from unauthorized IP source.") + logging.warning( + "Heleket webhook denied from unauthorized IP source " + "(client_ip=%s remote=%s x_forwarded_for=%s trusted_ips=%s trusted_proxies=%s).", + client_ip, + request.remote, + request.headers.get("X-Forwarded-For"), + trusted, + self.settings.trusted_proxies, + ) return web.Response(status=403, text="forbidden") raw_body = await request.read() diff --git a/backend/bot/payment_providers/wata.py b/backend/bot/payment_providers/wata.py index 40cceec..4d92f89 100644 --- a/backend/bot/payment_providers/wata.py +++ b/backend/bot/payment_providers/wata.py @@ -263,7 +263,15 @@ class WataService(HttpClientMixin): client_ip = request_client_ip(request, trusted_proxies=self.settings.trusted_proxies) trusted = self.config.trusted_ips_list if trusted and not ip_in_allowlist(client_ip, trusted): - logging.warning("Wata webhook denied from unauthorized IP source.") + logging.warning( + "Wata webhook denied from unauthorized IP source " + "(client_ip=%s remote=%s x_forwarded_for=%s trusted_ips=%s trusted_proxies=%s).", + client_ip, + request.remote, + request.headers.get("X-Forwarded-For"), + trusted, + self.settings.trusted_proxies, + ) return web.Response(status=403, text="forbidden") raw_body = await request.read() diff --git a/backend/bot/payment_providers/yookassa.py b/backend/bot/payment_providers/yookassa.py index 42b586c..2427a85 100644 --- a/backend/bot/payment_providers/yookassa.py +++ b/backend/bot/payment_providers/yookassa.py @@ -861,7 +861,15 @@ async def yookassa_webhook_route(request: web.Request): client_ip = request_client_ip(request, trusted_proxies=settings.trusted_proxies) if not ip_in_allowlist(client_ip, YOOKASSA_WEBHOOK_ALLOWED_IPS): - logging.warning("YooKassa webhook denied from unauthorized IP source.") + logging.warning( + "YooKassa webhook denied from unauthorized IP source " + "(client_ip=%s remote=%s x_forwarded_for=%s trusted_ips=%s trusted_proxies=%s).", + client_ip, + request.remote, + request.headers.get("X-Forwarded-For"), + YOOKASSA_WEBHOOK_ALLOWED_IPS, + settings.trusted_proxies, + ) return web.Response(status=403) try: diff --git a/deploy/compose/docker-compose-caddy.yml b/deploy/compose/docker-compose-caddy.yml index e4c4a00..9e88123 100644 --- a/deploy/compose/docker-compose-caddy.yml +++ b/deploy/compose/docker-compose-caddy.yml @@ -60,6 +60,7 @@ services: POSTGRES_HOST: postgres REDIS_URL: redis://redis:6379/0 WEBAPP_ENABLED: "true" + TRUSTED_PROXIES: ${TRUSTED_PROXIES:-127.0.0.1,::1,172.16.0.0/12} volumes: - shop-data:/app/data networks: diff --git a/frontend/src/App.svelte b/frontend/src/App.svelte index 022223c..fbb9161 100644 --- a/frontend/src/App.svelte +++ b/frontend/src/App.svelte @@ -421,8 +421,15 @@ ) { billingStore.update((s) => ({ ...s, selectedPlan: selectedTariffPlans[0] || null })); } - $: if (!$billingStore.selectedMethod && methods.length) { - billingStore.update((s) => ({ ...s, selectedMethod: methods[0].id })); + $: if (methods.length) { + const selectedMethodAvailable = methods.some( + (method) => method.id === $billingStore.selectedMethod + ); + if (!$billingStore.selectedMethod || !selectedMethodAvailable) { + billingStore.update((s) => ({ ...s, selectedMethod: methods[0].id })); + } + } else if ($billingStore.selectedMethod) { + billingStore.update((s) => ({ ...s, selectedMethod: "" })); } $: { const emailKey = normalizedEmail(user?.email);