kokiwa

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ıkAçıklama
Kokiwa-Signaturet=zaman_damgası,v1=imza biçiminde imza.
Kokiwa-Event-IdOlay kimliği, gövdedeki id ile aynı.
Kokiwa-Delivery-AttemptTeslim 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

typeNe zaman gönderilirdata
payment_intent.paidÖdeme tamamen ödendipayment_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 doldupayment_intent
payment_intent.paid_lateÖdemenin süresi dolduktan sonra para geldipayment_intent、deposit
deposit.confirmedBir yatırma zincirde onaylandı (ödemeden veya yatırma adresinden)deposit
deposit.settledBir yatırma alım adresinize ulaştıdeposit
webhook.testPanelden 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.

  1. Kokiwa-Signature içinden t ve v1 değerlerini alın.
  2. Gizli anahtarla {t}.{ham gövde} dizesinin HMAC-SHA256 değerini hesaplayın, küçük harfli onaltılıya çevirin ve v1 ile sabit sürede karşılaştırın.
  3. 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 id değerine göre tekrarları eleyin, güncel durum için GET /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/deposits ile 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.

Connect a wallet with WalletConnect