feat: add multiple platega buttons
This commit is contained in:
+5
-1
@@ -107,7 +107,11 @@ CRYPTOPAY_ASSET=RUB #
|
||||
PLATEGA_BASE_URL=https://app.platega.io # Base API URL
|
||||
PLATEGA_MERCHANT_ID= # Your MerchantId from Platega
|
||||
PLATEGA_SECRET= # API secret from Platega
|
||||
PLATEGA_PAYMENT_METHOD=2 # Payment method ID (2=SBP QR, 10=RU cards, 12=International, 13=Crypto)
|
||||
PLATEGA_PAYMENT_METHOD=2 # Legacy method ID; fallback for the SBP button when PLATEGA_SBP_METHOD stays default
|
||||
PLATEGA_SBP_ENABLED=False # Show a separate "Pay via SBP" Platega button
|
||||
PLATEGA_CRYPTO_ENABLED=False # Show a separate "Pay with crypto" Platega button
|
||||
PLATEGA_SBP_METHOD=2 # Platega method ID for SBP QR (default 2)
|
||||
PLATEGA_CRYPTO_METHOD=13 # Platega method ID for crypto (default 13)
|
||||
PLATEGA_RETURN_URL= # Optional: redirect after successful payment (defaults to bot link)
|
||||
PLATEGA_FAILED_URL= # Optional: redirect after failed/cancelled payment (defaults to return URL)
|
||||
|
||||
|
||||
@@ -2066,7 +2066,8 @@ def _serialize_payment_methods(
|
||||
labels = {
|
||||
"severpay": "SeverPay",
|
||||
"freekassa": "FreeKassa / СБП",
|
||||
"platega": "Platega",
|
||||
"platega_sbp": "Platega · СБП",
|
||||
"platega_crypto": "Platega · Crypto",
|
||||
"yookassa": "Банковская карта",
|
||||
"stars": "Telegram Stars",
|
||||
"cryptopay": "CryptoPay",
|
||||
@@ -2078,7 +2079,9 @@ def _serialize_payment_methods(
|
||||
methods.append({"id": method, "name": labels[method]})
|
||||
elif method == "freekassa" and _service_configured(app, "freekassa_service"):
|
||||
methods.append({"id": method, "name": labels[method]})
|
||||
elif method == "platega" and _service_configured(app, "platega_service"):
|
||||
elif method == "platega_sbp" and settings.PLATEGA_SBP_ENABLED and _service_configured(app, "platega_service"):
|
||||
methods.append({"id": method, "name": labels[method]})
|
||||
elif method == "platega_crypto" and settings.PLATEGA_CRYPTO_ENABLED and _service_configured(app, "platega_service"):
|
||||
methods.append({"id": method, "name": labels[method]})
|
||||
elif method == "yookassa" and _service_configured(app, "yookassa_service"):
|
||||
methods.append({"id": method, "name": labels[method]})
|
||||
@@ -2116,9 +2119,9 @@ async def _create_subscription_payment(
|
||||
return await _create_freekassa_payment(
|
||||
request, session, user_id, months, price, description
|
||||
)
|
||||
if method == "platega":
|
||||
if method in ("platega", "platega_sbp", "platega_crypto"):
|
||||
return await _create_platega_payment(
|
||||
request, session, user_id, months, price, description
|
||||
request, session, user_id, months, price, description, variant=method
|
||||
)
|
||||
if method == "severpay":
|
||||
return await _create_severpay_payment(
|
||||
@@ -2316,11 +2319,20 @@ async def _create_platega_payment(
|
||||
months: int,
|
||||
price: float,
|
||||
description: str,
|
||||
variant: str = "platega_sbp",
|
||||
) -> web.Response:
|
||||
settings: Settings = request.app["settings"]
|
||||
service: PlategaService = request.app["platega_service"]
|
||||
if not service or not service.configured:
|
||||
return _json_error(400, "payment_unavailable", "Payment method unavailable")
|
||||
if variant == "platega_crypto":
|
||||
if not settings.PLATEGA_CRYPTO_ENABLED:
|
||||
return _json_error(400, "payment_unavailable", "Payment method unavailable")
|
||||
platega_method_id = settings.PLATEGA_CRYPTO_METHOD
|
||||
else:
|
||||
if variant == "platega_sbp" and not settings.PLATEGA_SBP_ENABLED:
|
||||
return _json_error(400, "payment_unavailable", "Payment method unavailable")
|
||||
platega_method_id = settings.platega_sbp_method_resolved
|
||||
|
||||
try:
|
||||
payment = await _create_base_payment_record(
|
||||
@@ -2340,6 +2352,7 @@ async def _create_platega_payment(
|
||||
"months": months,
|
||||
"sale_mode": "subscription",
|
||||
"source": "webapp",
|
||||
"platega_variant": "crypto" if variant == "platega_crypto" else "sbp",
|
||||
}
|
||||
)
|
||||
success, response_data = await service.create_transaction(
|
||||
@@ -2350,6 +2363,7 @@ async def _create_platega_payment(
|
||||
currency=settings.DEFAULT_CURRENCY_SYMBOL or "RUB",
|
||||
description=description,
|
||||
payload=payload,
|
||||
payment_method=platega_method_id,
|
||||
)
|
||||
payment_url = (
|
||||
response_data.get("redirect")
|
||||
|
||||
@@ -14,7 +14,11 @@ from db.dal import payment_dal
|
||||
router = Router(name="user_subscription_payments_platega_router")
|
||||
|
||||
|
||||
@router.callback_query(F.data.startswith("pay_platega:"))
|
||||
@router.callback_query(
|
||||
F.data.startswith("pay_platega_sbp:")
|
||||
| F.data.startswith("pay_platega_crypto:")
|
||||
| F.data.startswith("pay_platega:")
|
||||
)
|
||||
async def pay_platega_callback_handler(
|
||||
callback: types.CallbackQuery,
|
||||
settings: Settings,
|
||||
@@ -22,6 +26,29 @@ async def pay_platega_callback_handler(
|
||||
platega_service: PlategaService,
|
||||
session: AsyncSession,
|
||||
):
|
||||
callback_prefix, _, _ = (callback.data or "").partition(":")
|
||||
if callback_prefix == "pay_platega_crypto":
|
||||
platega_method_id = settings.PLATEGA_CRYPTO_METHOD
|
||||
platega_variant = "crypto"
|
||||
if not settings.PLATEGA_CRYPTO_ENABLED:
|
||||
try:
|
||||
await callback.answer()
|
||||
except Exception:
|
||||
pass
|
||||
return
|
||||
elif callback_prefix == "pay_platega_sbp":
|
||||
platega_method_id = settings.platega_sbp_method_resolved
|
||||
platega_variant = "sbp"
|
||||
if not settings.PLATEGA_SBP_ENABLED:
|
||||
try:
|
||||
await callback.answer()
|
||||
except Exception:
|
||||
pass
|
||||
return
|
||||
else:
|
||||
# Legacy callback (pre-split): keep working as SBP
|
||||
platega_method_id = settings.platega_sbp_method_resolved
|
||||
platega_variant = "sbp"
|
||||
current_lang = i18n_data.get("current_language", settings.DEFAULT_LANGUAGE)
|
||||
i18n: Optional[JsonI18n] = i18n_data.get("i18n_instance")
|
||||
get_text = lambda key, **kwargs: i18n.gettext(current_lang, key, **kwargs) if i18n else key
|
||||
@@ -103,6 +130,7 @@ async def pay_platega_callback_handler(
|
||||
"user_id": user_id,
|
||||
"months": months,
|
||||
"sale_mode": sale_mode,
|
||||
"platega_variant": platega_variant,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -114,6 +142,7 @@ async def pay_platega_callback_handler(
|
||||
currency=currency_code,
|
||||
description=payment_description,
|
||||
payload=payload_meta,
|
||||
payment_method=platega_method_id,
|
||||
)
|
||||
|
||||
if success:
|
||||
|
||||
@@ -206,10 +206,15 @@ def get_payment_method_keyboard(months: int, price: float,
|
||||
text=_("pay_with_sbp_button"),
|
||||
callback_data=f"pay_fk:{value_str}:{price}{mode_suffix}",
|
||||
)
|
||||
elif method == "platega" and settings.PLATEGA_ENABLED:
|
||||
elif method == "platega_sbp" and settings.PLATEGA_ENABLED and settings.PLATEGA_SBP_ENABLED:
|
||||
builder.button(
|
||||
text=_("pay_with_platega_button"),
|
||||
callback_data=f"pay_platega:{value_str}:{price}{mode_suffix}",
|
||||
text=_("pay_with_platega_sbp_button"),
|
||||
callback_data=f"pay_platega_sbp:{value_str}:{price}{mode_suffix}",
|
||||
)
|
||||
elif method == "platega_crypto" and settings.PLATEGA_ENABLED and settings.PLATEGA_CRYPTO_ENABLED:
|
||||
builder.button(
|
||||
text=_("pay_with_platega_crypto_button"),
|
||||
callback_data=f"pay_platega_crypto:{value_str}:{price}{mode_suffix}",
|
||||
)
|
||||
elif method == "yookassa" and settings.YOOKASSA_ENABLED:
|
||||
builder.button(
|
||||
|
||||
@@ -42,6 +42,8 @@ class PlategaService:
|
||||
self.merchant_id = settings.PLATEGA_MERCHANT_ID
|
||||
self.secret = settings.PLATEGA_SECRET
|
||||
self.payment_method = settings.PLATEGA_PAYMENT_METHOD
|
||||
self.sbp_method = settings.platega_sbp_method_resolved
|
||||
self.crypto_method = settings.PLATEGA_CRYPTO_METHOD
|
||||
self.return_url = settings.PLATEGA_RETURN_URL or f"https://t.me/{default_return_url}"
|
||||
self.failed_url = settings.PLATEGA_FAILED_URL or self.return_url
|
||||
|
||||
@@ -77,6 +79,7 @@ class PlategaService:
|
||||
currency: Optional[str],
|
||||
description: str,
|
||||
payload: Optional[str] = None,
|
||||
payment_method: Optional[int] = None,
|
||||
) -> Tuple[bool, Dict[str, Any]]:
|
||||
if not self.configured:
|
||||
logging.error("PlategaService is not configured. Cannot create transaction.")
|
||||
@@ -85,9 +88,10 @@ class PlategaService:
|
||||
session = await self._get_session()
|
||||
url = f"{self.base_url}/transaction/process"
|
||||
currency_code = (currency or self.settings.DEFAULT_CURRENCY_SYMBOL or "RUB").upper()
|
||||
method_id = int(payment_method if payment_method is not None else self.payment_method)
|
||||
|
||||
body: Dict[str, Any] = {
|
||||
"paymentMethod": int(self.payment_method),
|
||||
"paymentMethod": method_id,
|
||||
"paymentDetails": {"amount": float(amount), "currency": currency_code},
|
||||
"description": description,
|
||||
"return": self.return_url,
|
||||
|
||||
+47
-5
@@ -44,6 +44,10 @@ class PaymentSettings(BaseModel):
|
||||
platega_merchant_id: Optional[str]
|
||||
platega_secret: Optional[str]
|
||||
platega_payment_method: int
|
||||
platega_sbp_enabled: bool
|
||||
platega_crypto_enabled: bool
|
||||
platega_sbp_method: int
|
||||
platega_crypto_method: int
|
||||
platega_return_url: Optional[str]
|
||||
platega_failed_url: Optional[str]
|
||||
severpay_enabled: bool
|
||||
@@ -179,7 +183,24 @@ class Settings(BaseSettings):
|
||||
PLATEGA_MERCHANT_ID: Optional[str] = None
|
||||
PLATEGA_SECRET: Optional[str] = None
|
||||
PLATEGA_PAYMENT_METHOD: int = Field(
|
||||
default=2, description="Platega payment method ID (e.g., 2 for SBP QR)"
|
||||
default=2,
|
||||
description="Legacy Platega payment method ID. Used as fallback for PLATEGA_SBP_METHOD when the new field is unset.",
|
||||
)
|
||||
PLATEGA_SBP_ENABLED: bool = Field(
|
||||
default=False,
|
||||
description="Show a separate Platega SBP payment button.",
|
||||
)
|
||||
PLATEGA_CRYPTO_ENABLED: bool = Field(
|
||||
default=False,
|
||||
description="Show a separate Platega crypto payment button.",
|
||||
)
|
||||
PLATEGA_SBP_METHOD: int = Field(
|
||||
default=2,
|
||||
description="Platega method ID for SBP QR (default 2).",
|
||||
)
|
||||
PLATEGA_CRYPTO_METHOD: int = Field(
|
||||
default=13,
|
||||
description="Platega method ID for crypto (default 13).",
|
||||
)
|
||||
PLATEGA_RETURN_URL: Optional[str] = Field(default=None)
|
||||
PLATEGA_FAILED_URL: Optional[str] = Field(default=None)
|
||||
@@ -404,6 +425,10 @@ class Settings(BaseSettings):
|
||||
platega_merchant_id=self.PLATEGA_MERCHANT_ID,
|
||||
platega_secret=self.PLATEGA_SECRET,
|
||||
platega_payment_method=self.PLATEGA_PAYMENT_METHOD,
|
||||
platega_sbp_enabled=self.PLATEGA_SBP_ENABLED,
|
||||
platega_crypto_enabled=self.PLATEGA_CRYPTO_ENABLED,
|
||||
platega_sbp_method=self.platega_sbp_method_resolved,
|
||||
platega_crypto_method=self.PLATEGA_CRYPTO_METHOD,
|
||||
platega_return_url=self.PLATEGA_RETURN_URL,
|
||||
platega_failed_url=self.PLATEGA_FAILED_URL,
|
||||
severpay_enabled=self.SEVERPAY_ENABLED,
|
||||
@@ -750,7 +775,8 @@ class Settings(BaseSettings):
|
||||
"""
|
||||
default_order = [
|
||||
"freekassa",
|
||||
"platega",
|
||||
"platega_sbp",
|
||||
"platega_crypto",
|
||||
"severpay",
|
||||
"yookassa",
|
||||
"stars",
|
||||
@@ -758,13 +784,29 @@ class Settings(BaseSettings):
|
||||
]
|
||||
if not self.PAYMENT_METHODS_ORDER:
|
||||
return default_order
|
||||
methods = []
|
||||
methods: List[str] = []
|
||||
for item in self.PAYMENT_METHODS_ORDER.split(","):
|
||||
slug = item.strip().lower()
|
||||
if slug:
|
||||
methods.append(slug)
|
||||
if not slug:
|
||||
continue
|
||||
if slug == "platega":
|
||||
# Legacy slug — expand to the new sub-methods preserving order
|
||||
if "platega_sbp" not in methods:
|
||||
methods.append("platega_sbp")
|
||||
if "platega_crypto" not in methods:
|
||||
methods.append("platega_crypto")
|
||||
continue
|
||||
methods.append(slug)
|
||||
return methods or default_order
|
||||
|
||||
@computed_field
|
||||
@property
|
||||
def platega_sbp_method_resolved(self) -> int:
|
||||
"""SBP method ID, falling back to legacy PLATEGA_PAYMENT_METHOD when SBP-specific value is the default."""
|
||||
if self.PLATEGA_SBP_METHOD != 2:
|
||||
return self.PLATEGA_SBP_METHOD
|
||||
return self.PLATEGA_PAYMENT_METHOD or 2
|
||||
|
||||
@computed_field
|
||||
@property
|
||||
def email_auth_configured(self) -> bool:
|
||||
|
||||
@@ -49,6 +49,8 @@
|
||||
"yookassa_autopay_charge_initiated": "Charge request sent to the selected card. We'll notify you once the payment completes.",
|
||||
"pay_with_sbp_button": "📱 SBP",
|
||||
"pay_with_platega_button": "💳 Platega (SBP/Cards)",
|
||||
"pay_with_platega_sbp_button": "🏦 Pay via SBP",
|
||||
"pay_with_platega_crypto_button": "🪙 Pay with crypto",
|
||||
"pay_with_severpay_button": "💳 SeverPay",
|
||||
"back_to_payment_methods_button": "⬅️ Back",
|
||||
"pay_with_cryptopay_button": "💎 CryptoBot",
|
||||
|
||||
@@ -49,6 +49,8 @@
|
||||
"yookassa_autopay_charge_initiated": "Запрос на списание с выбранной карты отправлен. Сообщим, как только платёж завершится.",
|
||||
"pay_with_sbp_button": "📱 СБП",
|
||||
"pay_with_platega_button": "💳 Platega (СБП/карты)",
|
||||
"pay_with_platega_sbp_button": "🏦 Оплата через СБП",
|
||||
"pay_with_platega_crypto_button": "🪙 Оплата криптой",
|
||||
"pay_with_severpay_button": "💳 SeverPay",
|
||||
"back_to_payment_methods_button": "⬅️ Назад",
|
||||
"pay_with_cryptopay_button": "💎 CryptoBot",
|
||||
|
||||
Reference in New Issue
Block a user