PayssageFrontend
Coding Conventions
How the Payssage frontend consumes the API — generated clients, intents, webhook plumbing.
Consume the generated client
- All API calls go through
@trieoh/payssage-models(orval-generated from the spec). No hand-written fetch wrappers per endpoint. - Regenerate after spec changes:
pnpm orval— the client is not hand-edited. - Use the generated TanStack Query hooks; let React Query own caching/retry/invalidation.
Runtime setup
Configure the shared fetch stack once, at app startup:
configureApiClient({
baseURL: env.VITE_API_URL, // → https://api.trieoh.com/payssage
authBaseURL: env.VITE_AUTH_API_URL, // used for token refresh
})Envelope & errors
- The
fun.Responseenvelope is unwrapped at the client layer — you never see it. Success returns the payload directly. - Failures reject with
ApiError: the envelope is in.envelope, so error UI readserror.envelope.error.message(or the typed code). - Public routes are rare here (the provider callback and provider webhook are not frontend concerns) — but any anonymous call uses
{ public: true }.
Payment flows
- Checkout:
POST /wallets/{wallet_id}/checkoutwith the payment method. Pix returns the QR inprovider_data; cards charge synchronously (tokenize first via@mercadopago/sdk-js). - Status: reflect intent statuses as-is (
pending | processing | succeeded | cancelled | failed | rejected | refunded). State changes arrive via webhook → downstream service — don't fabricate transitions client-side. - Test mode: with
TEST_MODE=trueon the service,/testmode/intents/createlets you hard-create an intent with a chosen status for local flows.
Webhook plumbing (consumers)
- If you receive webhook deliveries from Payssage: verify
X-Payssage-Signature= hex(HMAC-SHA256(raw body, endpoint secret)) over the exact bytes POSTed, return 200 to stop retries. - The endpoint secret is returned once at creation — store it in env (
PAYSSAGE_WEBHOOK_SECRET), never in the client bundle.
Authentication
- Users authenticate through IdentityX; the JWT's
subject.idis the owner id for wallet/org scoping. - Platform wallet operations are done server-side with the service API key — never ship service keys to the browser.
Keeping in sync with the spec
- Spec changed? Run
just generate-orvaland let the type errors guide the UI updates. - Generated types are the source of truth — don't
as-cast around them.
Don't
- Don't call endpoints by URL string — import the generated functions.
- Don't hand-roll response envelopes or error parsing.
- Don't render money from client-computed totals — the server computes amounts.