Skip to main content

Checkout Flow

Related docs: Payment Architecture · Order Lifecycle


1. Overview

The Pakashop checkout is a two-step process composed as a single page with conditional rendering:

  1. Delivery Information — address collection.
  2. Payment Method — method selection, wallet number (MoMo), consent, and order submission.

The page assembles these components from frontend/src/components/checkout/:

ComponentResponsibility
DeliveryForm.jsZambian address form with all 10 provinces
PaymentMethodSelector.jsAnimated grid of MTN / Airtel / Zamtel / Card options
MobileMoneyOverlay.jsFull-screen USSD waiting overlay with polling
OrderSummary.jsCart items, VAT breakdown, trust badges

2. Step-by-Step User Journey


3. Delivery Form

Collects Zambian-specific delivery details. All labels use "delivery" (never "shipping").

Fields:

FieldValidation
First NameRequired
Last NameRequired
EmailRequired, valid format
Mobile NumberRequired (delivery contact)
Delivery AddressRequired
CityRequired
ProvinceRequired — select from all 10 Zambian provinces
CountryFixed: Zambia

On submission, formData is passed to Step 2 and the wallet number field is pre-filled from formData.phone.


4. Payment Method Selection

The PaymentMethodSelector renders a 2×2 grid of clickable cards:

Method IDLabelTypeLogo path
MTN_MONEYMTN Mobile MoneyUSSD push/images/logos/.../mtn.svg
AIRTEL_MONEYAirtel MoneyUSSD push/images/logos/.../airtel.svg
ZAMTEL_MONEYZamtel KwachaUSSD push/images/logos/.../zamtel.png
CARDVisa / MastercardRedirectvisa.svg + mastercard.svg

State: selectedMethod (default: MTN_MONEY).


5. Mobile Money Wallet Number

Conditionally rendered when selectedMethod !== 'CARD'.

  • Label: "Enter Mobile Money Number"
  • Pre-fill: formData.phone from delivery form
  • Validation: Zambian number format (10 digits, starts with 097/096/095/077/076/075/095)
  • Storage: formData.mobileWalletNumber

Required for mobile money payments.

Text: "I confirm that the mobile money wallet is registered in my name and I agree to Pakashop's [Terms of Service]."

The checkbox enforces the Zambia Data Protection Act 2021 requirement for explicit consent before processing personal financial data.


The checkout process follows a coordinated sequence:

  1. Order Creation: A pending order is created in the database with the customer's delivery and item details.
  2. Payment Initiation: The chosen provider is called to generate a USSD push (for mobile money) or a hosted payment link (for card).
  3. Redirection/Overlay: The user is either redirected to a secure payment page or shown a local USSD status overlay.

8. USSD Polling Logic

To provide a real-time experience for mobile money users, the frontend continuously polls the backend for payment status updates every 5 seconds. This process remains active for up to 3 minutes, or until a terminal state (PAID or FAILED) is reached, at which point the user is automatically redirected to their order confirmation page.


9. Payment Callback Page (/payment/callback)

Landing page for card payment redirects. Also handles manual navigation for edge cases.

Logic:

  1. Extract orderId from searchParams.
  2. If no orderId: show generic error (mobile money payments are confirmed via polling on the checkout page, not here).
  3. Call GET /api/v1/payments/status/:orderId once.
  4. If PAID → show success UI, clear cart, link to order.
  5. If PENDING → start polling (3 s interval, 2 min timeout).
  6. If FAILED → show failure UI, link back to checkout.

Success message: "Payment successful! Your order is being processed and will be delivered soon."


10. Error Handling

ScenarioBehaviour
Order creation failsToast error, button re-enabled, user stays on checkout
Payment initiation failsToast with backend message, button re-enabled
USSD timeout (3 min)Overlay dismissed, link to order page for status check
Card redirect failsUser lands on callback page with FAILED/PENDING status
Network error during pollPoll continues; errors logged to console