Webhook'lar
Bir ödeme yansıtıldığında veya ödeme durumu değiştiğinde kokiwa, https adresinize POST isteği gönderir. Adresleri satıcı panelindeki Webhook'lar sayfasından yönetin.
Hemen kopyalanabilir kod mu arıyorsunuz? Node.js, Python, PHP, Go ve Java entegrasyon örnekleri
İstek biçimi
{
"id": "evt_3Fk9Qw2Lm7Rt5Xb1Nc8Vz4",
"type": "payment_intent.paid",
"created_at": "2026-11-02T08:41:07Z",
"livemode": true,
"data": {
"payment_intent": { "id": "pi_7Gm4Rk2Wp9Ls1Qv8Bd3Zt6", "object": "payment_intent", "status": "paid", "...": "..." },
"deposit": { "id": "dep_9Kx2Pa6Wn3Ty8Lq5Rb1Ms4", "object": "deposit", "status": "settled", "...": "..." }
}
}| Başlık | Açıklama |
|---|---|
Kokiwa-Signature | t=zaman_damgası,v1=imza biçiminde imza. |
Kokiwa-Event-Id | Olay kimliği, gövdedeki id ile aynı. |
Kokiwa-Delivery-Attempt | Teslim denemesi, 1'den başlar. |
data.deposit, yatırma nesnesidir. data.payment_intent, ödeme getirildiğinde dönen nesnedir ama checkout_url ve livemode içermez; livemode olayın en üst düzeyindedir.
Olay türleri
| type | Ne zaman gönderilir | data |
|---|---|---|
payment_intent.paid | Ödeme tamamen ödendi | payment_intent、deposit |
payment_intent.partially_paid | Ödeme tutarının bir kısmı alındı | payment_intent、deposit |
payment_intent.expired | Ödeme ödenmeden süresi doldu | payment_intent |
payment_intent.paid_late | Ödemenin süresi dolduktan sonra para geldi | payment_intent、deposit |
deposit.confirmed | Bir yatırma zincirde onaylandı (ödemeden veya yatırma adresinden) | deposit |
deposit.settled | Bir yatırma alım adresinize ulaştı | deposit |
webhook.test | Panelden gönderdiğiniz test olayı | message |
Cüzdanla ödeme, ödeme işleminin içinde sonuçlanır; bu yüzden deposit.confirmed ve deposit.settled birlikte gelir. Transferde önce deposit.confirmed, toplamadan sonra deposit.settled gelir. Kullanıcıya confirmed ile yansıtın; settled beklemeniz gerekmez.
İmzayı doğrulayın
Her webhook adresinin kendi imza gizli anahtarı (whsec_…) vardır ve oluşturulurken bir kez gösterilir.
Kokiwa-Signatureiçindentvev1değerlerini alın.- Gizli anahtarla
{t}.{ham gövde}dizesinin HMAC-SHA256 değerini hesaplayın, küçük harfli onaltılıya çevirin vev1ile sabit sürede karşılaştırın. tşu andan 5 dakikadan fazla farklıysa isteği reddedin.
Ham istek gövdesini kullanın. JSON'u ayrıştırıp yeniden serileştirmek baytları değiştirir ve imza eşleşmez.
Node.js
import crypto from "node:crypto";
import express from "express";
const app = express();
const secret = process.env.KOKIWA_WEBHOOK_SECRET;
app.post("/kokiwa/webhook", express.raw({ type: "application/json" }), (req, res) => {
const header = req.get("Kokiwa-Signature") ?? "";
const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
const expected = crypto.createHmac("sha256", secret)
.update(`${parts.t}.${req.body}`).digest("hex");
const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) < 300;
const match = parts.v1?.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
if (!fresh || !match) {
return res.sendStatus(400);
}
const event = JSON.parse(req.body);
// deduplicate by event.id, process, then return 2xx quickly
res.sendStatus(200);
});Go
func verify(secret, body []byte, header string) bool {
var t, v1 string
for _, p := range strings.Split(header, ",") {
k, v, _ := strings.Cut(strings.TrimSpace(p), "=")
switch k {
case "t":
t = v
case "v1":
v1 = v
}
}
ts, err := strconv.ParseInt(t, 10, 64)
if err != nil || math.Abs(float64(time.Now().Unix()-ts)) > 300 {
return false
}
mac := hmac.New(sha256.New, secret)
mac.Write([]byte(t + "."))
mac.Write(body)
return hmac.Equal([]byte(hex.EncodeToString(mac.Sum(nil))), []byte(v1))
}Python
import hashlib, hmac, time
def verify(secret: bytes, body: bytes, header: str) -> bool:
parts = dict(p.strip().split("=", 1) for p in header.split(","))
t, v1 = parts.get("t", ""), parts.get("v1", "")
if not t.isdigit() or abs(time.time() - int(t)) > 300:
return False
expected = hmac.new(secret, f"{t}.".encode() + body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, v1)Yanıtlar ve yeniden denemeler
- 10 saniye içinde herhangi bir 2xx döndürün, uzun işleri arka plan kuyruğuna taşıyın.
- 2xx dışı yanıtlar, zaman aşımları ve bağlantı hataları 11 kez yeniden denenir: 30 saniye, 2, 10 ve 30 dakika, sonra 1, 2, 4, 8, 12, 24 ve 20 saat sonra. Teslim yaklaşık 3 gün sonra durur.
- Bir olay birden çok kez gelebilir ve sıra garanti edilmez. Olay
iddeğerine göre tekrarları eleyin, güncel durum içinGET /v1/payment_intents/{id}çağırın. - Webhook'lar sayfası her teslimin sonucunu gösterir ve elle yeniden göndermenizi sağlar.
- Tüm denemeler başarısız olursa kaçan yatırmaları
GET /v1/depositsile tamamlayın.
Telegram bildirimleri
Her yatırma için mesaj almak üzere Ayarlar sayfasında @KoKiWaPayBot bağlayın. Yalnızca hatırlatmadır, webhook'ların yerini tutmaz.