234 lines
9.0 KiB
Python
234 lines
9.0 KiB
Python
"""Сборка платёжных клиентов и публичный payload для админки."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
from config import Settings, get_settings
|
|
from services.anypay import Anypay
|
|
from services.cryptopay import CryptoPay
|
|
from services.digiseller import Digiseller
|
|
from services.env_file import (
|
|
BOOL_ENV_KEYS,
|
|
PAYMENT_ENV_KEYS,
|
|
SECRET_ENV_KEYS,
|
|
env_file_path,
|
|
env_writable,
|
|
mask_secret,
|
|
upsert_env_keys,
|
|
)
|
|
from services.heleket import Heleket
|
|
from services.lava import Lava
|
|
|
|
|
|
def build_payment_clients(settings: Settings) -> dict[str, Any]:
|
|
return {
|
|
"cryptopay": CryptoPay(
|
|
settings.crypto_bot_token,
|
|
testnet=settings.crypto_pay_testnet,
|
|
),
|
|
"heleket": Heleket(
|
|
settings.heleket_merchant_id,
|
|
settings.heleket_api_key,
|
|
callback_url=settings.heleket_callback_url,
|
|
currency=settings.heleket_currency,
|
|
),
|
|
"digiseller": Digiseller(
|
|
settings.digiseller_seller_id,
|
|
settings.digiseller_api_key,
|
|
product_ids=settings.digiseller_product_ids,
|
|
pay_url=settings.digiseller_pay_url,
|
|
credit_from=settings.digiseller_credit_from,
|
|
),
|
|
"lava": Lava(
|
|
settings.lava_shop_id,
|
|
settings.lava_secret_key,
|
|
additional_key=settings.lava_additional_key,
|
|
hook_url=settings.lava_hook_url,
|
|
success_url=settings.lava_success_url,
|
|
fail_url=settings.lava_fail_url,
|
|
expire_minutes=settings.lava_expire_minutes,
|
|
),
|
|
"anypay": Anypay(
|
|
settings.anypay_api_id,
|
|
settings.anypay_api_key,
|
|
settings.anypay_project_id,
|
|
currency=settings.anypay_currency,
|
|
method=settings.anypay_method,
|
|
success_url=settings.anypay_success_url,
|
|
fail_url=settings.anypay_fail_url,
|
|
default_email=settings.anypay_email or "pay@anypay.local",
|
|
check_ip=settings.anypay_check_ip,
|
|
),
|
|
}
|
|
|
|
|
|
def apply_payment_runtime(app: Any, settings: Settings) -> dict[str, Any]:
|
|
clients = build_payment_clients(settings)
|
|
app["settings"] = settings
|
|
app["cryptopay"] = clients["cryptopay"]
|
|
app["heleket"] = clients["heleket"]
|
|
app["digiseller"] = clients["digiseller"]
|
|
app["lava"] = clients["lava"]
|
|
app["anypay"] = clients["anypay"]
|
|
|
|
inject = app.get("inject")
|
|
if inject is not None:
|
|
inject.settings = settings
|
|
inject.cryptopay = clients["cryptopay"]
|
|
inject.heleket = clients["heleket"]
|
|
inject.digiseller = clients["digiseller"]
|
|
inject.lava = clients["lava"]
|
|
inject.anypay = clients["anypay"]
|
|
return clients
|
|
|
|
|
|
def payments_public_dict(settings: Settings) -> dict[str, Any]:
|
|
path = env_file_path()
|
|
return {
|
|
"env_path": str(path),
|
|
"env_writable": env_writable(path),
|
|
"crypto": {
|
|
"enabled": bool(settings.crypto_bot_token),
|
|
"token_set": bool(settings.crypto_bot_token),
|
|
"token_hint": mask_secret(settings.crypto_bot_token),
|
|
"testnet": bool(settings.crypto_pay_testnet),
|
|
},
|
|
"heleket": {
|
|
"enabled": bool(settings.heleket_merchant_id and settings.heleket_api_key),
|
|
"merchant_id": settings.heleket_merchant_id,
|
|
"api_key_set": bool(settings.heleket_api_key),
|
|
"api_key_hint": mask_secret(settings.heleket_api_key),
|
|
"callback_url": settings.heleket_callback_url,
|
|
"currency": settings.heleket_currency or "RUB",
|
|
},
|
|
"lava": {
|
|
"enabled": bool(settings.lava_shop_id and settings.lava_secret_key),
|
|
"shop_id": settings.lava_shop_id,
|
|
"secret_key_set": bool(settings.lava_secret_key),
|
|
"secret_key_hint": mask_secret(settings.lava_secret_key),
|
|
"additional_key_set": bool(settings.lava_additional_key),
|
|
"additional_key_hint": mask_secret(settings.lava_additional_key),
|
|
"hook_url": settings.lava_hook_url,
|
|
"success_url": settings.lava_success_url,
|
|
"fail_url": settings.lava_fail_url,
|
|
"expire_minutes": settings.lava_expire_minutes,
|
|
},
|
|
"anypay": {
|
|
"enabled": bool(
|
|
settings.anypay_api_id
|
|
and settings.anypay_api_key
|
|
and settings.anypay_project_id
|
|
),
|
|
"api_id": settings.anypay_api_id,
|
|
"api_key_set": bool(settings.anypay_api_key),
|
|
"api_key_hint": mask_secret(settings.anypay_api_key),
|
|
"project_id": settings.anypay_project_id,
|
|
"currency": settings.anypay_currency or "RUB",
|
|
"method": settings.anypay_method,
|
|
"success_url": settings.anypay_success_url,
|
|
"fail_url": settings.anypay_fail_url,
|
|
"email": settings.anypay_email,
|
|
"check_ip": bool(settings.anypay_check_ip),
|
|
"notify_url": (
|
|
f"{settings.webapp_url.rstrip('/')}/api/payments/anypay"
|
|
if settings.webapp_url
|
|
else "/api/payments/anypay"
|
|
),
|
|
},
|
|
"digiseller": {
|
|
"enabled": bool(settings.digiseller_seller_id and settings.digiseller_api_key),
|
|
"seller_id": settings.digiseller_seller_id,
|
|
"api_key_set": bool(settings.digiseller_api_key),
|
|
"api_key_hint": mask_secret(settings.digiseller_api_key),
|
|
"product_ids": ",".join(str(x) for x in settings.digiseller_product_ids),
|
|
"pay_url": settings.digiseller_pay_url,
|
|
"credit_from": settings.digiseller_credit_from or "cnt_goods",
|
|
"callback_url": settings.digiseller_callback_url,
|
|
},
|
|
"stars": {
|
|
"enabled": bool(settings.stars_enabled),
|
|
"rub_per_star": settings.stars_rub_per_star,
|
|
},
|
|
"topup_code_pay_url": settings.topup_code_pay_url,
|
|
}
|
|
|
|
|
|
def _is_masked_placeholder(value: str) -> bool:
|
|
v = (value or "").strip()
|
|
if not v:
|
|
return True
|
|
return "…" in v or "•" in v or "..." in v
|
|
|
|
|
|
def apply_payments_body(body: dict[str, Any]) -> Settings:
|
|
"""Применить тело POST админки: .env + os.environ + новый Settings."""
|
|
updates: dict[str, str | None] = {}
|
|
|
|
mapping = {
|
|
"CRYPTO_BOT_TOKEN": body.get("crypto_bot_token"),
|
|
"CRYPTO_PAY_TESTNET": body.get("crypto_pay_testnet"),
|
|
"HELEKET_MERCHANT_ID": body.get("heleket_merchant_id"),
|
|
"HELEKET_API_KEY": body.get("heleket_api_key"),
|
|
"HELEKET_CALLBACK_URL": body.get("heleket_callback_url"),
|
|
"HELEKET_CURRENCY": body.get("heleket_currency"),
|
|
"LAVA_SHOP_ID": body.get("lava_shop_id"),
|
|
"LAVA_SECRET_KEY": body.get("lava_secret_key"),
|
|
"LAVA_ADDITIONAL_KEY": body.get("lava_additional_key"),
|
|
"LAVA_HOOK_URL": body.get("lava_hook_url"),
|
|
"LAVA_SUCCESS_URL": body.get("lava_success_url"),
|
|
"LAVA_FAIL_URL": body.get("lava_fail_url"),
|
|
"LAVA_EXPIRE_MINUTES": body.get("lava_expire_minutes"),
|
|
"ANYPAY_API_ID": body.get("anypay_api_id"),
|
|
"ANYPAY_API_KEY": body.get("anypay_api_key"),
|
|
"ANYPAY_PROJECT_ID": body.get("anypay_project_id"),
|
|
"ANYPAY_CURRENCY": body.get("anypay_currency"),
|
|
"ANYPAY_METHOD": body.get("anypay_method"),
|
|
"ANYPAY_SUCCESS_URL": body.get("anypay_success_url"),
|
|
"ANYPAY_FAIL_URL": body.get("anypay_fail_url"),
|
|
"ANYPAY_EMAIL": body.get("anypay_email"),
|
|
"ANYPAY_CHECK_IP": body.get("anypay_check_ip"),
|
|
"DIGISELLER_SELLER_ID": body.get("digiseller_seller_id"),
|
|
"DIGISELLER_API_KEY": body.get("digiseller_api_key"),
|
|
"DIGISELLER_PRODUCT_IDS": body.get("digiseller_product_ids"),
|
|
"DIGISELLER_PAY_URL": body.get("digiseller_pay_url"),
|
|
"DIGISELLER_CREDIT_FROM": body.get("digiseller_credit_from"),
|
|
"DIGISELLER_CALLBACK_URL": body.get("digiseller_callback_url"),
|
|
"STARS_ENABLED": body.get("stars_enabled"),
|
|
"STARS_RUB_PER_STAR": body.get("stars_rub_per_star"),
|
|
"TOPUP_CODE_PAY_URL": body.get("topup_code_pay_url"),
|
|
}
|
|
|
|
for env_key, raw in mapping.items():
|
|
if env_key not in PAYMENT_ENV_KEYS:
|
|
continue
|
|
if raw is None:
|
|
continue
|
|
if env_key in BOOL_ENV_KEYS:
|
|
if isinstance(raw, bool):
|
|
updates[env_key] = "true" if raw else "false"
|
|
else:
|
|
updates[env_key] = (
|
|
"true"
|
|
if str(raw).strip().lower() in {"1", "true", "yes", "on"}
|
|
else "false"
|
|
)
|
|
continue
|
|
|
|
text = str(raw).strip()
|
|
if env_key in SECRET_ENV_KEYS:
|
|
if text == "__clear__":
|
|
updates[env_key] = None
|
|
elif _is_masked_placeholder(text):
|
|
continue
|
|
else:
|
|
updates[env_key] = text
|
|
continue
|
|
|
|
updates[env_key] = text if text else None
|
|
|
|
if updates:
|
|
upsert_env_keys(updates)
|
|
|
|
return get_settings(require_bot_token=False)
|