WordPress Plugin

Monobank Installment Checkout for WooCommerce

A custom WordPress plugin that lets shoppers pay in installments via a Ukrainian bank's merchant API — phone validation, signed requests, and full order lifecycle.

  • PHP
  • WordPress
  • cURL
  • HMAC-SHA256
  • AJAX
Illustration of a payment card split into installment segments

The ask

A marketing agency’s e-commerce clients wanted “pay in installments” at checkout — a popular option in Ukraine, where a major bank offers merchants an installment program (“оплата частинами”) through its own payment API. No off-the-shelf WooCommerce gateway existed for it, so I built the integration from scratch as a standalone plugin, addressable anywhere on a site through a single shortcode: [mono_chast].

How the flow works

  • Phone-first, not card-first. The customer types their phone number; the plugin validates it against the bank’s /client/validate endpoint before anything else happens — installment eligibility in this program is tied to the client’s bank relationship, not a card number typed into a form.
  • Every request is signed. Each API call — validate, create, confirm, check, reject, return — is a POST with a store-id header and an HMAC-SHA256 signature of the JSON body, computed server-side and never exposed to the browser. The frontend only ever talks to WordPress’s own admin-ajax.php; the signing key and the bank’s endpoint never reach client-side JavaScript.
  • The order has a full lifecycle, not just “create.” Beyond starting an installment order, the plugin exposes confirm, reject, check-paid, get state, get info, request a return, and pull a settlement report — the complete set of operations a merchant actually needs once an order exists, not just the checkout moment.
  • An admin panel doubles as an ops console. Rather than digging through server logs to debug a stuck order, the settings page has one button per API action — paste an order ID, click “Check Paid” or “State order,” and see the bank’s raw response immediately. It turned “is this order actually paid?” from a support escalation into a 10-second admin-panel check.

The detail that mattered

Every one of these bank endpoints — reject, confirm, check, return — needs to be idempotent-safe from the merchant’s side: nothing about a failed or double-clicked request should be able to charge, refund, or cancel twice. Centralizing every API call through one make_api_request() helper meant the signing, headers and error handling lived in exactly one place, so every new operation added to the plugin got that safety by construction instead of by remembering to copy it correctly each time.

Result

Shoppers get a “pay in installments” option that a large share of Ukrainian buyers already trust from using it elsewhere, without the agency’s clients needing to onboard a whole new payment processor stack — it plugs into the checkout they already have.