Co to jest MonoPay/plata by mono i jak wygląda integracja
W skrócie: tworzysz fakturę na swoim backendzie za pośrednictwem interfejsu API monobanku, otrzymujesz invoiceId i pageUrl w odpowiedzi, wysyłasz użytkownika do zapłaty i ustalasz wynik zgodnie ze zdarzeniem, które monobank wysyła na Twój webHookUrl. sam monobank bezpośrednio zaleca rozważenie webhooka jako głównego mechanizmu uzyskiwania statusów i używanie metody sprawdzania statusu jedynie jako „planu B” w przypadku desynchronizacji.
Kluczowe punkty połączenia:
-
Łączenie, nabywanie w biurze firmy i odbieranie tokena (X-Token).
-
Utwórz fakturę (
/api/merchant/invoice/create) z kwotą, opisem iredirectUrliwebHookUrl. -
Płatność na
pageUrl(karta/Apple Pay/Google Pay/płatność w aplikacji – zależy od scenariusza). -
Webhook od monobanku na temat zmiany statusu faktury.
-
Weryfikacja podpisu webhook (ECDSA, nagłówek
X-Sign). -
Potwierdzenie w Twoim systemie: zmieniasz status zamówienia/subskrypcji/konta.
-
Sprawdzenie kopii zapasowej stanu (
/api/merchant/invoice/status) w razie potrzeby.
Uzyskanie rejestracji i połączenia: co zrobić przed napisaniem kodu
Aby połączyć usługi nabycia, musisz być zarejestrowany jako osoba prowadząca jednoosobową działalność gospodarczą i mieć otwarte konto dla jednoosobowej działalności gospodarczej w trybie mono.
Następną czynnością jest autoryzacja w gabinecie internetowym i uzupełnienie informacji o firmie (rodzaj działalności, link do strony/sieci społecznościowe), po czym wybierasz i podłączasz instrumenty płatnicze.
To ważne: jeśli nawiązywanie połączenia nie jest połączone, po prostu nie będziesz mieć tokena dla API („stanie się dostępny po nawiązaniu połączenia”).
Uzyskanie dokumentacji obejmuje jasne kroki umożliwiające uzyskanie tokena:
-
wejdź do biura internetowego;
-
przejdź do zakładki żądanej metody płatności i kliknij „Konfiguruj”;

- Możesz teraz utworzyć token

