Powiadomienia Webhook
Używaj webhooków, aby odbierać w swojej aplikacji wyniki dostarczania kodów QR i odnowień.
Wprowadzenie
Używaj webhooków, aby odbierać w swojej aplikacji wyniki dostarczania kodów QR i odnowień.
Czym jest webhook?
iRoamly wysyła powiadomienia webhook o dostarczeniu kodów QR i wynikach odnowień. Każdy webhook korzysta z HTTPS i zawiera treść JSON. Za pomocą webhooków możesz:
- Odbierać informacje o kodzie QR po zamianie kodu wymiany lub po zakończeniu bezpośredniego zakupu kodu QR.
- Odbierać wyniki odnowień przez webhook:
esim.renewal.success, gdy kod QR odnowienia jest gotowy,esim.renewal.failed, gdy zamówienie odnowienia u dostawcy nie powiedzie się.
Jeśli Twój endpoint nie odpowie statusem 2xx, iRoamly podejmie łącznie do 5 prób dostarczenia: pierwszą natychmiast, a kolejne po 30 sekundach, 2 minutach, 3 minutach i 5 minutach.
Jak zacząć odbierać webhooki
Aby zacząć odbierać zdarzenia w czasie rzeczywistym w aplikacji, wykonaj następujące kroki:
- Utwórz lokalny endpoint do odbierania żądań
- Zarejestruj endpoint webhooka w sekcji Dla programistów > Powiadomienia Webhook w panelu iRoamly Shop
1. Utwórz lokalny endpoint do odbierania żądań
W lokalnej aplikacji utwórz nową trasę przyjmującą żądania POST.
Na przykład możesz dodać trasę API w Next.js:
import type { NextApiRequest, NextApiResponse } from 'next';
export default (req: NextApiRequest, res: NextApiResponse) => {
if (req.method === 'POST') {
const payload = req.body;
console.log(payload);
res.status(200);
}
};Po odebraniu zdarzenia odpowiedz statusem HTTP 200 OK, aby zasygnalizować iRoamly, że zdarzenie zostało dostarczone.
2. Zarejestruj deweloperski endpoint webhooka
Zarejestruj publicznie dostępny URL HTTPS w panelu iRoamly Shop.
Możesz utworzyć tunel do serwera localhost za pomocą narzędzia takiego jak ngrok.

