Sign in
Giriş/Webhook bildirimleri

Webhook Bildirimleri

HMAC ile imzalanmış webhook'lar üzerinden gerçek zamanlı ödeme ve çekim durumu güncellemeleri alın.

2328.io sistemi, bir ödeme durumu her değiştiğinde url_callback adresinize bir webhook gönderir. Başarılı ödemeler hakkında bildirim almanın önerilen yolu budur.

İstek formatı

  • Method: POST
  • Content-Type: application/json
  • İmza: istek gövdesindeki sign alanı

Payload

Webhook gövdesi /v1/payment/info yanıtının biçimini izler ve tx_explorer_url ile imza doğrulamasında kullanılan sign alanını ekler.

Başarılı ödeme

JSON
{
  "uuid": "db17d490-15b6-47b9-9015-91d1d8b119f2",
  "order_id": "ORDER-12345",
  "amount": "180.00000000",
  "currency": "RUB",
  "url": "https://go.2328.io/db17d490-15b6-47b9-9015-91d1d8b119f2",
  "expires_at": "2026-05-09T16:56:58+03:00",
  "created_at": "2026-05-09T15:56:58+03:00",
  "payer_currency": "TON",
  "payer_amount": "0.95256917",
  "network": "TON",
  "address": "UQA0RevhkCQx-EltyNgPPeG8dqtnCz7ZslOzMdNQlLxVaNBb",
  "payment_status": "paid",
  "txid": "41c2a327323480af8e705d05deb09c238a41779928832abef4bb77c862357b11",
  "tx_explorer_url": "https://tonviewer.com/transaction/41c2a327323480af8e705d05deb09c238a41779928832abef4bb77c862357b11",
  "payment_amount": "0.95256917",
  "merchant_amount": "0.949711462490000000",
  "amount_usd": "2.41324380",
  "exchange_rate": "0.01340691",
  "sign": "6f8c15b6e53b506d5bfa38ed3fb3b50697af73434262153c02e412541372f04d"
}

İptal edilmiş / başarısız ödeme

Ödeme terminal paid durumunda olmadığında txid, payment_amount ve merchant_amount null'dur:

JSON
{
  "uuid": "48edaf2d-2c49-4638-8f86-88636f661c1f",
  "order_id": "ORDER-12345",
  "amount": "2800.00000000",
  "currency": "RUB",
  "url": "https://go.2328.io/48edaf2d-2c49-4638-8f86-88636f661c1f",
  "expires_at": "2026-05-09T06:19:04+03:00",
  "created_at": "2026-05-09T05:19:04+03:00",
  "payer_currency": "ETH",
  "payer_amount": "0.01620968",
  "network": "ETH-ERC20",
  "address": "0x37c20d6d96d130Bc5B33D832e43b8e16aACe0c59",
  "payment_status": "cancel",
  "txid": null,
  "tx_explorer_url": null,
  "payment_amount": null,
  "merchant_amount": null,
  "amount_usd": "37.53934800",
  "exchange_rate": "0.01340691",
  "sign": "40ce68ad9691ad54e684329d75ab5adaf5b01409a2d18d3e0110b8c1be605342"
}

Alan referansı

AlanTipAçıklama
uuidstringÖdeme UUID'si
order_idstringSipariş ID'niz
amountdecimal (8 dp)currency cinsinden fiat tutarı
currencystringMerchant'ın talep ettiği fiat para birimi
urlstringHosted checkout URL'si
expires_atstring (ISO 8601)Ödeme oturumunun ne zaman süresi dolar
created_atstring (ISO 8601)Ödeme oturumunun ne zaman oluşturulduğu
payer_currencystringÖdeyenin ödeme yaptığı kripto
payer_amountdecimal (8 dp)Beklenen kripto tutarı
networkstringBlockchain ağı
addressstringYatırma adresi
payment_statusstringŞunlardan biri: pending, check, paid, underpaid_check, underpaid, overpaid, cancel, aml_lock (bkz. References)
txidstring | nullBlockchain tx hash'i, yalnızca onaylanmış bir ödemeden sonra mevcut
tx_explorer_urlstring | nullBlockchain gezginindeki işlem URL'si. txid yoksa veya transfer dahili P2P ise null olur.
payment_amountdecimal | nullGerçek ödenen tutar, yalnızca ödemeden sonra mevcut
merchant_amountdecimal (18 dp) | nullÜcretler sonrası merchant'a yansıtılan tutar
amount_usddecimal (8 dp)Oluşturma anındaki USD tutarı
exchange_ratedecimalKullanılan kripto / fiat döviz kuru
signstring (hex)Payload'un HMAC-SHA256 imzası

İmzayı doğrulama

Bir webhook imzasını doğrulamak için:

  1. Payload'dan sign alanını çıkarın
  2. Nesneden sign alanını kaldırın
  3. Kalan alanları JSON olarak encode edin
  4. JSON'u Base64 ile encode edin
  5. API_KEY'inizi kullanarak Base64 string'inden HMAC-SHA256 hesaplayın
  6. Hesaplanan imzayı sign değeri ile sabit zamanlı bir karşılaştırma kullanarak karşılaştırın
