أحداث الـ webhook
ترسل OrcaRail أحداث webhook لإعلامك بالتغييرات على الـ Payment Intents والموارد الأخرى.
بنية الحدث
تتبع كل أحداث الـ webhook هذه البنية:
{
"type": "payment_intent.completed",
"livemode": true,
"data": {
"object": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"amount": "100.00",
"currency": "usd",
"status": "completed",
"paymentMethodTypes": ["crypto"],
"metadata": {
"order_id": "12345"
},
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
}
}
}
تكون قيمة livemode هي false للأحداث الصادرة من مؤسسة sandbox (شبكات تجريبية، دون أموال حقيقية). لا تنفّذ أبدًا طلبات حقيقية من أحداث livemode: false. وتحمل مدفوعات الـ sandbox المحاكاة أيضًا latest_transaction.simulated: true.
أحداث Payment Intent
payment_intent.completed
يُرسل عندما ينجح Payment Intent وتُعالج الدفعة. (قد ترى payment_intent.succeeded في أمثلة قديمة؛ تعامل معه كاسم بديل لـ payment_intent.completed.)
نوع الحدث: payment_intent.completed
الحمولة:
{
"type": "payment_intent.completed",
"data": {
"object": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"amount": "100.00",
"currency": "usd",
"status": "completed",
"paymentMethodTypes": ["crypto"],
"metadata": {
"order_id": "12345"
},
"latestTransaction": {
"id": "txn_1234567890",
"status": "completed",
"hash": "0x1234567890abcdef...",
"amount": "100.00",
"currency": "usd"
},
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
}
}
}
متى تستخدمه:
- تنفيذ الطلبات
- إرسال رسائل تأكيد بالبريد
- تحديث قاعدة بياناتك
- تشغيل سير عمل التسليم
مثال على معالج:
async function handlePaymentIntentSucceeded(event) {
const paymentIntent = event.data.object
const orderId = paymentIntent.metadata.order_id
// Fulfill the order
await fulfillOrder(orderId)
// Send confirmation email
await sendConfirmationEmail(paymentIntent)
// Update database
await updateOrderStatus(orderId, 'paid')
}
payment_intent.processing
يُرسل عندما يكون Payment Intent قيد المعالجة على البلوكتشين.
نوع الحدث: payment_intent.processing
الحمولة:
{
"type": "payment_intent.processing",
"data": {
"object": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"amount": "100.00",
"currency": "usd",
"status": "processing",
"paymentMethodTypes": ["crypto"],
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
}
}
}
متى تستخدمه:
- عرض حالة المعالجة للعملاء
- تحديث الواجهة للإشارة إلى أن الدفع جارٍ
- تسجيل أحداث المعالجة
مثال على معالج:
async function handlePaymentIntentProcessing(event) {
const paymentIntent = event.data.object
const orderId = paymentIntent.metadata.order_id
// Update order status to processing
await updateOrderStatus(orderId, 'processing')
// Notify customer
await notifyCustomer(orderId, 'Your payment is being processed')
}
payment_intent.canceled
يُرسل عند إلغاء Payment Intent.
نوع الحدث: payment_intent.canceled
الحمولة:
{
"type": "payment_intent.canceled",
"data": {
"object": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"amount": "100.00",
"currency": "usd",
"status": "canceled",
"paymentMethodTypes": ["crypto"],
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
}
}
}
متى تستخدمه:
- تحرير المخزون المحجوز
- إلغاء الطلبات المعلّقة
- إشعار العملاء
- تنظيف الموارد
مثال على معالج:
async function handlePaymentIntentCanceled(event) {
const paymentIntent = event.data.object
const orderId = paymentIntent.metadata.order_id
// Release inventory
await releaseInventory(orderId)
// Cancel order
await cancelOrder(orderId)
// Notify customer
await notifyCustomer(orderId, 'Your payment was canceled')
}
payment_intent.requires_payment_method
يُرسل عندما يحتاج Payment Intent إلى إرفاق طريقة دفع.
نوع الحدث: payment_intent.requires_payment_method
الحمولة:
{
"type": "payment_intent.requires_payment_method",
"data": {
"object": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"amount": "100.00",
"currency": "usd",
"status": "requires_payment_method",
"paymentMethodTypes": ["crypto"],
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
}
}
}
متى تستخدمه:
- تتبّع جلسات الدفع المتروكة
- إرسال رسائل تذكير
- تحديث التحليلات
مثال على معالج:
async function handlePaymentIntentRequiresPaymentMethod(event) {
const paymentIntent = event.data.object
// Track abandoned pay
await trackAbandonedPay(paymentIntent.id)
// Send reminder email after delay
setTimeout(
() => {
sendReminderEmail(paymentIntent)
},
24 * 60 * 60 * 1000
) // 24 hours
}
معالجة الأحداث
موجّه الأحداث
أنشئ موجّهًا للتعامل مع أنواع الأحداث المختلفة:
const eventHandlers = {
'payment_intent.completed': handlePaymentIntentSucceeded,
'payment_intent.succeeded': handlePaymentIntentSucceeded, // alias
'payment_intent.processing': handlePaymentIntentProcessing,
'payment_intent.canceled': handlePaymentIntentCanceled,
'payment_intent.requires_payment_method':
handlePaymentIntentRequiresPaymentMethod,
}
app.post('/webhooks/orcarail', express.json(), async (req, res) => {
const event = req.body
// Verify signature
verifyWebhookSignature(req)
// Get handler for event type
const handler = eventHandlers[event.type]
if (handler) {
try {
await handler(event)
} catch (error) {
console.error(`Error handling ${event.type}:`, error)
// Still return 200 to prevent retries if you handle errors internally
}
} else {
console.log(`Unhandled event type: ${event.type}`)
}
res.status(200).json({ received: true })
})
عدم التكرار (Idempotency)
تأكد من أن معالجاتك idempotent:
const processedEvents = new Map()
async function handlePaymentIntentSucceeded(event) {
const eventId = `${event.type}_${event.data.object.id}`
// Check if already processed
if (processedEvents.has(eventId)) {
console.log(`Event ${eventId} already processed`)
return
}
// Process event
await fulfillOrder(event.data.object.metadata.order_id)
// Mark as processed (with timestamp for cleanup)
processedEvents.set(eventId, Date.now())
}
اختبار الأحداث
باستخدام نقطة نهاية الاختبار
يمكنك اختبار نقطة نهاية الـ webhook بإرسال أحداث تجريبية:
curl -X POST https://your-webhook-url.com/webhooks/orcarail \
-H "Content-Type: application/json" \
-H "x-webhook-signature: test-signature" \
-d '{
"type": "payment_intent.completed",
"data": {
"object": {
"id": "550e8400-e29b-41d4-a716-446655440001",
"amount": "100.00",
"currency": "usd",
"status": "completed",
"paymentMethodTypes": ["crypto"],
"metadata": {
"order_id": "test_order_123"
}
}
}
}'
الخطوات التالية
- توقيعات الـ webhooks — تعرّف على كيفية التحقق من أصالة الـ webhook
- نظرة عامة على الـ webhooks — راجع أفضل ممارسات الـ webhooks