Sign in
مقدمة/إشعارات Webhook

إشعارات Webhook

تلقَّ تحديثات حالة المدفوعات والسحوبات في الوقت الفعلي عبر webhooks موقّعة بـ HMAC.

يرسل نظام 2328.io webhook إلى url_callback الخاص بك كلما تغيرت حالة الدفع. هذه هي الطريقة الموصى بها للحصول على إشعار بالمدفوعات الناجحة.

تنسيق الطلب

  • الطريقة: POST
  • Content-Type: application/json
  • التوقيع: حقل sign في محتوى الطلب

المحتوى

محتوى webhook مطابق لاستجابة /v1/payment/info، بالإضافة إلى حقل sign المستخدم للتحقق من التوقيع.

دفعة ناجحة

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",
  "payment_amount": "0.95256917",
  "merchant_amount": "0.949711462490000000",
  "amount_usd": "2.41324380",
  "exchange_rate": "0.01340691",
  "sign": "6f8c15b6e53b506d5bfa38ed3fb3b50697af73434262153c02e412541372f04d"
}

دفعة ملغاة / فاشلة

عندما لا تكون الدفعة في حالة paid نهائية، تكون قيم txid، payment_amount، وmerchant_amount هي null:

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,
  "payment_amount": null,
  "merchant_amount": null,
  "amount_usd": "37.53934800",
  "exchange_rate": "0.01340691",
  "sign": "40ce68ad9691ad54e684329d75ab5adaf5b01409a2d18d3e0110b8c1be605342"
}

مرجع الحقول

الحقلالنوعالوصف
uuidstringمعرّف الدفعة UUID
order_idstringمعرّف الطلب الخاص بك
amountdecimal (8 dp)المبلغ بالعملة الورقية في currency
currencystringالعملة الورقية التي طلبها التاجر
urlstringعنوان URL لصفحة الدفع المستضافة
expires_atstring (ISO 8601)متى تنتهي صلاحية جلسة الدفع
created_atstring (ISO 8601)متى تم إنشاء جلسة الدفع
payer_currencystringالعملة المشفرة التي يدفع بها الدافع
payer_amountdecimal (8 dp)مبلغ العملة المشفرة المتوقع
networkstringشبكة البلوكتشين
addressstringعنوان الإيداع
payment_statusstringإحدى: pending، check، paid، underpaid_check، underpaid، overpaid، cancel، aml_lock (راجع References)
txidstring | nullهاش معاملة البلوكتشين، يكون موجودًا فقط بعد تأكيد الدفع
payment_amountdecimal | nullالمبلغ المدفوع فعليًا، يكون موجودًا فقط بعد الدفع
merchant_amountdecimal (18 dp) | nullالمبلغ المُضاف إلى التاجر بعد الرسوم
amount_usddecimal (8 dp)المبلغ بالدولار الأمريكي وقت الإنشاء
exchange_ratedecimalسعر صرف العملة المشفرة / الورقية المستخدم
signstring (hex)توقيع HMAC-SHA256 للمحتوى

التحقق من التوقيع

للتحقق من توقيع webhook:

  1. استخرج حقل sign من المحتوى
  2. أزل حقل sign من الكائن
  3. رمّز الحقول المتبقية كـ JSON
  4. رمّز JSON بـ Base64
  5. احسب HMAC-SHA256 من سلسلة Base64 باستخدام API_KEY الخاص بك
  6. قارن التوقيع المحسوب بقيمة sign باستخدام مقارنة بزمن ثابت
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);

تحقق دائمًا من التوقيع قبل إيداع أي أموال للمستخدم. webhook غير موقّع أو موقّع بشكل غير صحيح قد يكون طلبًا مزيفًا.

webhooks السحب

عند تغيّر status لعملية سحب، يرسل النظام webhook بطريقة POST إلى عنوان url_callback الذي تم تمريره عند إنشاء السحب. إذا لم يتم توفير url_callback، فلن يتم إرسال أي webhooks لتلك العملية.

يجب التحقق من webhooks السحب باستخدام Payout API key الخاص بك — وليس API key العادي. خوارزمية التوقيع متطابقة مع webhooks المدفوعات (إزالة sign، ترميز JSON، base64، HMAC-SHA256)، يختلف فقط المفتاح.

المحتوى

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",
  "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"
}

مرجع الحقول

الحقلالنوعالوصف
uuidstringمعرّف السحب UUID
order_idstringمعرّف idempotency / المرجع الخاص بك، إذا قمت بتوفيره
statusstringpending، completed، failed، cancelled (راجع References)
currencystringعملة السحب
networkstringشبكة البلوكتشين
amountdecimalمبلغ السحب (بـ currency)
merchant_amountdecimalالمبلغ المخصوم من رصيد التاجر
network_amountdecimalالمبلغ المُرسل فعليًا على البلوكتشين
amount_usddecimalالقيمة بالدولار الأمريكي وقت السحب
to_addressstringعنوان البلوكتشين للمستلم
memostring | nullmemo / تاج الوجهة، إن استُخدم
txidstring | nullهاش معاملة البلوكتشين، يُحدد عند completed
block_numberinteger | nullارتفاع البلوك للمعاملة على البلوكتشين
error_typestring | nullالسبب عند status = failed (مثل aml_risk، راجع References)
created_atstring (ISO 8601)متى تم إنشاء عملية السحب
updated_atstring (ISO 8601)متى تغيرت الحالة آخر مرة
from_currencystringالرصيد المصدري الذي خُصم منه السحب عند استخدام التحويل التلقائي (مثلًا USDT لسحب بـ BTC)
debited_amountdecimalالمبلغ المخصوم من رصيد from_currency
debited_currencystringعملة الخصم
signstring (hex)توقيع HMAC-SHA256 للمحتوى، موقّع باستخدام Payout API key

أفضل الممارسات

  • Idempotency — تحقق دائمًا مما إذا كانت الدفعة قد عولجت بالفعل (بواسطة order_id أو uuid). قد تصل webhooks عدة مرات.
  • استجابة سريعة — أعد HTTP 200 بأسرع وقت ممكن. أنقل العمل الثقيل إلى طابور خلفي.
  • إعادة المحاولة — إذا لم يتلقَّ النظام HTTP 200، تتم إعادة إرسال webhook بعد دقيقتين. الحد الأقصى 5 محاولات.
  • معالجة غير متزامنة — تعامل مع أحداث webhook بشكل غير متزامن لتجنب حجب الاستجابة.
  • الأمان — تحقق دائمًا من توقيع sign قبل الوثوق بالمحتوى.

قد تصل webhooks خارج الترتيب. لا تفترض أن أول webhook تستلمه هو الحالة النهائية — أعد الجلب دائمًا عبر /v1/payment/info (أو /v1/payout/status/{uuid}) إذا كنت بحاجة إلى يقين.