PHP
<?php
function verifyWebhookSign(array $data, string $apiKey): bool {
    $receivedSign = $data['sign'] ?? '';
    unset($data['sign']);

    $json = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    $base64 = base64_encode($json);
    $calculated = hash_hmac('sha256', $base64, $apiKey);

    return hash_equals($calculated, $receivedSign);
}

$apiKey = 'YOUR_API_KEY';
$payload = json_decode(file_get_contents('php://input'), true);

if (!verifyWebhookSign($payload, $apiKey)) {
    http_response_code(401);
    exit;
}

switch ($payload['payment_status']) {
    case 'paid':
    case 'overpaid':
        // Credit the order — check idempotency by order_id first
        break;
    case 'underpaid_check':
    case 'underpaid':
    case 'cancel':
        break;
}

http_response_code(200);

Bir kullanıcıya herhangi bir fon yansıtmadan önce her zaman imzayı doğrulayın. İmzasız veya yanlış imzalanmış bir webhook, sahte bir istek olabilir.

Çekim webhook'ları

Bir çekimin status'u değiştiğinde, sistem çekim oluşturulurken geçirilen url_callback URL'ine bir POST webhook gönderir. url_callback sağlanmadıysa, o çekim için webhook gönderilmez.

Çekim webhook'ları normal API key ile değil, Payout API key'iniz ile doğrulanmalıdır. İmzalama algoritması ödeme webhook'larıyla aynıdır (sign'i çıkar, JSON'a encode et, base64, HMAC-SHA256), yalnızca anahtar farklıdır.

Payload

JSON
{
  "uuid": "019dff1f-0dbd-7277-8d45-271e7775388f",
  "order_id": "4dfdcc84402b1185b71cbe399321533e",
  "status": "completed",
  "currency": "TRX",
  "network": "TRX-TRC20",
  "amount": "3.00",
  "merchant_amount": "3.00",
  "network_amount": "3.00",
  "amount_usd": "1.04",
  "to_address": "THauRv5tcucQRohXg8NiyGTk16DX1XQG5x",
  "memo": null,
  "txid": "9242e533703704ef3eaba840f70b4a26333e72c943377ee375fea17badb53def",
  "tx_explorer_url": "https://tronscan.org/#/transaction/9242e533703704ef3eaba840f70b4a26333e72c943377ee375fea17badb53def",
  "block_number": null,
  "error_type": null,
  "created_at": "2026-05-07T00:08:38+03:00",
  "updated_at": "2026-05-07T00:08:54+03:00",
  "from_currency": "USDT",
  "debited_amount": "1.050735",
  "debited_currency": "USDT",
  "sign": "925ad7bf3d6841864101f7cc2c7e30652e70a06cdb04dbe07a0129480000ce4a"
}

Alan referansı

AlanTipAçıklama
uuidstringÇekim UUID'si
order_idstringSağladıysanız idempotency / referans ID'niz
statusstringpending, completed, failed, cancelled (bkz. References)
currencystringÇekim para birimi
networkstringBlockchain ağı
amountdecimalÇekim tutarı (currency cinsinden)
merchant_amountdecimalMerchant bakiyesinden tahsil edilen tutar
network_amountdecimalZincir üzerinde gerçekten gönderilen tutar
amount_usddecimalÇekim anındaki USD değeri
to_addressstringAlıcı blockchain adresi
memostring | nullMemo / hedef etiketi, kullanıldığında
txidstring | nullBlockchain işlem hash'i, completed durumunda ayarlanır
tx_explorer_urlstring | nullBlockchain gezginindeki işlem URL'si. txid yoksa veya transfer dahili P2P ise null olur.
block_numberinteger | nullZincir üzerindeki işlemin blok yüksekliği
error_typestring | nullstatus = failed olduğunda neden (örn. aml_risk, bkz. References)
created_atstring (ISO 8601)Çekimin oluşturulduğu zaman
updated_atstring (ISO 8601)Durumun en son ne zaman değiştiği
from_currencystringOtomatik dönüştürme kullanıldığında çekimin düşüldüğü kaynak bakiye (örn. BTC çekimi için USDT)
debited_amountdecimalfrom_currency bakiyesinden düşülen tutar
debited_currencystringDüşmenin para birimi
signstring (hex)Payload'un Payout API key ile imzalanmış HMAC-SHA256 imzası

En iyi uygulamalar

  • Idempotency — Ödemenin zaten işlenip işlenmediğini her zaman kontrol edin (order_id veya uuid ile). Webhook'lar birden çok kez gelebilir.
  • Hızlı yanıt — Mümkün olduğunca hızlı HTTP 200 dönün. Ağır işleri arka plan kuyruğuna devredin.
  • Yeniden denemeler — Sistem HTTP 200 alamazsa, webhook 2 dakika sonra yeniden gönderilir. En fazla 5 yeniden deneme.
  • Asenkron işleme — Yanıtı bloke etmemek için webhook olaylarını asenkron işleyin.
  • Güvenlik — Payload'a güvenmeden önce HER ZAMAN sign imzasını doğrulayın.

