Payment gateway integration
The gateway processes financial operations. Kevmi connects them to orders, store settings and notifications. This guide describes the integration contract and availability checks.
On this page
Checking availability#
Kevmi uses the gateway v3 API to create and recover operations, read statuses and reconcile results. The integration supports encrypted card and bank-code transport, Alipay and SBP QR payments, a crypto coin/network catalogue and incoming financial events.
gateway.configured in GET /api/config reports whether the required connection settings are present. This endpoint does not probe the gateway; gateway.connected=false here means that connectivity has not been verified. For a specific invoice, read invoice.availability in GET /api/checkout/{token}: it checks the method, amount, terms and merchant approval. The compatibility field invoice.gatewayConnected mirrors availability.available and is also neither a health check nor a guarantee of payment approval.
A new payment and card intent require the merchant’s latest website-review application to be approved. Approval alone does not connect the payment gateway. If the review changes after dispatch, the existing operation remains available for status reads, reconciliation and a requested bank code.
Customer checkout contract#
Sensitive data is encrypted in the browser with RSA-OAEP-256 and A256GCM. The private key stays on the gateway. Kevmi validates that the intent belongs to this invoice and purpose, relays the envelope, and does not store plaintext card numbers, CVV, buyer name, email, bank codes or the envelope itself.
Install the encrypted-transport extension on the gateway host before enabling cards. It checks the intent signature, expiry, replay, order and amounts. There is no plaintext fallback. This describes the protection mechanism, not PCI certification.
| Kevmi route | Purpose |
|---|---|
| GET /api/checkout/{token} | Invoice, quote, method availability and existing payment |
| POST /api/checkout/{token}/card-intent | One-time intent and public key for payment or code |
| POST /api/checkout/{token}/pay | Start one operation; card uses sealed: {intent,jwe} |
| POST /api/checkout/{token}/code | Encrypted one-time code for the current bank challenge |
| GET /api/checkout/{token}/status | Read the original operation without another charge |
| POST /api/checkout/{token}/reconcile | Explicitly reconcile the original operation |
| GET /api/checkout/{token}/crypto-services | Current coins, networks and limits for a USDT invoice |
Hosting and gateway connectivity#
Kevmi supports Sites hosting on Cloudflare Workers with D1, and self-hosting on Node.js with SQLite. SQLite requires a persistent volume and backups. The payment gateway runs as a separate service with its own durable storage.
An external gateway requires an HTTPS origin reachable by the server. In the self-hosted bundle, the server connects to a fixed gateway service on the private container network; the gateway service API is not exposed to the internet. The public site and callbacks use HTTPS. The browser also encrypts card details and bank codes before they reach Kevmi.
localhost refers to the current server or container; it does not expose the gateway owner’s computer. Connection keys and secrets belong only in server configuration.
For a custom domain, set a public HTTPS origin in NEXT_PUBLIC_SITE_URL before building. Documentation, canonical links and indexing resources use this value. It accepts only a scheme and host with an optional port, without a path, query, fragment or credentials. Match it to APP_ORIGIN in server configuration.
Calculation and supported terms#
For a new invoice in the interface, USD offers cards and Alipay; RUB offers SBP; USDT offers crypto. The API can also save USD + crypto for compatibility, but its live crypto payment is blocked with crypto_requires_usdt. USD and USDT are distinct, with no automatic conversion or assumed 1:1 rate. A crypto payment requires a separate USDT invoice.
For a new live card or Alipay payment, the current gateway supports only feeCustomerPercent=0 and vatCustomerPercent=100: the merchant covers the entire processing fee and VAT is added in full for the customer. Other shares can be saved and calculated on an invoice, but execution is blocked with unsupported_allocation. The server never silently changes saved terms. SBP and USDT crypto payments support every processing-fee share and have no VAT.
Sending an arbitrary total_cents does not change the provider’s tax calculation. An actual amount that differs from the saved total enters review and cannot confirm fulfilment. Gateway business_balance fields are retained as settlement evidence, not treated as a Kevmi merchant balance.
Connecting a live gateway#
Connecting the gateway includes server configuration, checks for the selected channels and processing verified financial events. Configuration readiness is checked separately from provider connectivity. A successful payment is accepted after verifying the operation status and amount. Deployment instructions are in ops/gateway-integration.md.
- 1
Deploy the Kevmi server and gateway as separate services. Configure durable storage, backups and the required background processes.
- 2
For an external connection, set an HTTPS origin in GATEWAY_BASE_URL. The self-hosted bundle uses its configured internal service. Both require a server-only GATEWAY_API_KEY and a separate GATEWAY_WEBHOOK_SECRET; secrets never reach the browser.
- 3
Set gateway BACKEND_WEBHOOK_URL to /api/gateway/webhook on Kevmi and a matching BACKEND_WEBHOOK_SECRET.
- 4
Enable encrypted card transport and keep its private key exclusively on the gateway host. Check public-key availability and matching intent-signing settings.
- 5
Check channel readiness, restrictions and the merchant website approval before launch.