تعتبر أحداث Webhooks لعمليات الدفع (والتي كانت تعرف سابقًا باسم التحديثات الفورية) طريقة أساسية يتم من خلالها إبلاغك بالتغييرات في الطلبات التي تتم عبر عمليات الدفع من فيسبوك في تطبيقك. |
تُعد أحداث Webhooks نظامًا يستند إلى الاشتراك متوفر بين فيسبوك والخادم لديك. حيث يشترك تطبيقك لتلقي التحديثات من فيسبوك عبر نقطة نهاية HTTPS محددة. وعند تحديث طلب تم إجراؤه داخل تطبيقك، سنصدر طلب POST
HTTPS إلى نقطة النهاية هذه، لإخطار الخادم بالتغيير.
تتوفر 3 سيناريوهات أساسية يتم فيها إرسال التحديثات إلى خادم المطوّر:
للاشتراك في أحداث Webhooks لعمليات الدفع، يجب أولاً إنشاء عنوان URL لنقطة نهاية عامة يتلقى كل من طلب GET
HTTPS للتحقق من الاشتراك وPOST
لطلبات تغيير البيانات. تم وصف بنية هذين النوعين من الطلبات أدناه. بعد ذلك، يمكنك إعداد الاشتراك في الكائن payment
لدى تطبيقك. توجد طريقتان للقيام بذلك:
في كلتا الحالتين، ستتلقى نقطة النهاية البيانات ذاتها بالطريقة ذاتها. راجع خادم الاستدعاء لمزيد من المعلومات حول ما سيتلقاه الخادم.
تُعد أسهل طريقة لإعداد تطبيقك لتلقي تحديثات Webhooks هي استخدام لوحة عمليات الدفع في لوحة معلومات التطبيق. ابحث عن تطبيقك في لوحة المعلومات ثم انقر على علامة التبويب Payments
. سيكون قسم أحداث Webhooks أسفل قسم إعدادات الشركة مباشرةً.
ستعرض هذه الشاشة بعد ذلك حالة اشتراك التطبيق، سواء تمت إضافته من خلال هذه اللوحة أو API. ومن هنا، يمكن تغيير عنوان URL الاستدعاء واختباره.
في الحقل "استدعاء"، يجب توفير نقطة نهاية خادم صالحة وقابلة للوصول من جانب العامة. هذا هو العنوان الذي سنستخدمه للتحقق من الاشتراك بالإضافة إلى إرسال التحديثات، ويجب أن تكون الاستجابة على النحو الموضح في خادم الاستدعاء.
وأخيرًا، قم بتوفير "رمز تحقق". سيتم إرسال هذا الرمز فقط أثناء مرحلة التسجيل للتحقق من أن الاشتراك قد تم إنشاؤه من موقع آمن. لن يتم إرسال هذا الرمز في تحديثات Webhook المعتادة.
يجب اختبار إعدادات الاستدعاء قبل حفظ الاشتراك. سيصدر ذلك طلب GET للتحقق إلى نقطة النهاية، يحتوي على المعلمات hub.mode
وhub.challenge
وhub.verify_token
، وسيضمن معالجتها بشكل صحيح. على سبيل المثال، يجب أن تتأكد من أن نقطة النهاية تُرجع hub.challenge
مرة أخرى إلى فيسبوك:
بمجرد إدخال تفاصيل الاشتراك، احرص على النقر على الزر "حفظ التغييرات" أسفل الصفحة. يُعد تعديل الاشتراك أمرًا بسيطًا يتمثل في تغيير محتويات الحقول وإعادة الاختبار ثم حفظ النموذج مرة أخرى.
من الممكن إعداد الاشتراكات وإدراجها بشكل برمجي من خلال واجهة Graph API. ستحتاج إلى access token
للتطبيق، والذي يتوفر من خلال أداة رمز الوصول أو من خلال استخدام نقطة النهاية /oauth
لواجهة Graph API
تتوفر API الاشتراك في نقطة النهاية https://graph.facebook.com/[APP_ID]/subscriptions
يمكنك إجراء 3 مهمات من خلالها:
POST
HTTPS)GET
HTTPS)لإعداد اشتراك، أرسل طلب POST
يتضمن المعلمات التالية. لاحظ أن هذه المعلمات تتوافق مع الحقول الموجودة في النموذج الموضح أعلاه:
object
- كما هو موضح بالأعلى، تمثل نوع الكائن الذي تريد تلقي تحديثات حوله. حدّد payments
.fields
- تمثل قائمة مفصولة بفاصلة تتضمن خصائص نوع الكائن الذي تود الحصول على تحديثات حول التغييرات التي تتم به. حدّد "الإجراءات" و"النزاعات".callback_url
- تمثل نقطة نهاية خادم صالحة وقابلة للوصول من خلال العامة.verify_token
- تمثل سلسلة عشوائية، يتم إرسالها إلى نقطة النهاية عند التحقق من الاشتراك.عندما نتلقى هذا الطلب، كما هو الحال مع تكوين النموذج أعلاه، سنرسل طلب GET
إلى الاستدعاء للتأكد من صلاحيته وجاهزيته لتلقي التحديثات. على وجه التحديد، يجب أن تتأكد من أن نقطة النهاية تُرجع hub.challenge
مرة أخرى إلى فيسبوك.
لاحظ أنه نظرًا لأن التطبيق يمكن أن يكون له اشتراك واحد فقط لكل نوع كائن، في حالة وجود اشتراك بالفعل لنوع الكائن هذا، فإن البيانات المنشورة حديثًا تحل محل أي بيانات الحالية.
يؤدي إرسال طلب GET
HTTP إلى API الاشتراكات إلى إرجاع محتوى مشفّر بلغة JSON يدرج الاشتراكات. على سبيل المثال:
[ { "object": "payments", "callback_url": "https://www.friendsmash.com/rtu.php", "fields": ["actions", "disputes"], "active": true } ]
يمكنك استخدام مستكشف Graph لاختبار API هذه مباشرةً، مع الحرص على استخدام رمز وصول التطبيق.
يجب أن يتعامل خادم الاستدعاء مع نوعي طلبات. تأكد من وجوده على عنوان URL عام حتى نتمكن من إجراء هذه الطلبات بنجاح.
أولاً، ستقوم خوادم فيسبوك بإرسال طلب GET
HTTPS إلى عنوان URL الاستدعاء عند محاولة إضافة اشتراك أو تعديله. سيتم إلحاق سلسلة استعلام بعنوان URL مع تضمين المعلمات التالية:
المعلمة | الوصف |
---|---|
| يتم إدخال السلسلة " |
| سلسلة عشوائية |
| قيمة |
يجب على نقطة النهاية التحقق من hub.verify_token
أولاً. يضمن ذلك أن يعرف الخادم أن الطلب يتم إجراؤه بواسطة فيسبوك ويربطه بالاشتراك الذي قمت بتكوينه للتو.
حينها يجب أن تُرجع نقطة النهاية القيمة hub.challenge
فقط مرة أخرى، الأمر الذي يؤكد لفيسبوك أن هذا الخادم تم تكوينه لقبول الاستدعاءات، ويمنع الثغرات التي تسهل شن هجمات حجب الخدمة (DDoS).
ملاحظة لمطوّري PHP: في PHP، يتم تحويل النقاط والمسافات في أسماء معلمات الاستعلام إلى شرطات سفلية تلقائيًا. ولذلك، عليك الوصول إلى هذه المعلمات باستخدام $_GET['hub_mode']
و$_GET['hub_challenge']
و$_GET['hub_verify_token']
إذا كنت تكتب نقطة نهاية الاستدعاء بلغة PHP. راجع هذه الملاحظة في دليل لغة PHP لمزيد من المعلومات.
بعد نجاح الاشتراك، سنشرع في إرسال طلب POST
HTTPS إلى نقطة نهاية الخادم في كل مرة تحدث فيها تغييرات (في الحقول أو جهات التواصل المختارة). يجب الاستجابة لهذا الطلب برمز HTTP 200
.
ملاحظة - نعتبر أي استجابة HTTP بخلاف 200
خطأً. وفي هذه الحالات، سنواصل إعادة محاولة إرسال تحديث webhooks. إذا لم تستجب على النحو المطلوب، فقد تتلقى التحديث ذاته عدة مرات.
سيتوفر لدى الطلب نوع محتوى application/json
وسيتألف النص الأساسي من سلسلة مشفّرة بلغة JSON تحتوي على تغيير واحد أو أكثر.
ملاحظة لمطوّري PHP: في PHP، للحصول على البيانات المشفرة، ستستخدم الرمز التالي:
$data = file_get_contents("php://input"); $json = json_decode($data);`
لاحظ أنه لا يتم إرسال المعلمات hub.mode
وhub.challenge
وhub.verify_token
مرة أخرى بمجرد تأكيد الاشتراك.
فيما يلي مثال أساسي لاستدعاء تم إنشاؤه لاشتراك كائن payments
:
{ "object": "payments", "entry": [ { "id": "296989303750203", "time": 1347996346, "changed_fields": [ "actions" ] } ] }
من المهم ملاحظة أن تحديثات Webhook تخبرك فقط أنه تم تغيير عملية دفع معينة، محددة بواسطة الحقل id
. بعد تلقي التحديث، يُطلب منك بعد ذلك الاستعلام عن واجهة Graph API للحصول على تفاصيل المعاملة، لمعالجة التغيير بشكل مناسب.
ملاحظة - على الرغم من إمكانية تجميع تحديثات Webhooks لأنواع الكائنات الأخرى، فإنه لا يمكن مطلقًا تجميع تحديثات الدفع.
نضمن لك تلقي تحديث جديد في كل مرة يتم فيها تحديث معاملة، إما عن طريق إجراء المستخدم أو إجراء المطوّر.
إذا فشل تحديث الخادم، فسنعيد المحاولة مرة أخرى على الفور ثم نكرر المحاولة عدة مرات، بمعدل تكرار متناقص، على مدار الـ 24 ساعة التالية.
مع كل طلب، نرسل عنوان HTTP X-Hub-Signature-256
يحتوي على توقيع SHA256 لحمولة بيانات الطلب، باستخدام المفتاح السري للتطبيق كمفتاح، ومسبوقًا ببادئة sha256=
. بإمكان نقطة نهاية الاستدعاء التحقق من هذا التوقيع للتحقق من سلامة حمولة البيانات وأصلها.
بعد تلقي الخادم للتحديث، يجب الاستعلام عن واجهة Graph API باستخدام الحقل id
للحصول على تفاصيل حول حالة المعاملة الجديدة. عليك حينها اتخاذ إجراء استنادًا إلى الحالة.
تسرد الأقسام التالية كل تغييرات الحالة المحتملة التي تؤدي إلى إرسال تحديث. وتنقسم هذه التغييرات عمومًا إلى:
يحتوي كل كائن payment
على مصفوفة تُسمى actions
، تتضمن مجموعة تغييرات الحالة التي مرت بها المعاملة. ويحتوي كل إدخال في المصفوفة actions
على خاصية تُسمى type
والتي تصف نوع الإجراء الذي تم. يمكن أن يحتوي type
على القيم التالية: charge
وrefund
وchargeback
وchargeback_reversal
وdecline
والتي يتم شرحه بالكامل هنا.
عينة من استجابة واجهة Graph API لكائن عملية دفع مع الإجراءات المرتبطة فيما يلي:
{ "id": "3603105474213890", "user": { "name": "Marco Alvarez", "id": "500535225" }, "application": { "name": "Friend Smash", "namespace": "friendsmashsample", "id": "241431489326925" }, "actions": [ { "type": "charge", "status": "completed", "currency": "USD", "amount": "0.99", "time_created": "2013-03-22T21:18:54+0000", "time_updated": "2013-03-22T21:18:55+0000" }, { "type": "refund", "status": "completed", "currency": "USD", "amount": "0.99", "time_created": "2013-03-23T21:18:54+0000", "time_updated": "2013-03-23T21:18:55+0000" } ], "refundable_amount": { "currency": "USD", "amount": "0.00" }, "items": [ { "type": "IN_APP_PURCHASE", "product": "https://www.friendsmash.com/og/friend_smash_bomb.html", "quantity": 1 } ], "country": "US", "created_time": "2013-03-22T21:18:54+0000", "payout_foreign_exchange_rate": 1,}`
بمجرد الاشتراك في حقل الإجراءات عند التسجيل في أحداث Webhooks، سنصدر تحديثًا عندما تتغير المصفوفة على النحو التالي:
في البداية، تحتوي كل الطلبات على إدخال تحصيل رسوم بالحالة "status": "initiated"
. تشير عملية الدفع المبدئية إلى أن عملية الدفع بدأت فقط ولم تكتمل بعد. وبالتالي لن نرسل تحديثات حول عمليات الدفع غير المكتملة.
عند إكمال عملية دفع بنجاح، سيتم تغيير "status": "initiated"
إلى "status": "completed"
وسنرسل تحديثًا. بمجرد رؤية هذا التحديث يجب الرجوع إلى سجلات عملية الدفع للتحقق مما إذا كان هذا التحديث لمعاملة جديدة أم معاملة موجودة ثم الاستجابة على النحو التالي:
initiated
، فيمكنك متابعة تنفيذ الطلب، وإرسال العنصر أو العملة الافتراضية المرتبطة به إلى المستهلك. ويمكن بعد ذلك تحديد عملية الدفع هذه بأمان على أنها مكتملة.ستتلقى تحديثات أيضًا حول عمليات الدفع المحددة بالحالة "status": "failed"
. يجب ألا يتم إتمام تلك العمليات.
عند إصدار طلب استرداد أموال عبر واجهة Graph API، ستتلقى تحديثًا. كما هو الحال مع "type": "charge"
، يمكن أن يحتوي طلب استرداد الأموال أيضًا على حالة متغيرة يجب أن تكون على دراية بها. والأهم من ذلك، أنه من الممكن أن تفشل عملية استرداد الأموال، عادةً بسبب خطأ في المعالجة أو الاتصال - وفي هذه الحالة يجب إعادة محاولة إرسال طلب استرداد الأموال.
كما هو الحال مع عملية استرداد الأموال، سيتم إبلاغك أيضًا في حالة إصدار عملية رد المبالغ المدفوعة وعملية إبطال رد المبالغ المدفوعة وعملية الرفض. وستتم إضافة كائن عملية رد المبالغ المدفوعة أو عملية إبطال رد المبالغ المدفوعة أو عملية الرفض إلى مصفوفة الإجراءات في بيانات واجهة Graph API التي يتم إرجاعها حول عملية الدفع.
سنخطرك عن طريق إرسال تحديث عند بدء النزاع. في هذه الحالة، ستظهر مصفوفة "disputes"
جديدة كجزء من الكائن payment
. وستحتوي المصفوفة على وقت بدء النزاع، والسبب الذي دفع المستهلك لبدء الاستجابة وكذلك عنوان البريد الإلكتروني للمستهلك، والذي يمكنك استخدامه للاتصال به مباشرةً لحل النزاع.
فيما يلي عينة من استجابة كاملة من واجهة Graph API لمعاملة متنازع عليها:
{ "id": "990361254213890", "user": { "name": "Marco Alvarez", "id": "500535225" }, "application": { "name": "Friend Smash", "namespace": "friendsmashsample", "id": "241431489326925" }, "actions": [ { "type": "charge", "status": "completed", "currency": "USD", "amount": "0.99", "time_created": "2013-03-22T21:18:54+0000", "time_updated": "2013-03-22T21:18:55+0000" } ], "refundable_amount": { "currency": "USD", "amount": "0.99" }, "items": [ { "type": "IN_APP_PURCHASE", "product": "https://www.friendsmash.com/og/friend_smash_bomb.html", "quantity": 1 } ], "country": "US", "created_time": "2013-03-22T21:18:54+0000", "payout_foreign_exchange_rate": 1, "disputes": [ { "user_comment": "I didn't receive my item! I want a refund, please!", "time_created": "2013-03-24T18:21:02+0000", "user_email": "email\u0040domain.com", "status": "resolved", "reason": "refunded_in_cash" } ] }
لمزيد من المعلومات حول كيفية الاستجابة للنزاعات وإصدار عمليات استرداد الأموال، يُرجى مراجعة شروحات عمليات الدفع: كيفية معالجة النزاعات وعمليات استرداد الأموال.