43 lines
1.5 KiB
Python
43 lines
1.5 KiB
Python
from fastapi import APIRouter, Depends, HTTPException, status
|
|
from sqlalchemy import select
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from database.models import Ticket, TicketStatus
|
|
from database.session import get_db
|
|
from schemas.payment import PaymentWebhookRequest
|
|
from core.rabbitmq import publish_ticket_task # Оставили только правильный импорт
|
|
|
|
router = APIRouter(prefix="/api/webhooks", tags=["webhooks"])
|
|
|
|
@router.post("/payment", status_code=status.HTTP_200_OK)
|
|
async def payment_webhook(
|
|
body: PaymentWebhookRequest,
|
|
db: AsyncSession = Depends(get_db),
|
|
) -> dict[str, str]:
|
|
result = await db.execute(select(Ticket).where(Ticket.id == body.ticket_id))
|
|
ticket: Ticket | None = result.scalar_one_or_none()
|
|
|
|
if ticket is None:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail=f"Ticket {body.ticket_id} not found",
|
|
)
|
|
|
|
# Idempotency guard
|
|
if ticket.idempotency_key == body.idempotency_key:
|
|
return {"detail": "Already processed"}
|
|
|
|
if ticket.status != TicketStatus.LOCKED:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
detail=f"Ticket is in '{ticket.status}' state, expected 'LOCKED'",
|
|
)
|
|
|
|
ticket.status = TicketStatus.PAID
|
|
ticket.idempotency_key = body.idempotency_key
|
|
await db.commit()
|
|
|
|
# Вызываем нашу актуальную функцию отправки в очередь
|
|
await publish_ticket_task(ticket.id)
|
|
|
|
return {"detail": "Payment processed"} |