Webhook'lar sıra dışı gelebilir. Aldığınız ilk webhook'un nihai durum olduğunu varsaymayın — kesinlik istiyorsanız her zaman /v1/payment/info (veya /v1/payout/status/{uuid}) üzerinden yeniden alın.

Teslimat ve işleme sözleşmesi

Aşağıdaki sırayı webhook uç noktanız içinde kullanın:

  1. İstek gövdesini, sırları veya tam imzayı kaydetmeden okuyun.
  2. Doğru API anahtarını seçmek için bunun bir ödeme/statik-cüzdan olayı mı yoksa bir ödeme olayı mı olduğunu belirleyin.
  3. sign kaldırın, belgelenmiş JSON baytlarını çoğaltın, HMAC-SHA256 hesaplayın ve sabit zamanda karşılaştırın.
  4. Gerekli tanımlayıcıları, ondalık dizeleri ve durum değerlerini doğrulayın.
  5. inbox/idempotency kaydını atomik olarak ekleyin. Zaten varsa yan etkileri tekrarlamadan HTTP 200 döndürün.
  6. Sipariş/defter mutasyonunu işleyin ve kritik olmayan e-posta, analiz veya bildirimleri sıraya alın.
  7. Hızlı bir şekilde HTTP 200 döndürün.

idempotency işlemini tutarken yavaş üçüncü taraf servislerini çağırmayın. Bir timeout, işleme koyduktan sonra ama döndürmeden önce, retry oluşturabilir; kopya, işlenmiş inbox anahtarını gözlemlemeli ve etkisiz olmalıdır.

OlayBirincil kimlikNotlar
Ödeme oturumuuuid + durum/sürüm kanıtıAynı invoice, birden fazla meşru durum değişikliği üretebilir.
Kısmi ödeme yüklemesiinvoice uuid + txidBirden fazla transfer aynı eksik ödenmiş invoice'ya ait olabilir.
Statik-cüzdan yatırımıağ + txidHer cüzdana yapılan her yatırma işlemi order_id'yı yeniden kullanır.
ÖdemeÖdeme uuid + durumwebhook retry mantığından asla ikinci bir ödeme yaratmayın.

Şemanızda olay kimliği yoksa, doğrulanmış payload hash'i ek denetim kanıtı olarak saklayın, ancak yukarıdaki işletme kimliklerini zaman damgası ile değiştirmeyin.

Sipariş ve reconciliation

Teslimat en az bir kere yapılabilir ve durum mesajları hızlanabilir. "Son istek kazanır" yerine monoton iş kuralları uygulayın:

  • Eski bir etkinlik geç geldiği için yerine getirilen siparişi asla check'a geri taşımayın;
  • underpaid_check]'in önceki kredileri tekrarlamadan ek txidler almasına izin ver;
  • paid ve overpaid]'i başarılı settlement durumları olarak ele almak, farklı miktarlarını koruyarak;
  • underpaid nihai kısmi ödeme sonucu olarak tutulur; yetkili API daha sonra başka bir durum rapor etmedikçe;
  • aml_lock]'i gözden geçirmeye yönlendirmeli ve genel bir retry çalışanının bunu yerine getirmesine izin vermemeli;
  • Geçiş imkansız, bağlam eksik veya finansal olarak belirsiz olduğunda ödeme/ödeme bilgisini sorgulayın.

webhook teslimatı sağlıklı görünse bile planlı reconciliation çalıştırın. Yerel terminal durumu ve kredili tutarınızı /v1/payment/info, /v1/static-wallet/transactions veya /v1/payout/status/{uuid} ile karşılaştırın ve farklılıklar hakkında sessizce defter geçmişini üzerine yazmak yerine uyarı yapın.

Webhook uç nokta güvenliği

  • HTTPS gerektirmeli ve geri çağrıyı halka açık erişilebilir tut; Özel/geri dönüş geri dönüş hedefleri ödeme oluşturulurken reddedilir.
  • Küçük bir istek-gövde sınırı ve JSON içerik türü zorunlu kılın.
  • Pahalı çalışmadan önce oran sınırı olsun, ama gerçek patlamalar ve retries için yeterli boşluk bırakın.
  • Bir webhook'i sadece kaynak IP ile yetkilendirmeyin. Ağ izin listeleri derinlikte savunmadır; HMAC doğrulaması zorunludur.
  • sign, API anahtarlarını, politika gerektirdiğinde adresleri ve uygulama kayıtlarından kişisel meta verileri sansür.
  • Kontrollü bir dönme penceresi boyunca hem güncel hem de açıkça planlanmış yedek anahtarları kullanılabilir tutmak; Bir etkinliği hangi anahtarın işaret ettiğini asla tahmin etmeyin.
  • Geçersiz imzalarda genel bir hata gövdesi döndürün ki uç nokta anahtar veya hesap oracle haline gelmesin.