SMMFor

Webhook'lar

Sipariş durumu değiştiğinde bayi sunucusuna anında bildirim; yük biçimi, imza doğrulama ve yeniden deneme kuralları.

Ne işe yarar

API kullanan müşterileriniz (bayiler), siparişlerinin durumunu sürekli status ile sormak yerine bir webhook adresi tanımlayabilir. Siparişin durumu her değiştiğinde panel o adrese imzalı bir POST isteği gönderir.

Webhook'lar Müşteri paneli → API & Bayi sayfasından yönetilir:

  • Müşteri başına en fazla 3 adres.
  • Adres https:// olmalı ve herkese açık bir sunucuyu göstermeli (yerel/özel ağ adresleri reddedilir; DNS gönderim anında yeniden kontrol edilir).
  • Gizli anahtar (whsec_ + 48 karakter) yalnızca oluştururken bir kez gösterilir; sonra döndürülebilir (yenilenebilir).
  • Her adres için son 10 teslimat görünür.

Olay ve yük

Tek olay vardır: order.status.

{
  "event": "order.status",
  "order": 12345,
  "service": 101,
  "link": "https://instagram.com/hesap",
  "quantity": 1000,
  "charge": "0.5",
  "status": "Completed",
  "start_count": "0",
  "remains": "0",
  "currency": "USD",
  "created_at": "2026-10-05T10:00:00.000Z",
  "sent_at": "2026-10-05T10:05:12.000Z"
}

status değerleri API v2 ile aynıdır: Pending, In progress, Completed, Partial, Canceled. Maliyet, kâr ve sağlayıcı sipariş numarası asla gönderilmez.

Başlıklar

BaşlıkDeğer
Content-Typeapplication/json
User-AgentSMMPanel-Webhook/1
X-TB-Eventorder.status
X-TB-TimestampUnix zaman damgası (saniye)
X-TB-Signaturesha256=<hex>

İmza doğrulama

İmza, zaman_damgası + "." + ham_gövde metninin gizli anahtarınızla HMAC-SHA256 özetidir. Gövdeyi JSON olarak ayrıştırıp yeniden yazmadan, ham haliyle doğrulayın.

<?php
$body = file_get_contents('php://input');
$ts   = $_SERVER['HTTP_X_TB_TIMESTAMP'];
$sig  = $_SERVER['HTTP_X_TB_SIGNATURE'];
$calc = 'sha256=' . hash_hmac('sha256', $ts . '.' . $body, $secret);
if (!hash_equals($calc, $sig)) { http_response_code(401); exit; }
// İsteğe bağlı: eski istekleri reddedin
if (abs(time() - (int)$ts) > 300) { http_response_code(401); exit; }
$event = json_decode($body, true);
http_response_code(200);
import crypto from "node:crypto";
import express from "express";

const app = express();
app.post("/panel-webhook", express.raw({ type: "application/json" }), (req, res) => {
  const ts = req.header("X-TB-Timestamp");
  const sig = req.header("X-TB-Signature") || "";
  const calc = "sha256=" + crypto.createHmac("sha256", process.env.WHSEC).update(`${ts}.${req.body}`).digest("hex");
  const ok = sig.length === calc.length && crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(calc));
  if (!ok) return res.sendStatus(401);
  const event = JSON.parse(req.body.toString());
  // event.order, event.status …
  res.sendStatus(200);
});

Teslimat ve yeniden deneme

  • Her istek 10 saniye zaman aşımına sahiptir; yönlendirmeler izlenmez.
  • Herhangi bir 2xx yanıt başarılı sayılır.
  • Başarısız teslimat en fazla 8 kez üstel aralıklarla (1 dk, 2 dk, 4 dk… en fazla 6 saat) yeniden denenir.
  • Üst üste 20 başarısız teslimattan sonra adres otomatik devre dışı kalır; panelden yeniden etkinleştirildiğinde sayaç sıfırlanır.
  • Teslimat kayıtları 14 gün saklanır.

Aynı olay birden fazla kez gelebilir (ör. yanıtınız zaman aşımına uğrarsa). İşleyicinizi order + status ikilisine göre tekrar güvenli (idempotent) yazın.