Appearance
Hosted Checkout
The citizen/payer-facing payment page — launched from the government portal or a merchant site. It is the CNP entry point to the Tonder rail. In-person POS via Menta does not go through Hosted Checkout — that's card-present at the terminal.
Live mockup
See the working checkout at vecnet-pay-checkout.vercel.app.
Tech & PCI
- Embeds Tonder Lite SDK v2.0. Card fields are collected through Skyflow Elements and tokenized — the PAN never touches Vecnet's frontend or backend, so Vecnet stays out of PCI scope (Skyflow's Level-1 cert carries it). See Security.
- The light SDK is the refactored drop-in from the prior session: Vecnet consumes it to build the checkout rather than reimplementing card capture.
Payment flow
- Portal opens the checkout with
{ entity_id, amount, currency, reference, correlation_id }— mint thecorrelation_idhere if absent. - Payer enters card (Skyflow elements) or picks an APM (SPEI / OXXO / Mercado Pago).
- Lite SDK sends the
payment request→ Tonder API → Tonder Backend. responsereturns: approved / declined / 3DS challenge / APM pending-with-voucher.- Tonder Backend → Transaction Notification → Listener →
transactions(+ journals if successful) → Webhook Manager → portal/merchant + the Dashboard via Realtime.
States the UI must handle
approved · declined (offer retry) · 3DS challenge (iframe/redirect) · APM pending (show SPEI CLABE / OXXO voucher with reference + expiry) · expired · failed/network.
Every state becomes a transactions row
That is what feeds the acceptance / decline / 3DS metrics.
Theming — config-driven, per merchant
A checkout_config row per entity drives branding — no per-merchant code.
sql
create table checkout_config (
id uuid primary key default uuid_generate_v7(),
entity_id text not null unique,
logo_url text, -- merchant / government logo
primary_color text not null default '#14b8a6', -- button / accent (Obsidian Terminal token by default)
button_text_color text,
accent_color text,
background text, -- dark-first per Obsidian Terminal
locale_default text not null default 'es', -- es | en
methods_enabled text[] not null default '{card,spei,oxxopay,mercadopago}',
success_redirect_url text,
origin_allowlist text[] not null default '{}', -- which sites may launch this checkout
metadata jsonb,
created_at timestamptz not null default now(),
modified_at timestamptz not null default now()
);- Defaults to the Obsidian Terminal tokens (dark-first; Syne / DM Sans / JetBrains Mono);
logo_url/primary_color/accent_coloroverride per merchant. - Mobile-first, minimal fields, fast paint — the checkout is the highest-stakes conversion surface, so latency and field count are first-order. The acceptance/conversion metrics are how you'll know if the aesthetics actually convert.
- Editable by Vecnet personnel (and optionally the merchant) via the Admin Panel.
Security specifics
No PAN in checkout_config or anywhere in Vecnet; the SDK + Skyflow hold card data; the return is signed; the correlation_id threads into the transactions/journal rows; the launching origin is allowlisted per merchant (origin_allowlist).
The live mockup is at vecnet-pay-checkout.vercel.app; the
yuyo99/vecnet-pay-checkoutrepo is private, so this spec is grounded in the live mockup, the architecture diagram, and stated intent. Align component/structure to the repo once shared (open items).