feat: добавлена поддержка RioPay для лендингов и подарков
- Добавлен RioPay в create_guest_payment (landing/gift покупки) - user_id в RioPayPayment теперь nullable (для гостевых платежей) - Добавлен guest purchase flow в _finalize_riopay_payment - Миграция 0039: riopay_payments.user_id nullable
This commit is contained in:
@@ -15,7 +15,7 @@ logger = structlog.get_logger(__name__)
|
||||
async def create_riopay_payment(
|
||||
db: AsyncSession,
|
||||
*,
|
||||
user_id: int,
|
||||
user_id: int | None,
|
||||
order_id: str,
|
||||
amount_kopeks: int,
|
||||
currency: str = 'RUB',
|
||||
|
||||
@@ -42,7 +42,7 @@ class RioPayPaymentMixin:
|
||||
self,
|
||||
db: AsyncSession,
|
||||
*,
|
||||
user_id: int,
|
||||
user_id: int | None,
|
||||
amount_kopeks: int,
|
||||
description: str = 'Пополнение баланса',
|
||||
email: str | None = None,
|
||||
@@ -277,6 +277,20 @@ class RioPayPaymentMixin:
|
||||
logger.info('RioPay платеж уже привязан к транзакции', order_id=payment.order_id, trigger=trigger)
|
||||
return True
|
||||
|
||||
# --- Guest purchase flow (landing page / gift) ---
|
||||
riopay_metadata = dict(getattr(payment, 'metadata_json', {}) or {})
|
||||
from app.services.payment.common import try_fulfill_guest_purchase
|
||||
|
||||
guest_result = await try_fulfill_guest_purchase(
|
||||
db,
|
||||
metadata=riopay_metadata,
|
||||
payment_amount_kopeks=payment.amount_kopeks,
|
||||
provider_payment_id=str(riopay_order_id) if riopay_order_id else payment.order_id,
|
||||
provider_name='riopay',
|
||||
)
|
||||
if guest_result is not None:
|
||||
return True
|
||||
|
||||
# Получаем пользователя
|
||||
user = await get_user_by_id(db, payment.user_id)
|
||||
if not user:
|
||||
|
||||
@@ -692,6 +692,29 @@ class PaymentService(
|
||||
}
|
||||
return None
|
||||
|
||||
# --- RioPay -----------------------------------------------------------
|
||||
if payment_method == 'riopay':
|
||||
if not settings.is_riopay_enabled():
|
||||
logger.warning('RioPay is not enabled, cannot create guest payment')
|
||||
return None
|
||||
|
||||
result = await self.create_riopay_payment(
|
||||
db=db,
|
||||
user_id=None,
|
||||
amount_kopeks=amount_kopeks,
|
||||
description=description,
|
||||
success_url=return_url,
|
||||
fail_url=return_url,
|
||||
)
|
||||
if result:
|
||||
await _patch_guest_metadata(result['local_payment_id'], 'riopay')
|
||||
return {
|
||||
'payment_url': result.get('payment_url'),
|
||||
'payment_id': result.get('riopay_order_id') or result.get('order_id'),
|
||||
'provider': 'riopay',
|
||||
}
|
||||
return None
|
||||
|
||||
# --- Telegram Stars ---------------------------------------------------
|
||||
if payment_method == 'telegram_stars':
|
||||
if not settings.TELEGRAM_STARS_ENABLED:
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
"""make riopay_payments.user_id nullable for guest purchases
|
||||
|
||||
Revision ID: 0039
|
||||
Revises: 0038
|
||||
Create Date: 2026-03-18
|
||||
|
||||
"""
|
||||
|
||||
from typing import Sequence, Union
|
||||
|
||||
import sqlalchemy as sa
|
||||
from alembic import op
|
||||
|
||||
revision: str = '0039'
|
||||
down_revision: Union[str, None] = '0038'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
with op.batch_alter_table('riopay_payments') as batch_op:
|
||||
batch_op.alter_column('user_id', existing_type=sa.Integer(), nullable=True)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
with op.batch_alter_table('riopay_payments') as batch_op:
|
||||
batch_op.alter_column('user_id', existing_type=sa.Integer(), nullable=False)
|
||||
Reference in New Issue
Block a user