Middleware — Payments
Folder: src/routes/payments/
Mount: api/v1/bookdirect/payments
Status: to implement (Paystack first; Squad / Tsara same shape).
Do not store the booking only in Mongo. Persist on Core.
Middleware · winner
POST https://middleware-dev.bookdirect.live/api/v1/bookdirect/payments/initialize
POST https://middleware-dev.bookdirect.live/api/v1/bookdirect/payments/verify/{reference}
POST https://middleware-dev.bookdirect.live/api/v1/bookdirect/payments/webhook/paystack
Frontend: Checkout and pay.
Initialize (frontend → Middleware)
{
"booking_uuid": "{booking_uuid}",
"provider": "paystack",
"amount_kobo": 6000000,
"currency": "NGN",
"callback_url": "https://your-app/booking/confirmation"
}Middleware must
Validate JWT. Load booking from Core:
GET https://backend-dev.bookdirect.live/public/api/v1/nellalink/smart-meta-manager/entity/booking/{booking_uuid}Reject if
owned_by≠ JWT user, or status ≠pending, or amount ≠extra_data.total_amount_ngn * 100.Create Core payment:
POST https://backend-dev.bookdirect.live/public/api/v1/nellalink/smart-meta-manager/entity/paymentjson{ "request_id": "pay-{booking_uuid}-{n}", "meta_key": "pay_{reference}", "title_name": "Payment for booking", "parent_entity_type": "booking", "parent_entity_uuid": "{booking_uuid}", "owned_by": "{guest_uuid}", "status": "initialized", "extra_data": { "provider": "paystack", "reference": "{reference}", "amount_kobo": 6000000, "currency": "NGN", "booking_uuid": "{booking_uuid}" } }Call Paystack
transaction/initialize. Returnauthorization_url,reference,payment_uuid.
Webhook (PSP → Middleware)
Verify signature. Then:
PUT https://backend-dev.bookdirect.live/public/api/v1/nellalink/smart-meta-manager/entity/payment/{payment_uuid} → status: paid
PUT https://backend-dev.bookdirect.live/public/api/v1/nellalink/smart-meta-manager/entity/booking/{booking_uuid} → status: confirmed
Then send mail: Emails. Optionally push ARI: Google rates.
Webhook has no user JWT. Authenticate the PSP only. Never accept a client body that says “mark paid” without a verified webhook or verify call.
Verify
Used by the confirmation page if the webhook is slow. Same Core writes as the webhook after Paystack verify succeeds.
IDOR
- Initialize: booking must belong to the JWT user.
- Webhook: do not take
owned_byfrom the PSP payload as a new owner. - Middleware → Core uses a service
x-api-keyplus the guest Bearer (or a tightly scoped service identity). Do not write bookings as a different guest.