39 lines
1.5 KiB
Python
39 lines
1.5 KiB
Python
"""Local development checkout.
|
|
|
|
The real path is the provider webhook. This exists so the local stack can reach
|
|
a paid order without a provider account, and it goes through the same service so
|
|
the two cannot drift apart.
|
|
"""
|
|
from uuid import UUID
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException
|
|
|
|
from .. import payments
|
|
from ..core import db
|
|
from ..core.auth import owner
|
|
from ..core.models import Pay
|
|
from ..runtime import ENVIRONMENT, payment
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.post('/api/orders/dev-paid')
|
|
def dev_paid(body: Pay, session_id=Depends(owner)):
|
|
if ENVIRONMENT != 'local':
|
|
raise HTTPException(503, 'Checkout is not configured yet')
|
|
with db.connect() as c:
|
|
try:
|
|
quote = payments.approved_quote(c, body.quote_id, session_id)
|
|
except payments.PaymentRefused as refusal:
|
|
# The quote may already be paid; that is not a refusal.
|
|
existing = c.execute('SELECT * FROM dtf_local.orders WHERE quote_id=%s AND owner=%s',
|
|
(body.quote_id, session_id)).fetchone()
|
|
if existing:
|
|
return existing
|
|
raise HTTPException(404 if 'not found' in str(refusal) else 409, str(refusal))
|
|
# The charge happens inside the transaction that persists the order, so a
|
|
# failure to record it cannot leave a customer charged without an order.
|
|
receipt = payment.pay(str(body.quote_id), quote['approved']['total_cents'])
|
|
order, _ = payments.create_order(c, quote, receipt)
|
|
return order
|