Payment UI
Stripe Payment Element, Easypay, and Ifthenpay payment interfaces in the checkout app.
The checkout app renders provider-specific payment UI on /c/[id]. The active provider is determined by the session configuration and tenant integration settings.
Provider selection
A session uses one provider: the first the store has connected and turned on, in the order Stripe, Easypay, Ifthenpay. With none connected, it fails with "This store has no payment provider connected yet."
At payment time, @prood/checkout-host rebuilds the provider with the store's own credentials:
const { provider } = await getTenantPaymentProvider(tenantId, session.providerId, { includeDisabled: true })
// credentials come from integration_config, decrypted. There is no environment fallback.Stripe (embedded Payment Element)
Component: components/stripe-payment.tsx
Uses @stripe/react-stripe-js with the Payment Element:
<Elements stripe={stripePromise} options={{ clientSecret }}>
<PaymentElement />
<Button onClick={handleSubmit}>Pay now</Button>
</Elements>Flow
- Session loaded →
submitPayment()creates a Stripe Checkout Session - Client receives
clientSecretfrom payment session - Payment Element renders card form
- Customer submits → Stripe handles 3DS if required
- On success → redirect to
/confirm/{id}
Test cards
| Card number | Result |
|---|---|
4242 4242 4242 4242 | Success |
4000 0000 0000 3220 | 3DS required |
4000 0000 0000 9995 | Declined |
The publishable and secret keys are the store's own, entered under Integrations in the dashboard.
Easypay (Portugal)
Component: components/reference-payment.tsx
Reference-based payment for Portuguese methods:
| Method | UI |
|---|---|
| Multibanco | Entity + reference number for ATM/homebanking |
| MB WAY | Phone number input → push notification |
| Credit card | Redirect to Easypay hosted page |
Flow
- Customer selects payment method
submitPayment({ method: 'multibanco' })creates Easypay charge- Reference numbers displayed for Multibanco
- Customer pays asynchronously (ATM, app)
- Easypay webhook confirms payment → order updated
Sandbox
Set the Easypay address field to https://api.test.easypay.pt under Integrations for testing.
Ifthenpay (Portugal)
Component: components/reference-payment.tsx
Similar reference-based flow:
| Method | Integrations field |
|---|---|
| Multibanco | Multibanco key |
| MB WAY | MB WAY key |
| Credit card | Credit card key |
Calls back are verified with the store's anti-phishing key.
Shared payment page
Component: components/payment-page-client.tsx
Orchestrates the payment page:
- Loads session snapshot
- Determines provider type
- Renders Stripe Element or reference payment UI
- Handles submit, loading states, and error display
- Redirects on success/failure
Error handling
| Error | UI behavior |
|---|---|
| Session expired | "Session expired" message with link back to storefront |
| Payment declined | Retry button — state machine allows failed → payment |
| Provider error | Error toast with provider message |
| Network error | Retry with exponential backoff |