Webhook
Kesles dapat mengirimkan event realtime ke endpoint HTTPS milik Anda setiap kali terjadi perubahan status pada merchant di portfolio Anda. Ini memungkinkan sistem Anda bereaksi langsung tanpa harus polling API.
Cara Kerja
Kesles Backend
│
├─ Event terjadi (mis. transaksi masuk, status merchant berubah)
│
▼
partner_service mengambil webhook_url dari konfigurasi partner
│
▼
POST {webhook_url}
Headers: X-Kesles-Signature, Content-Type: application/json
Body: { "event_type": "...", "data": {...}, "timestamp": "..." }
│
▼
Server Anda merespons 2xx dalam 10 detik
Kesles mencatat setiap percobaan pengiriman (sukses maupun gagal) di log internal. Webhook bersifat best-effort — tidak ada retry otomatis saat ini; pastikan endpoint Anda reliable dan merespons cepat.
Konfigurasi Webhook
Webhook URL dan secret dikonfigurasi oleh tim Kesles saat onboarding partner. Untuk mengubah URL atau secret, hubungi support@kesles.com atau minta tim Kesles via dashboard internal.
Partner API publik saat ini tidak menyediakan endpoint self-service untuk mengubah webhook config. Ini adalah keterbatasan yang direncanakan untuk diatasi di versi mendatang.
Verifikasi Tanda Tangan
Setiap request webhook dari Kesles menyertakan header X-Kesles-Signature. Nilai header ini adalah HMAC-SHA256 dari request body menggunakan webhook secret yang diberikan saat onboarding.
Format Header
X-Kesles-Signature: sha256=<hex_digest>
Cara Verifikasi (Go)
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
)
func verifyWebhookSignature(body []byte, secret, signature string) bool {
mac := hmac.New(sha256.New, []byte(secret))
mac.Write(body)
expected := "sha256=" + hex.EncodeToString(mac.Sum(nil))
return hmac.Equal([]byte(expected), []byte(signature))
}
Cara Verifikasi (Python)
import hmac
import hashlib
def verify_webhook_signature(body: bytes, secret: str, signature: str) -> bool:
expected = "sha256=" + hmac.new(
secret.encode(), body, hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature)
Selalu gunakan constant-time comparison (hmac.Equal / hmac.compare_digest) saat membandingkan signature — bukan == biasa — untuk mencegah timing attack.
Format Payload
{
"event_type": "transaction.completed",
"event_id": "evt_01j2abcd…",
"timestamp": "2026-06-07T10:30:00+07:00",
"partner_id": "uuid-partner",
"data": {
"merchant_id": "uuid-merchant",
"merchant_code": "MRC-XXXXX",
...
}
}
| Field | Tipe | Deskripsi |
|---|---|---|
event_type | string | Jenis event (lihat katalog di bawah) |
event_id | string | ID unik event — gunakan untuk idempotency |
timestamp | RFC3339 | Waktu event terjadi (timezone +07:00) |
partner_id | UUID | ID partner penerima |
data | object | Payload spesifik per event type |
Katalog Event
Event yang akan Anda terima bergantung pada scope partner yang dikonfigurasi saat onboarding. Berikut event-event yang saat ini didukung:
Transaksi
| Event Type | Trigger | Field utama di data |
|---|---|---|
transaction.completed | Pembayaran QRIS/terminal berhasil | merchant_id, amount, currency, terminal_id, reference_id |
transaction.failed | Pembayaran gagal / expired | merchant_id, amount, failure_reason |
transaction.refunded | Refund berhasil diproses | merchant_id, original_transaction_id, refund_amount |
Status Merchant
| Event Type | Trigger | Field utama di data |
|---|---|---|
merchant.status_changed | Status merchant berubah (active, suspended, pending_review, dll.) | merchant_id, merchant_code, old_status, new_status |
merchant.registered | Merchant baru di-refer oleh partner ini selesai registrasi | merchant_id, merchant_code, referral_code |
Daftar event type di atas adalah event yang saat ini tersedia. Event type baru dapat ditambahkan seiring pengembangan platform — perubahan ini akan dikomunikasikan via email ke alamat kontak partner yang terdaftar.
Keamanan Endpoint
Pastikan endpoint webhook Anda memenuhi persyaratan berikut:
- HTTPS wajib — Kesles menolak konfigurasi URL HTTP atau IP privat
- Respons cepat — Kembalikan
200 OKdalam 10 detik. Jika processing membutuhkan waktu lebih, queue dulu dan proses secara async - Idempotent — Simpan
event_iddan abaikan event duplikat (Kesles bisa mengirim ulang dalam kasus network failure) - Verifikasi signature — Selalu validasi
X-Kesles-Signaturesebelum memproses payload
Troubleshooting
Endpoint Tidak Menerima Event
- Pastikan URL dapat diakses dari internet (bukan localhost atau IP privat)
- Pastikan firewall tidak memblokir koneksi masuk dari IP Kesles
- Hubungi tim Kesles untuk memeriksa log delivery terbaru
Signature Verification Gagal
- Pastikan Anda menggunakan raw request body bytes (sebelum parsing JSON) sebagai input HMAC
- Pastikan secret yang digunakan sesuai dengan yang dikonfigurasi tim Kesles
- Jangan trim whitespace atau modifikasi body sebelum verifikasi
Event Duplikat
Implementasi idempotency dengan menyimpan event_id yang sudah diproses:
INSERT INTO processed_webhook_events (event_id, processed_at)
VALUES ($1, NOW())
ON CONFLICT (event_id) DO NOTHING
RETURNING event_id
Jika RETURNING tidak mengembalikan row, event sudah pernah diproses — skip.