diff --git a/admin.html b/admin.html index fee37e7..a426e69 100644 --- a/admin.html +++ b/admin.html @@ -611,7 +611,7 @@

Платежи и вебхуки

Вкладка Платежи → «Настройка приёма платежей» собирает публичную оферту и политику конфиденциальности (/offer, /privacy) из введённых реквизитов — ЮKassa их спросит при регистрации магазина. Дата вступления в силу проставляется один раз, правки реквизитов её не двигают.

Ключи ЮKassa проверяются вживую через их /v3/me перед сохранением; у Platega такого эндпоинта нет, ключи сохраняются без проверки. Оба провайдера включаются независимо.

-

Исходящие вебхуки (Настройки → Webhook на события) — панель стучится на указанный URL при оплате (payment.paid) и ручной выдаче подписки админом (subscription.granted_by_admin), тело подписано X-Signature (HMAC-SHA256). Секрет выдаётся один раз и не меняется при правке URL — для интеграций со своими системами, без опроса API.

+

Исходящие вебхуки (Настройки → Webhook на события) — панель стучится на указанный URL при оплате (payment.paid), ручной выдаче подписки админом (subscription.granted_by_admin), отзыве (subscription.revoked), постановке на паузу (subscription.held) и возобновлении (subscription.resumed). Тело подписано X-Signature (HMAC-SHA256). Секрет выдаётся один раз и не меняется при правке URL — для интеграций со своими системами, без опроса API.

Вкладка Платежи → «Тарифы» — цены по срокам и общий рубильник приёма оплаты. Как и реквизиты с ключами провайдеров, это читается панелью напрямую из .env при каждом запросе — правки в UI применяются мгновенно везде (бот, API, проверка вебхуков), рестарт панели нигде не требуется.

@@ -718,7 +718,7 @@

- События: payment.paid, subscription.granted_by_admin. Тело — JSON {"event": "...", "data": {...}}, подписано заголовком X-Signature (HMAC-SHA256 от тела запроса на секрете ниже) — так получатель проверяет, что запрос реально от панели. + События: payment.paid, subscription.granted_by_admin, subscription.revoked, subscription.held, subscription.resumed. Тело — JSON {"event": "...", "data": {...}}, подписано заголовком X-Signature (HMAC-SHA256 от тела запроса на секрете ниже) — так получатель проверяет, что запрос реально от панели. Секрет для проверки: —

diff --git a/api.py b/api.py index b1fbd69..55b3b69 100644 --- a/api.py +++ b/api.py @@ -887,6 +887,9 @@ def admin_revoke_subscription(uuid: str, request: Request): if node: xray_manager.remove_client_from_node(node, uuid) db.revoke_subscription(uuid) + webhooks.send("subscription.revoked", { + "tg_id": sub["tg_id"], "node": sub["node"], "plan": sub["plan"], "subscription_uuid": uuid, + }) return {"ok": True} @@ -901,6 +904,9 @@ def admin_hold_subscription(uuid: str, request: Request): node = db.get_node(sub["node"]) if node: xray_manager.remove_client_from_node(node, uuid) + webhooks.send("subscription.held", { + "tg_id": sub["tg_id"], "node": sub["node"], "plan": sub["plan"], "subscription_uuid": uuid, + }) return {"ok": True} @@ -913,6 +919,10 @@ def admin_resume_subscription(uuid: str, request: Request): node = db.get_node(resumed["node"]) if node: xray_manager.add_client_to_node(node, uuid, email=uuid) + webhooks.send("subscription.resumed", { + "tg_id": resumed["tg_id"], "node": resumed["node"], "plan": resumed["plan"], + "subscription_uuid": uuid, "expires_at": resumed["expires_at"], + }) return {"ok": True, "expires_at": resumed["expires_at"]}