ADR-039 · 2026-06-03 · UA-first payment stack

Payment infrastructure without vendor lock-in

Multi-provider stack for Ukrainian ФОП-3 SaaS. WayForPay for subscriptions and one-off purchases, LiqPay + Monobank for refunds. Stripe remains in the repo for Y2 EU expansion.

Provider-agnostic architecture — switching between providers via a single env var. PCI DSS Level 1, 3-D Secure 2.0, ПРРО integration out of the box.

First question technical evaluators ask

Why not Stripe as primary?

Stripe is the industry standard for SaaS in the West, but for Ukrainian ФОП-3 it is not a practical choice in V1. Stripe does not accept Ukrainian ФОП registration directly — you must either open an EU LLC (Estonia OÜ ~€600 + annual costs, Poland sp. z o.o. ~₴80k setup), or use Stripe Atlas (US Delaware LLC, $500 setup + annual IRS reporting).

Additionally, UAH recurring through Stripe has 1.5–2% FX losses on each conversion to USD. For a $49/month plan, that's ~$0.70–1.00 loss per month per customer — money better left with the customer or in the product.

WayForPay accepts Ukrainian ФОП-3 in 1–3 business days of KYC, natively charges in UAH without FX, and has automatic ПРРО integration. LiqPay serves as the secondary refund executor. These two have everything needed for a UA-first launch.

Stripe is not "rejected" — it is active in the codebase as a third provider. When we have an EU LLC or Stripe Atlas (Y2 — after PMF in UA), we activate it with a single env flag. See ADR-039 for the full breakdown.

Multi-provider stack

Five providers — one abstraction

Each provider closes a specific use case. Routing happens at the orchestrator layer via <code class="font-mono text-primary-500">SubscriptionProvider</code> interface + multi-provider <code class="font-mono text-primary-500">refund-providers.ts</code> switch.

WayForPay

live (post-KYC)
Subscription billing primary

Recurring tokenized charges, ПРРО integration, monthly/annual plans, dunning + payment retries.

  • Subscription Cloud (recurring without manual tokenization)
  • Card + Apple Pay + Google Pay
  • 3-D Secure 2.0 mandatory
  • ПРРО integration on KYC — fiscal receipts automatic
  • PCI DSS Level 1
  • EU expansion path via Flitt rebrand

LiqPay

live (multi-provider switch)
Refund fallback

Most trusted UA gateway (PrivatBank). Used for refund execution on orders paid via LiqPay.

  • Refund API (sha1 signature)
  • Multi-currency: UAH, USD, EUR
  • Apple Pay + Google Pay
  • Reverse-payment flow for refunds

Monobank Acquiring

deferred (P2)
Cheap option (deferred P2)

Cheapest UA acquirer (1.4–2.5%). Recurring limited — will use for one-off payments once buyer funnel stabilizes.

  • Invoice cancel/refund API
  • X-Token authorization
  • Cheapest commission on UA market
  • Recurring requires separate banker agreement

Stripe

deferred (Y2 EU)
Deferred to Y2 EU

Third provider in the repo. Activated when we have an EU LLC or Stripe Atlas + EU/US customer volume justifies the cost.

  • Subscription + Tax + Billing Portal
  • Best-in-class dev DX
  • Multi-currency native
  • Activate via BILLING_PROVIDER=stripe
Compliance automatic

ФОП-3 + ПРРО — no manual reporting

Ukrainian SaaS on ФОП-3 (simplified system 5% of turnover) when selling services to Ukraine residents are obligated to use software cash register — a registry of calculation operations. This is a fiscal receipt automatically sent to tax authorities on each transaction.

What WayForPay does
  • ✓ Automatic formation of ПРРО receipt on each successful transaction
  • ✓ Email to customer with fiscal receipt (legally closing document)
  • ✓ Transfer of receipt to tax authorities via cabinet API
  • ✓ Calculation of single tax (5%) automatically from incoming turnover
What the merchant (you) does
  • ✓ Activate ПРРО integration during WayForPay KYC (~10 min conversation)
  • ✓ File quarterly ФОП-3 declaration — our Tax Auto-Pilot agent generates it
  • ✓ Keep ФОП-3 limit within ~₴8.3M/year turnover (~$200k)
  • ✓ When approaching the limit — transition to TOV (plan ahead)

If you plan to scale > $200k ARR — start registering a TOV in parallel with launch. Y1 mantra $30k MRR = $360k ARR exceeds ФОП-3 limit in ~6 months. Not a blocker for launch, but factor it into the roadmap.

Architecture (for devs)

What's under the hood

SubscriptionProvider interface

interface SubscriptionProvider {
  id: 'demo' | 'wayforpay' | 'stripe';
  isConfigured(): boolean;
  createCheckout(args): Promise<{ url }>;
  createPortal(args): Promise<
    | { kind: 'hosted'; url }
    | { kind: 'unsupported'; reason }
  >;
}

Each provider implements this interface. Registry in <code class="font-mono">billing/provider.ts</code>, selection via <code class="font-mono">BILLING_PROVIDER</code> env var. Unsupported portal (WayForPay does not have hosted billing portal) — UI fallback to /dashboard/settings.

Refund execution (multi-provider)

type RefundProviderId =
  | 'liqpay'    | 'monobank'
  | 'stripe'    | 'manual';

executePaymentRefund(provider, {
  paymentIntentId,
  amountUah,
  reason,
  idempotencyKey,
}) => Promise<RefundResult>

Routing to the provider the order was paid with. Idempotency via <code class="font-mono">refund-log id</code> — replay-safe. Failures return a structured result (succeeded/failed/manual_required), never throw.

Webhook signature verification

  • WayForPay: HMAC-MD5 on merchantSecretKey
  • LiqPay: sha1(secret + data + secret) base64
  • Monobank: X-Token header + body match
  • Stripe: Stripe-Signature header + secret

Each webhook route is separate — <code class="font-mono">/webhooks/&lt;provider&gt;</code>. Signatures verified before touching DB.

Outcome billing meters

  • $0.50 / closed_deal
  • $0.10 / ttn_generated
  • 1–2% / ad_budget_managed
  • $1.00 / return_resolved
  • $2.00 / recovered_oos_sale

Metrics emitted from agent runtime → aggregate in <code class="font-mono">billing-meters</code> → weekly invoice items in WayForPay. Failures in retry sweep cron. Operator sees usage in real-time in dashboard.

Codebase open on GitHub — apps/orchestrator/src/billing/.

Roadmap

What's next

V1 · Q3 2026
WayForPay subscription live + LiqPay refund executor + one-off purchases. Tax Auto-Pilot generates ФОП-3 declaration quarterly.
P2 · Q4 2026
Monobank Acquiring as cheaper option for high-volume customers (1.4–2.5% vs WayForPay 2.7%). Apple Pay + Google Pay in inbox checkout.
Y2 EU · 2027
Stripe live mode after forming EU LLC (Estonia OÜ or Poland). EUR/USD pricing, Stripe Tax for PL/CZ/DE customers. UA-side stays WayForPay.
Y3 US · 2028
Stripe primary for NA market. SOC 2 Type II certification (ADR-025). Multi-currency consolidation by region.

FAQ — Payments

Questions about payment architecture?

30-minute demo — I'll show you WayForPay sandbox checkout, refund flow, ПРРО receipt sample. If you're evaluating Unitelia from a technical angle — this is the fastest way to confirm we don't handwave.