Payment methods
MAXFI exposes one universal checkout flow that supports all eight canonical payment methods. The hosted checkout page decides at runtime which methods to show based on your Merchant Connector Account (MCA) — you do not ship connector-specific UI.
The same catalog is also available to the Widget SDK and to direct-API integrations that want to render their own method picker.
Canonical 8 methods
Every method_code returned by our APIs is one of these:
cardinline_formsbpqr_code + deeplinksberpayredirecttpayredirectyoomoneyredirectapple_paymodalgoogle_paymodalrecurrentinline_formEffective catalog · MCA ∩ CMC ∩ MCS
What a given customer actually sees on the checkout page is computed from three layers, resolved server-side:
- MCA — Merchant Connector Account. The set of methods the acquirer (Bank131, ATB, E-Xezine…) has switched on for this merchant.
- CMC — Connector Method Capability. The global whitelist of what each connector can technically do at the platform level (managed by MAXFI operations).
- MCS — Merchant Connector Setting. Per-merchant toggles the merchant controls from the Merchant Portal (“Способы оплаты” tab).
The effective catalog is the intersection: a method must be allowed at all three layers to appear. If any layer removes it, the checkout page hides the tab. Reordering is driven by MCS display_order.
Fetching the catalog
The hosted checkout page fetches this itself on load — you usually don't need to call it. But if you're rendering your own picker (direct API, a custom widget embed, a mobile SDK), hit it first:
curl https://maxfi-api.exezine.az/checkout/cs_abc123/methods \ -H "Accept: application/json" # Response { "methods": [ { "method_code": "card", "display_order": 10, "render_mode": "inline_form", "is_enabled": true, "supports_recurring": true, "supports_refund": true, "allowed_currencies": ["RUB", "USD", "EUR"] }, { "method_code": "sbp", "display_order": 20, "render_mode": "qr_code", "is_enabled": true, "supports_refund": true, "allowed_currencies": ["RUB"] } ] }
This endpoint fails open: if the catalog lookup errors, we return { methods: [{ method_code: "card", … }], fallback: true }so the customer can still pay by card.
Submitting a non-card method
Card payments go through POST /checkout/{sessionId}/pay(PCI SAQ A-EP, 2-phase 3DS). All other methods submit to the shared endpoint:
curl https://maxfi-api.exezine.az/checkout/cs_abc123/submit-method \ -H "Content-Type: application/json" \ -d '{ "method_code": "sbp" }' # Response — browser must render the QR + poll for settlement { "session_id": "cs_abc123", "status": "requires_action", "next_action": { "type": "show_qr", "qr_raw_payload": "https://qr.nspk.ru/AS1000…", "deeplink": "bank100000000111://qr.nspk.ru/AS1000…" } }
next_action shapes
The next_action object tells the browser what to do next. Four discriminated shapes:
show_qr— forsbp. Fields:qr_image_url(ready-to-render) orqr_raw_payload(render locally), plus a mobiledeeplink.redirect— forsberpay,tpay,yoomoney. Navigate the customer toredirect_url; they return viasuccess_urlorcancel_url.three_ds_challenge— for card flows that need a challenge. Fields:acs_url,creq. Post them into an iframe on your page.poll— no immediate browser action; pollGET /checkout/{sessionId}/statusevery 2–3 seconds until the session reaches a terminal state.
SBP bank picker · NSPK whitelist
SBP (Система Быстрых Платежей / Faster Payments System) in Russia is run by NSPK — the National Payment Card System. Every bank connected to SBP has a stable 12-digit identifier called nspkId. When a customer picks their bank on the checkout page before generating the QR, the QR payload is routed directly to that bank's mobile application via a deeplink, skipping the manual «open my banking app and scan» step.
MAXFI mirrors the public NSPK dictionary at qr.nspk.ru/proxyapp/c2bmembers.json into our database and exposes it through three endpoints. All three validate the supplied member_id against the active whitelist before a payment is even sent to the acquirer — unknown / stale identifiers return an error straight from Gateway.
GET /sbp/membersFull active whitelist (~200+ banks). No auth. Ideal for server-side validation or a «всё SBP-сообщество» picker.
GET /sbp/members/popular?limit=12Only top-N banks (curated by MAXFI Ops), sorted by display_order. Used by the hosted checkout grid.
GET /checkout/{sessionId}/sbp-membersSame list but tied to a checkout session. Returns an empty array if the session currency ≠ RUB (SBP only supports rubles).
GET /widget/v1/sbp-membersAuthenticated with your publishable key. Used by the embedded Widget modal to render the same grid on your site.
Each member is returned as:
curl https://maxfi-api.exezine.az/sbp/members/popular?limit= class="tok-number">4 # Response { "data": [ { "member_id": "100000000111", "name": { "en": "Sberbank", "ru": "Сбербанк", "az": "Sberbank" }, "logo_url": "https://qr.nspk.ru/logos/bank100000000111.png", "deeplink_ios": "bank100000000111://", "deeplink_android": "ru.sberbankmobile", "is_popular": true, "display_order": 1 }, { "member_id": "100000000004", "name": { "en": "T-Bank", … }, "display_order": 2, … }, { "member_id": "100000000005", "name": { "en": "VTB", … }, "display_order": 3, … }, { "member_id": "100000000008", "name": { "en": "Alfa-Bank", … }, "display_order": 4, … } ], "count": 4 }
Submit the chosen bank by adding extra.memberId to the SBP method payload:
curl https://maxfi-api.exezine.az/checkout/cs_abc123/submit-method \ -H "Content-Type: application/json" \ -d '{ "method_code": "sbp", "payload": { "dynamic": true, "extra": { "memberId": "100000000111" } } }' # Response — payload routed to Sberbank deeplink, QR still shown as fallback { "status": "requires_action", "next_action": { "type": "show_qr", "deeplink": "bank100000000111://qr.nspk.ru/AS1000…", "qr_raw_payload": "https://qr.nspk.ru/AS1000…" } }
A bogus memberId (typo, bot traffic, custom SDK bug) would still reach the acquirer and come back as an opaque invalid_member_bank error after a 500–800 ms round trip. By keeping an in-memory mirror of the NSPK whitelist (10-minute TTL, refreshed nightly by a cron job) we reject unknown IDs in under 1 ms, keep payment_audit_log clean, and can present a localised error message without leaking the acquirer's dictionary.
Apple Pay / Google Pay activation
Unlike card, sbp, or sberpay, wallet methods require extra setup on the acquirer side and on the merchant's own domain before they become toggleable. Until your MAXFI account manager completes verification, these methods are visible in Merchant Portal → Payment methods but the toggle is disabled with a “Awaiting verification” pill.
Apple Pay — checklist
- Register an Apple Merchant ID in your Apple Developer account (e.g.
merchant.com.yourshop). - Generate the Merchant Identity Certificate and the Payment Processing Certificate signed by your acquirer (ATB SmartVista, Bank131, …).
- Upload the domain association file Apple gives you to MAXFI. Once saved on the Merchant Connector Account (MCA), MAXFI serves it at
https://<your-domain>/.well-known/apple-developer-merchantid-domain-associationautomatically — one endpoint per verified domain, no extra deploy on your side. - Sign the Apple Pay Web merchant agreement with your acquirer.
When all four are in place, MAXFI Ops flips payment_methods.apple_pay on your MCA and the toggle in Merchant Portal → Payment methods becomes active — no deploy required on your side.
Google Pay — checklist
- Register a Google Pay Merchant ID in Google Pay & Wallet Console.
- Configure your gateway in the console pointing at your acquirer (e.g.
smartvistafor ATB). Google will issue a gateway_merchant_id that MAXFI stores on your MCA. - Sign the Google Pay API for Web agreement with your acquirer.
- (Optional, production launch) submit your website to Google for the Google Pay Web production review.
Same unlock mechanism as Apple Pay — MAXFI Ops adds google_pay to your MCA, the Merchant Portal toggle becomes active, and the hosted checkout starts advertising the Google Pay button on supported browsers.
Both wallets send MAXFI an encrypted device-specific token, not the customer's real PAN. From your server's point of view nothing changes — you still call POST /checkout/{sessionId}/submit-method with method_code: "apple_pay" or "google_pay". The hosted checkout handles the Apple Pay sheet / Google Pay button, sends the token server-to-server, and returns a standard succeeded / failed status.
Widget SDK
The Widget SDK (/widget/v1/maxfi.js) wraps all of this. Drop a button on your page, the SDK shows the method picker in a modal, creates the session, and mounts the checkout iframe. Card data never crosses your front-end — the iframe handles it.
If you want to pre-select a tab, pass initial_method:
<script src="https://maxfi-api.exezine.az/widget/v1/maxfi.js"></script> <script> const maxfi = new Maxfi({ publishableKey: "pk_live_…", amount: 4900, currency: "USD", initial_method: "sbp", // pre-selects the SBP tab }); maxfi.mount("#pay-button"); </script>
Enable / reorder methods for your account in Merchant Portal → Способы оплаты. What your customers see on the hosted page reflects that setting within a minute.
