feat: show payment provider webhook urls

This commit is contained in:
3252a8
2026-05-22 15:57:49 +03:00
parent f5023dc46b
commit 648f4ba4bc
10 changed files with 326 additions and 3 deletions
@@ -13,6 +13,7 @@ async def admin_settings_get_route(request: web.Request) -> web.Response:
overrides_by_key = {entry["key"]: entry for entry in overrides}
fields = manifest_payload()
webhook_base_url = str(settings.WEBHOOK_BASE_URL or "").strip().rstrip("/")
sections: Dict[str, Dict[str, Any]] = {}
for field in fields:
key = field["key"]
@@ -34,6 +35,14 @@ async def admin_settings_get_route(request: web.Request) -> web.Response:
}
if is_secret:
response_field["has_value"] = bool(value)
webhook_path = str(response_field.get("webhook_path") or "").strip()
if webhook_path:
if not webhook_path.startswith("/"):
webhook_path = f"/{webhook_path}"
response_field["webhook_path"] = webhook_path
response_field["webhook_base_url_configured"] = bool(webhook_base_url)
if webhook_base_url:
response_field["webhook_url"] = f"{webhook_base_url}{webhook_path}"
sections[section_id]["fields"].append(response_field)
ordered_sections = sorted(sections.values(), key=lambda s: s["order"])
@@ -507,7 +507,11 @@ def manifest_payload() -> List[dict]:
same value so existing UIs that only read ``placeholder`` also show the
hint inside the empty input.
"""
from bot.payment_providers import find_manifest_owner, manifest_field_default
from bot.payment_providers import (
find_manifest_owner,
manifest_field_default,
provider_webhook_metadata,
)
sections_order = {
"general": 1,
@@ -531,10 +535,12 @@ def manifest_payload() -> List[dict]:
)
default_value: Optional[str] = None
webhook_metadata: Optional[dict] = None
owner = find_manifest_owner(field.key)
if owner is not None:
spec, manifest_field = owner
default_value = manifest_field_default(spec, manifest_field)
webhook_metadata = provider_webhook_metadata(spec)
placeholder = field.placeholder
if not placeholder and default_value:
@@ -561,6 +567,8 @@ def manifest_payload() -> List[dict]:
}
if default_value is not None:
item["default"] = default_value
if webhook_metadata:
item.update(webhook_metadata)
if field.choices:
item["choices"] = [
{
@@ -25,6 +25,7 @@ from .registry import (
provider_emoji_map,
provider_label_map,
provider_telegram_button_text,
provider_webhook_metadata,
resolve_provider_presentation,
)
@@ -53,5 +54,6 @@ __all__ = [
"provider_telegram_button_text",
"provider_emoji_map",
"provider_label_map",
"provider_webhook_metadata",
"resolve_provider_presentation",
]
+40
View File
@@ -333,6 +333,46 @@ def find_manifest_owner(key: str) -> Optional[tuple[PaymentProviderSpec, Provide
return None
def _webhook_spec_for(spec: PaymentProviderSpec) -> Optional[PaymentProviderSpec]:
if spec.webhook_path and spec.webhook_route:
return spec
if not spec.service_key:
return None
for candidate in PAYMENT_PROVIDER_SPECS:
if (
candidate.service_key == spec.service_key
and candidate.webhook_path
and candidate.webhook_route
):
return candidate
return None
def provider_webhook_metadata(spec: PaymentProviderSpec) -> Optional[Dict[str, Any]]:
"""Return admin-manifest webhook metadata for a provider SPEC.
Some visible payment buttons share one backing service and webhook route
(for example Platega SBP and Platega Crypto), so presentation-only specs
inherit the route from their service sibling.
"""
webhook_spec = _webhook_spec_for(spec)
if webhook_spec is None or not webhook_spec.webhook_path:
return None
try:
path = str(webhook_spec.webhook_path(None) or "").strip()
except Exception:
return None
if not path:
return None
return {
"provider_id": spec.id,
"provider_label": spec.label,
"webhook_provider_id": webhook_spec.id,
"webhook_path": path,
"webhook_requires_base_url": bool(webhook_spec.webhook_requires_base_url),
}
def manifest_field_default(
spec: PaymentProviderSpec,
manifest_field: ProviderManifestField,