Następnie przekazujesz ten token w nagłówku X-Token dla żądań API.
Środowisko testowe
monobank daje możliwość pracy w środowisku testowym: do tego potrzebny jest token testowy, a dane „karty” mogą być dowolne ważne (z ważnym numerem zgodnie z algorytmem Luna) - autoryzacja finansowa będzie nie nastąpi, ale odepchniesz integrację.
Architektura integracji: co przechowywać w bazie danych
Aby mieć kontrolę nad integracją (a nie później rozumieć, dlaczego „pieniądze przyszły, ale zamówienie nie zostało opłacone”), radzę zachować przynajmniej:płatności / faktury
-
id(wewnętrzny) -
id_zamówienia(lub inny identyfikator firmy) -
id_faktury(z monobanku) -
kwota(w jednostkach minimalnych, np. groszach) -
ccy(ISO 4217, domyślnie 980) -
stan(utworzono/przetwarzanie/sukces/wygasło/niepowodzenie itp.) -
created_at,updated_at -
modified_date(z monobankiem - krytyczne dla prawidłowej kolejności webhooków) -
raw_last_payload(opcjonalny, ale przydatny do debugowania)
Dlaczego modifiedDate jest ważny?
monobank ostrzega, że ebhooki nie są gwarantowane jeden po drugim i teoretycznie status=success może wystąpić przed status=processing. Dlatego „poprawna prawda” to zdarzenie z dłuższą modifiedDate.
Licz także ponowne próby: moduł pozyskiwania wykonuje do 3 prób POST elementu webhook, dopóki nie uzyska 200 OK. Oznacza to: moduł obsługi webhooka powinien być idempotent (przywrócenie tego samego stanu nie powinno spowodować uszkodzenia systemu).
Faktura/tworzenie: kluczowe parametry i przykład żądania
Punkt końcowy
Oficjalna metoda tworzenia konta:
POST https://api.monobank.ua/api/merchant/invoice/create
Nagłówki
-
X-Token: -
opcjonalnie:
X-Cms/X-Cms-Version— jeśli tworzysz moduł dla CMS (przydatne, jeśli integracja jest spakowana jako wtyczka).
Treść żądania: wymagania minimalne
Zazwyczaj używane minimum:
-
kwota— kwota w jednostkach minimalnych (dla hrywny — kopiejek) -
ccydomyślnie wynosi 980 -
merchantPaymInfo— „ludzkie” informacje o płatności:referencja,miejsce docelowe,komentarz, koszykbasketOrder(szczególnie istotne dla e-commerce) -
redirectUrl— gdzie zwrócić klienta po zrealizowaniu płatności (powodzenie czy błąd) -
webHookUrl— gdzie monobank wyśle status przy zmianie (z wyjątkiemwygasł) -
validity— czas życia konta w sekundach (domyślnie 24 godziny) -
paymentType—debetlubwstrzymaj(jeśli wymagane jest wstrzymanie z dalszą finalizacją)
W odpowiedzi otrzymujesz:
-
Identyfikator faktury -
pageUrl(link do płatności)
Przykład PHP 8.x (cURL)
<?php
$token = getenv('MONO_X_TOKEN');
$payload = [
'amount' => 19900, // 199,00 UAH -> w kopiejkach
'ccy' => 980,
'merchantPaymInfo' => [
'reference' => 'ORDER-100045', // Twój unikalny numer referencyjny
'destination' => 'Płatność za zamówienie nr 100045',
'comment' => 'Dziękujemy za zakup',
'basketOrder' => [
[
'name' => 'Subskrypcja PRO, 1 miesiąc',
'qty' => 1,
'sum' => 19900,
'total' => 19900,
'unit' => 'sztuka.',
'code' => 'SUB-PRO-1M',
],
],
],
'redirectUrl' => 'https://example.com/pay/return',
'webHookUrl' => 'https://example.com/pay/mono/webhook',
'validity' => 3600,
'paymentType' => 'debit',
];
$ch = curl_init('https://api.monobank.ua/api/merchant/invoice/create');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'X-Token: ' . $token,
],
CURLOPT_POSTFIELDS => json_encode($payload, JSON_UNESCAPED_UNICODE),
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
throw new RuntimeException("Monobank create invoice failed: HTTP $httpCode; body=$response");
}
$data = json_decode($response, true);
$invoiceId = $data['invoiceId'];
$pageUrl = $data['pageUrl'];
// 1) przechowuj identyfikator faktury w bazie danych wraz z identyfikatorem zamówienia
// 2) przekieruj klienta do $pageUrl
header('Location: ' . $pageUrl, true, 302);
exit;
Semantyka pól i samego punktu końcowego odpowiada dokumentacji: suma w jednostkach minimalnych, redirectUrl, webHookUrl, a odpowiedź zawiera invoiceId i pageUrl.
Zwrot użytkownika: redirectUrl
Po dokonaniu płatności użytkownik zostanie przekierowany do Twojego redirectUrl (GET). Strony są często tworzone tutaj:
-
„Płatność powiodła się, realizujemy zamówienie”
-
„Płatność nie powiodła się, spróbuj ponownie”
Ale to jest fundamentalnie ważne: nie jest konieczne potwierdzanie płatności tylko na podstawie faktu przekierowania.
Przekierowanie to UX klienta, który można przerwać, zastąpić, zwolnić lub użytkownik może po prostu zamknąć zakładka.
Po stronie serwera konieczne jest przetwarzanie:
-
webhook ze statusem (z weryfikacją podpisu) lub
-
kopia zapasowa: żądanie statusu faktury.
Webhook: odbiór zdarzeń i weryfikacja podpisu (ECDSA, X-Sign)
Jak powstają webhooki
monobank wysyła POST do webHookUrl, gdy zmienia się status (z wyjątkiem wygasł), treść żądania identyczne z odpowiedzią metody „Account Status”, a w nagłówkach znajduje się X-Sign — podpis treści webhooka zgodnie ze standardem ECDSA.
Ważne są również dwie funkcje:
- do 3 prób dostarczenia do
200 OK - wydarzenia mogą nastąpić nie w kolejności chronologicznej, skup się na
modifiedDate.
Odbieranie klucza publicznego
W przykładzie z dokumentacji wskazano, że klucz publiczny do weryfikacji należy uzyskać poprzez punkt końcowy https://api.monobank.ua/api/merchant/pubkey.
Praktyczny przykład weryfikacji PHP
Poniżej znajduje się przykład dostosowany do prawdziwego modułu obsługi webhooka. Logika:
-
przeczytaj surową treść;
-
weź
X-Sign; -
weryfikuj za pomocą
openssl_verify; -
jeśli ok - parsujemy JSON i aktualizujemy status w bazie danych biorąc pod uwagę
modifiedDate.
function getMonoPubKeyPem(string $token): string
{
$ch = curl_init('https://api.monobank.ua/api/merchant/pubkey');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['X-Token: ' . $token],
]);
$resp = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($code !== 200) {
throw new RuntimeException("Cannot fetch monobank pubkey: HTTP $code; body=$resp");
}
// W dokumentacji przykłady działają z reprezentacją PEM w formacie base64.
// Tutaj zakładamy, że API zwraca ciąg w formacie base64, który należy zdekodować.
return base64_decode(trim($resp));
}
$token = getenv('MONO_X_TOKEN');
$rawBody = file_get_contents('php://input');
$xSign = $_SERVER['HTTP_X_SIGN'] ?? '';
if ($xSign === '') {
http_response_code(400);
echo 'Missing X-Sign';
exit;
}
$signature = base64_decode($xSign);
$pubKeyPem = getMonoPubKeyPem($token);
$pubKey = openssl_get_publickey($pubKeyPem);
if ($pubKey === false) {
http_response_code(500);
echo 'Invalid pubkey';
exit;
}
// OPENSSL_ALGO_SHA256 — jak w przykładach dokumentacji
$ok = openssl_verify($rawBody, $signature, $pubKey, OPENSSL_ALGO_SHA256);
if ($ok !== 1) {
http_response_code(401);
echo 'Invalid signature';
exit;
}
$payload = json_decode($rawBody, true);
if (!is_array($payload) || empty($payload['invoiceId'])) {
http_response_code(400);
echo 'Bad payload';
exit;
}
$invoiceId = $payload['invoiceId'];
$status = $payload['status'] ?? 'unknown';
$modifiedDate = $payload['modifiedDate'] ?? null;
// Następnie logika biznesowa:
// 1) znajdź rekord w bazie danych według identyfikatora faktury
// 2) porównaj datę modyfikacji (nie aktualizuj o starszą zawartość)
// 3) jeśli status=success -> oznacz zamówienie jako opłacone
// 4) zwróć 200 OK, aby monobank nie śledził ponownie webhooka
http_response_code(200);
echo 'OK';
Ważne szczegóły (pochodzą z dokumentacji):
X-Sign— podpis ECDSA treści webhooka;data modyfikacjito główne kryterium określające, który status jest istotny;- treść webhooka odpowiada strukturze „statusu faktury”, która zawiera
invoiceId,status, kwoty, przyczyny błędów itp.
Pola stanu i odpowiedzi: czego właściwie używać w logice biznesowej
Metoda statusu faktury zwraca przydatny zestaw pól, w tym:
-
Identyfikator faktury -
status(np.utworzono) -
failureReasonierrCode(gdy płatność nie powiodła się) -
kwota,ccy,finalAmount -
data utworzenia,data modyfikacji -
referencja,miejsce docelowe -
paymentInfo(karta zamaskowana,rrn,tranIditp. — przydatne dla zwierząt) -
cancelList, inne obiekty
W przykładzie z dokumentacji pola te są bezpośrednio widoczne w próbce odpowiedzi.
Praktyczne zalecenie:
w większości scenariuszy e-commerce używasz co najmniej:
-
stan -
Identyfikator faktury -
data modyfikacji -
finalAmount(jeśli możliwe są dla Ciebie częściowe odpisy/prowizje/wstrzymania)
I failureReason / errCode — aby pokazać danej osobie odpowiedni komunikat („Niewystarczające środki”, „Nieprawidłowe CVV” itp.), a nie zamień płatność w „magię, która nie działa”.
Sprawdzanie statusu płatności (faktura/status) jako „ubezpieczenie”
Punkt końcowy:
-
GET /api/merchant/invoice/status?invoiceId={invoiceIdz nagłówkiemX-Token
monobank wprost mówi: nie używaj tej usługi jako głównego mechanizmu po transakcji; lepsze niż webhooki. Jednak w przypadkach, gdy „webhook nie dotarł” lub „wystąpiła przestój po stronie sprzedawcy”, jest to właściwe narzędzie do przywracania spójności.
Przykład PHP
$token = getenv('MONO_X_TOKEN');
$invoiceId = $_GET['invoiceId'];
$url = 'https://api.monobank.ua/api/merchant/invoice/status?invoiceId=' . urlencode($invoiceId);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['X-Token: ' . $token],
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
throw new RuntimeException("Monobank status failed: HTTP $httpCode; body=$response");
}
$data = json_decode($response, true);
// Następnie: sprawdź data['status'], data['modifiedDate'], data['finalAmount'] i zaktualizuj bazę danych
Gotowe moduły i integracje: kiedy lepiej nie pisać kodu od zera
Jeśli Twoja witryna działa już na popularnym systemie CMS/builderze, czasami najlepszym rozwiązaniem jest nie wymyślanie koła na nowo, ale zapewnienie gotowej integracji.
Oficjalna strona gotowych integracji
monobank posiada scentralizowaną stronę, na której gromadzone są gotowe integracje i moduły płatności dla różnych systemów („po kliknięciu na logo partnera możesz przejść do instrukcji konfiguracji”).
To jest opcja „minimalna niestandardowa”: wstawiłem token w ustawieniach – i działa.
Przykład: WooCommerce / WordPress
Istnieje oficjalna wtyczka do WordPress/WooCommerce (wtyczka płatności Monobank WP), która jest pozycjonowana jako oficjalny moduł do łączenia się online nabywanie.
Przykład: OpenCart
Ekosystem OpenCart zawiera także moduły dla MonoPay (w tym publiczne katalogi/fora modułów).
Kiedy moduł jest najlepszym wyborem
Wybierz moduł, jeśli:
-
musisz „szybkiego rozpoczęcia płatności” bez niestandardowej logiki;
-
nie planujesz skomplikowanych scenariuszy (wstrzymania, tokenizacja, podzielone płatności, Twoje rozliczenia);
-
chcesz uzyskać pomoc w zakresie aktualizacji „w ramach CMS”.
Kiedy wymagana jest integracja API
Napisz swoją integrację poprzez API, jeśli:
-
masz niestandardowy backend (Laravel/CI/Symfony/Node/Go itp.) i nietypową logikę płatności;
-
wymagane złożone scenariusze (np. wstrzymanie/finalizacja, tokenizacja, wiele produktów z własnymi regułami);
-
chcesz mieć pełną kontrolę: własne ponowne próby, uzgodnienia, audyt zdarzeń, logika zapobiegająca oszustwom.
Praktyczna lista kontrolna „zrobione i zapomniane”: jak zapewnić integrację w zakresie jakości produkcji
-
Token przechowuj tylko w kluczach tajnych/ENV (nie w kodzie ani w repozytorium).
-
referencjaspraw, aby była ona wyjątkowa po Twojej stronie (np.ZAMÓWIENIE-). Bardzo pomaga w porównaniach. -
Punkt końcowy webhooka:
-
musi szybko odpowiedzieć
200 OK; -
musi być idempotentny;
-
musi zweryfikować
X-Sign.
-
-
Logika aktualizacji stanu:
-
nie ufaj kolejności nadejścia zdarzeń;
-
zawsze porównuj
modifiedDatei nie zastępuj „nowego” statusu „starym”.
-
-
Wykonaj zadanie uzgadniające (korona/kolejka): raz na N minut sprawdzaj „zawieszone” faktury za pomocą
faktura/status(tylko dla tych, którzy nie mieli webhook). Jest to zgodne z wyznaczeniem metody statusu jako metody zastępczej. -
Przed uruchomieniem w produkcie:
-
uruchom środowisko testowe z tokenem testowym;
-
sprawdź, czy Twoje adresy URL są dostępne z Internetu i nie są blokowane przez WAF/Cloudflare;
-
sprawdź, czy „sukces” rzeczywiście powoduje konwersję zamówienia na „płatne” tylko na serwerze (webhook/status), a nie „przez przekierowanie”.
-
Integracja MonoPay (plata by mono) dobrze wpisuje się w nowoczesną architekturę „faktura → strona płatności → webhook → potwierdzenie w bazie danych”, ale o jakości rozwiązania decydują trzy rzeczy:
-
poprawne zarządzanie połączeniem i tokenami w biurze firmy;
-
poprawna obsługa webhooków (podpis +
modifiedDate+ idempotencja); -
posiadają mechanizm uzgadniania kopii zapasowych za pomocą
faktura/statusw przypadku rzadkich desynchronizacji.