3. Sprawdź, czy endpoint webhooka działa poprawnie
Zamień testowy kod wymiany na kod QR lub dokonaj bezpośredniego zakupu kodu QR, aby sprawdzić, czy endpoint webhooka odbiera zdarzenie.
Typy zdarzeń
Lista obsługiwanych typów zdarzeń i ich treści.
Dostarczanie
Każde zdarzenie jest dostarczane w ten sam sposób: żądanie POST z treścią JSON do każdego endpointu subskrybującego to zdarzenie. Każda odpowiedź 2xx oznacza dostarczenie; w przeciwnym razie żądanie jest ponawiane, łącznie do 5 prób (pierwsza natychmiast, kolejne po 30 sekundach, 2 minutach, 3 minutach i 5 minutach). Każde żądanie zawiera te nagłówki:
Sposób sprawdzania podpisów opisano w sekcji Weryfikacja żądań webhooka.
esim.qrcode
Informacje o kodzie QR eSIM zwracane po wymianie lub zakupie kodu QR eSIM.
Przykładowa treść żądania
{
"code": 0,
"data": {
"activation_code": "CD112885573C49DDA42F64C905B925F4",
"code": "UtTpoKCe769u2tt",
"create_at": "2025-09-01 11:34:30",
"isrenew": 0,
"order_id": "ESIM202509021134343282",
"plan_name": "Japan-eSIM-3GB-15 Days-Daily",
"qrcode": "https://www.iroamly.com/qrcode/20250901/xSQfryvOWo0QUhsGcbpeTm9wWYfGu9BQ.png",
"qrcode_content": "LPA:1$rsp1.cmlink.com$CD352885573C49DDA42F64C905B925F4",
"sm_dp_address": "rsp1.cmlink.com"
},
"event_type": "esim.qrcode"
}esim.renewal.success
Wysyłane, gdy odnowienie się powiedzie: gdy dostawca zwróci dane pobierania zamówienia odnowienia, system wygeneruje kod QR dla kodu odnowienia, a jego status zmieni się na 2 (wymieniony).
Nagłówki żądania
esim.renewal.successŻądanie zawiera też X-Webhook-Delivery, X-Webhook-Timestamp, X-Webhook-Signature i X-Webhook-Signature-V2, tak jak każde zdarzenie (zob. Typy zdarzeń).
Przykładowa treść żądania
{
"code": 0,
"data": {
"activation_code": "CD112885573C49DDA42F64C905B925F4",
"code": "RnB7xTq2Lm9pQaZ",
"create_at": "2026-10-28 09:12:41",
"download_url": "LPA:1$rsp1.cmlink.com$CD352885573C49DDA42F64C905B925F4",
"iccid": "8944501234567890123",
"iscouldrenewal": 1,
"isrenew": 1,
"plan_name": "Japan-eSIM-3GB-15 Days-Daily",
"qrcode": "https://www.iroamly.com/qrcode/20261028/xSQfryvOWo0QUhsGcbpeTm9wWYfGu9BQ.png",
"qrcode_content": "LPA:1$rsp1.cmlink.com$CD352885573C49DDA42F64C905B925F4",
"renew_order_id": "TG202610280912410001",
"renewal_father_code": "UtTpoKCe769u2tt",
"sm_dp_address": "rsp1.cmlink.com"
},
"event_type": "esim.renewal.success"
}Pola
esim.renewal.failed
Wysyłane, gdy odnowienie się nie powiedzie: dostawca odpowie na zamówienie odnowienia kodem innym niż 0000 lub żądanie do dostawcy zakończy się błędem.
(Uwaga: brak lub opóźnienie wywołania zwrotnego od dostawcy nie powoduje tego zdarzenia. Ustaw limit czasu i w razie potrzeby odpytaj kod — zob. Obsługa zdarzeń odnowienia.)
Nagłówki żądania
esim.renewal.failedŻądanie zawiera też X-Webhook-Delivery, X-Webhook-Timestamp, X-Webhook-Signature i X-Webhook-Signature-V2, tak jak każde zdarzenie (zob. Typy zdarzeń).
Przykładowa treść żądania
{
"code": -1,
"data": {
"code": "RnB7xTq2Lm9pQaZ",
"create_at": "2026-10-28 09:12:41",
"error_msg": "TuGe_RenewOrderEx RespCode: 9999",
"isrenew": 1,
"plan_name": "Japan-eSIM-3GB-15 Days-Daily",
"renewal_father_code": "UtTpoKCe769u2tt"
},
"event_type": "esim.renewal.failed"
}Pola
Odnowienia i esim.qrcode
Odnowienia nie są już dostarczane jako esim.qrcode; to zdarzenie jest wysyłane przy zamianach na kody QR i bezpośrednich zakupach kodów QR. W porównaniu z treścią esim.qrcode:
event_typei nagłówekX-Webhook-Eventmają wartośćesim.renewal.successlubesim.renewal.failed, aisrenewma wartość1.data.codeto nowy kod wymiany utworzony przez odnowienie; odnowiony kod todata.renewal_father_code.esim.renewal.successdodajerenew_order_id,renewal_father_code,iscouldrenewal,download_urliiccidoraz nie zawieraorder_id.- Nieudane odnowienie jest zgłaszane przez
esim.renewal.failed, zcodenajwyższego poziomu równym-1i błędem dostawcy wdata.error_msg.
Subskrypcje zdarzeń
Nowe endpointy domyślnie subskrybują wszystkie trzy zdarzenia. Istniejące endpointy automatycznie otrzymują esim.renewal.success i esim.renewal.failed — nie trzeba niczego zmieniać.
Obsługa zdarzeń odnowienia
- Zadbaj o idempotentność obsługi. Ponowienie może dostarczyć to samo zdarzenie więcej niż raz, więc usuwaj duplikaty według
X-Webhook-Deliverylubevent_type+data.codei ignoruj już przetworzone zdarzenia. - Stosuj limit czasu. Jeśli w rozsądnym czasie nie nadejdzie ani
esim.renewal.success, aniesim.renewal.failed, odpytaj kod przez API zapytań (np. Query QR Code), zamiast zakładać, że odnowienie się nie powiodło. - Nie używaj
esim.renewal.faileddo decydowania o zwrotach. Zdarzenie informuje jedynie, że zamówienie u dostawcy się nie powiodło; o tym, czy i kiedy kredyty zostaną zwrócone, decyduje się osobno, więc nie zwracaj klientom należności na podstawie tego zdarzenia.
Weryfikacja żądań webhooka
Zweryfikuj podpis iRoamly w żądaniach webhooka.
Jak zweryfikować podpis iRoamly?
Podpis iRoamly jest wysyłany w nagłówku X-Webhook-Signature żądania webhooka jako sha256=, a po nim podpis zakodowany szesnastkowo. Podpis jest generowany algorytmem HMAC-SHA256 z sekretem webhooka jako kluczem i surową treścią żądania (dokładnie w postaci otrzymanej, przed parsowaniem JSON) jako wiadomością.
Przykładowy nagłówek webhooka
{
'X-Webhook-Signature': 'sha256=dd7bdd2cf1f6bac6e171c6c508c157b7cd3cc1fd196394277fb59ba0bdd9b87b'
}Sekret webhooka znajdziesz w panelu w sekcji Dla programistów > Powiadomienia Webhook.

Aby wygenerować podpis, możesz użyć następującego fragmentu kodu:
import * as crypto from 'crypto';
generateSignature(payload: string, secret: string): string {
const computedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return 'sha256=' + computedSignature;
}W powyższym fragmencie kodu payload to surowa treść żądania, a secret to sekret webhooka. Wystarczy porównać wygenerowany podpis (wraz z prefiksem sha256=) z wartością nagłówka X-Webhook-Signature, aby zakończyć weryfikację.
Podpis ze znacznikiem czasu (X-Webhook-Signature-V2)
Każde żądanie zawiera też X-Webhook-Signature-V2: v1=, a po nim zakodowany szesnastkowo HMAC-SHA256, z tym samym sekretem webhooka, z {timestamp}.{body} — wartości nagłówka X-Webhook-Timestamp, kropki i surowej treści żądania.
Po rotacji sekretu webhooka stary sekret pozostaje ważny przez 24 godziny. W tym czasie X-Webhook-Signature jest nadal podpisywany starym sekretem, a X-Webhook-Signature-V2 zawiera po jednej wartości dla każdego sekretu, rozdzielone przecinkami (v1=<old>,v1=<new>): zaakceptuj żądanie, jeśli pasuje dowolna wartość.