- Added return request handling in return.controller.js - Implemented webhook handling for PayHere payments in webhook.controller.js - Created models for coupon redemptions, invoices, orders, order items, payments, payment attempts, payment webhook events, refunds, return items, and return requests. - Developed services for order management, payment processing, refunds, and returns. - Introduced validation schemas for payment and return requests. - Created migration scripts for new database tables related to orders, payments, refunds, and returns. - Added unit tests for order state transitions and PayHere provider functionality.
2.7 KiB
Orders and Payments API
All /api/v1 customer endpoints derive ownership from authentication.
Orders
POST /orders/from-checkoutconverts an owned READY checkout. Conversion locks the checkout, verifies ACTIVE reservations, copies immutable snapshots, converts the cart, and is idempotent by unique checkout ID.GET /ordersandGET /orders/:idprovide owner-scoped history/detail.POST /orders/:id/cancelreleases unpaid reservations. Paid orders require an explicit refund.- Admin:
GET /admin/orders,GET /admin/orders/:id, cancel, and mark-processing action endpoints.
Legal transitions are centralized. Payment, order, and fulfillment status are separate.
Payments and webhooks
POST /orders/:id/payment,GET /orders/:id/paymentPOST /payments/webhooks/payhereis unauthenticated at the session layer but requires the PayHere merchant hash.
Online browser redirects are never authoritative. A verified webhook must match local payment reference, currency, and DECIMAL amount. Unique provider event IDs make retries idempotent. A first successful event consumes each reservation once, records coupon redemption, marks payment/order paid, and issues invoice metadata. Failure does not consume inventory.
PayHere configuration uses PAYHERE_MERCHANT_ID, PAYHERE_MERCHANT_SECRET, and notify/return/cancel URLs. Stripe has an explicit disabled adapter until its official SDK and webhook secret are configured. No raw card or provider secret is accepted or returned.
Invoices
GET /orders/:id/invoiceis owner-scoped.
Invoice numbers use the locked ReferenceNumber sequence. Invoice metadata is created once per paid order. PDF generation is reserved for the existing document worker integration; no second PDF/storage subsystem was introduced.
Refunds
POST /admin/orders/:id/refundsrequirespayments.refundandIdempotency-Key.
Requested item quantities and captured totals are locked and validated. A refund never restocks inventory automatically. Provider refund execution remains disabled until provider API credentials/workflows are validated.
Returns
- Customer:
POST /orders/:orderId/returns,GET /returns,GET /returns/:id. - Admin: list, approve, reject, mark-received, and complete actions.
The return window uses RETURN_WINDOW_DAYS (default 30). Quantity cannot exceed the remaining purchased quantity. Only accepted RESTOCKABLE items are added through the inventory service; damaged/non-restockable items are not. EXCHANGE records intent only.
Business credit purchasing is intentionally disabled: no locked credit ledger was added without an approved accounting policy. Delivery, loyalty, support AI, and analytics are outside Phase 7.