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.
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.
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)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)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)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)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
ФОП-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.
- ✓ 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
- ✓ 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.
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/<provider></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/.
What's next
FAQ — Payments
-
Why don't you use Stripe as primary, like all Western SaaS?
Stripe for UA ФОП-3 requires either an EU LLC (Estonia OÜ / Poland sp. z o.o.) or Stripe Atlas (US LLC). Both paths cost money and time we're currently investing in the product. WayForPay accepts Ukrainian ФОП-3, integrates with ПРРО for automatic receipts, and has native UAH recurring without FX exchanges. Stripe remains in the codebase — we'll activate it in Y2 EU expansion.
-
Is it safe to pay via WayForPay?
WayForPay has PCI DSS Level 1 certification (the highest level for payment providers). Card data never touches our servers — you enter it on WayForPay's hosted checkout; we receive only a tokenized identifier for recurring charges. 3-D Secure 2.0 is mandatory. Same for LiqPay, Monobank.
-
How are refunds (returns) automated?
Refunds route to whichever payment provider an order was paid with. If the order was charged via LiqPay, refund via LiqPay's refund API. If via WayForPay, via WayForPay's refund API, etc. The AI agent recognizes a return event via KeyCRM and automatically triggers the refund through the recorded payment provider. Refund logs track all transactions with idempotency — no duplicate charges.
-
What about ПРРО (software cash register) and fiscal receipts?
WayForPay has native ПРРО integration (Cabinet of Taxpayer) — each subscription automatically issues a fiscal receipt to the customer via email. Activated during KYC. For ФОП-3 on the simplified system (5%) selling services to Ukraine residents, this is mandatory. We pass order metadata (service category, VAT rate "VAT-exempt for ФОП-3"), the rest is WayForPay automation.
-
Can I pay with crypto / Apple Pay / Google Pay?
Apple Pay + Google Pay — yes, via WayForPay native wallet support. Cryptocurrencies — no in V1; we'll consider in Y2 when regulatory clarity emerges on NBU directive regarding virtual assets.
-
What if WayForPay is temporarily unavailable?
The architecture is provider-agnostic (see ADR-039) — we can emergency-switch to Stripe with a single env var (BILLING_PROVIDER=stripe) if WayForPay has an extended outage. Existing subscriptions stay with WayForPay; new signups route through Stripe until recovery. This is documented in the production-deploy runbook.
-
How much does WayForPay take? Will it affect my price?
WayForPay commission ~2.7–3% of amount + ПРРО fee (~₴1–2 per receipt). We cover these costs from marketplace margin; your Unitelia price doesn't change. For comparison: Stripe for UA ФОП — 2.9% + $0.30 fixed fee per transaction, which for a $49/mo plan is ~$1.72 vs WayForPay ~$1.32–1.47. Cheaper for small amounts.
-
Do you issue invoices, acts, VAT invoices?
Subscriptions on ФОП-3 — we are ФОП-3 on the simplified system (5%), VAT-exempt. WayForPay automatically generates a fiscal receipt via ПРРО — it is legally a closing document for most cases. If your accounting requires a service agreement in docx format — write to m.nazar77@gmail.com, we'll issue it manually. For legal entities with VAT (rare for UA SMB) — a separate path, not optimized at launch.
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.