feat: integrate AuraPay payment provider

Full integration following PayPear/RollyPay patterns:
- API client with X-ApiKey + X-ShopId auth, HMAC-SHA256 webhook verification
  (sorted keys, concatenated values, secret key #2)
- AuraPayPaymentMixin with create, webhook, finalize (all side effects), status check
- CRUD, model, migration (0060), PaymentMethod.AURAPAY enum
- Webhook endpoint, cabinet topup, bot handler with sub-options (card, sbp)
- Admin panel: AURAPAY category in bot_configuration + system_settings_service
- Config: AURAPAY_ENABLED, AURAPAY_API_KEY, AURAPAY_SHOP_ID, AURAPAY_SECRET_KEY
This commit is contained in:
Fringg
2026-04-18 00:02:49 +03:00
parent 2aa5927433
commit 97179360c0
17 changed files with 1595 additions and 0 deletions
+59
View File
@@ -30,6 +30,7 @@ from app.services.payment import (
WataPaymentMixin,
YooKassaPaymentMixin,
)
from app.services.payment.aurapay import AuraPayPaymentMixin
from app.services.payment.cloudpayments import CloudPaymentsPaymentMixin
from app.services.payment.freekassa import FreekassaPaymentMixin
from app.services.payment.kassa_ai import KassaAiPaymentMixin
@@ -369,6 +370,41 @@ async def link_paypear_payment_to_transaction(*args, **kwargs):
return await paypear_crud.link_paypear_payment_to_transaction(*args, **kwargs)
async def create_aurapay_payment(*args, **kwargs):
aurapay_crud = import_module('app.database.crud.aurapay')
return await aurapay_crud.create_aurapay_payment(*args, **kwargs)
async def get_aurapay_payment_by_order_id(*args, **kwargs):
aurapay_crud = import_module('app.database.crud.aurapay')
return await aurapay_crud.get_aurapay_payment_by_order_id(*args, **kwargs)
async def get_aurapay_payment_by_invoice_id(*args, **kwargs):
aurapay_crud = import_module('app.database.crud.aurapay')
return await aurapay_crud.get_aurapay_payment_by_invoice_id(*args, **kwargs)
async def get_aurapay_payment_by_id(*args, **kwargs):
aurapay_crud = import_module('app.database.crud.aurapay')
return await aurapay_crud.get_aurapay_payment_by_id(*args, **kwargs)
async def get_aurapay_payment_by_id_for_update(*args, **kwargs):
aurapay_crud = import_module('app.database.crud.aurapay')
return await aurapay_crud.get_aurapay_payment_by_id_for_update(*args, **kwargs)
async def update_aurapay_payment_status(*args, **kwargs):
aurapay_crud = import_module('app.database.crud.aurapay')
return await aurapay_crud.update_aurapay_payment_status(*args, **kwargs)
async def link_aurapay_payment_to_transaction(*args, **kwargs):
aurapay_crud = import_module('app.database.crud.aurapay')
return await aurapay_crud.link_aurapay_payment_to_transaction(*args, **kwargs)
# Mapping from model_name to getter function name for providers
# where it differs from the standard get_{model_name}_payment_by_id pattern.
_GETTER_OVERRIDES: dict[str, str] = {
@@ -394,6 +430,7 @@ class PaymentService(
SeverPayPaymentMixin,
PayPearPaymentMixin,
RollyPayPaymentMixin,
AuraPayPaymentMixin,
):
"""Основной интерфейс платежей, делегирующий работу специализированным mixin-ам."""
@@ -835,6 +872,28 @@ class PaymentService(
}
return None
# --- AuraPay ----------------------------------------------------------
if payment_method == 'aurapay':
if not settings.is_aurapay_enabled():
logger.warning('AuraPay is not enabled, cannot create guest payment')
return None
result = await self.create_aurapay_payment(
db=db,
user_id=None,
amount_kopeks=amount_kopeks,
description=description,
return_url=return_url,
)
if result:
await _patch_guest_metadata(result['local_payment_id'], 'aurapay')
return {
'payment_url': result.get('payment_url'),
'payment_id': result.get('aurapay_invoice_id') or result.get('order_id'),
'provider': 'aurapay',
}
return None
# --- Telegram Stars ---------------------------------------------------
if payment_method == 'telegram_stars':
if not settings.TELEGRAM_STARS_ENABLED: