Webhooks для платежей (ранее уведомления в режиме реального времени) — это очень полезный метод, который позволяет информировать вас об изменениях в заказах, сделанных через платежи на Facebook в вашем приложении. |
Webhooks — это система обмена информацией между Facebook и вашим сервером. Она работает по подписке. Ваше приложение подписывается на получение обновлений от Facebook через определенную конечную точку HTTPS. Когда в заказе, сделанном в вашем приложении, происходят изменения, мы отправляем запрос HTTPS POST
к этой конечной точке, чтобы уведомить сервер об изменениях.
Обновления отправляются на сервер в трех основных ситуациях:
Чтобы подписаться на Webhooks для платежей, создайте общедоступный URL конечной точки, получающей запросы HTTPS GET
(для подтверждения подписки) и POST
(для запросов на изменение данных). Структура запросов обоих типов показана ниже. Затем настройте подписку для объекта payment
в приложении. Это можно сделать двумя способами:
Конечная точка в любом случае будет получать одни и те же данные одним и тем же способом. Подробнее о том, какую информацию будет получать сервер, см. в разделе о сервере обратных вызовов.
Проще всего настроить получение обновлений Webhooks для приложения через панель "Платежи" на Панели приложений. Найдите приложение на панели и откройте вкладку Payments
(Платежи). Раздел Webhooks находится сразу под разделом "Настройки" компании.
На экране появится информация о статусе подписки приложения (вне зависимости от того, было ли приложение подписано через Панель приложений или через API). Здесь также можно изменить URL обратного вызова подписки и протестировать его.
В поле "Обратный вызов" нужно указать действующую и общедоступную конечную точку сервера. Мы будем использовать этот адрес, чтобы подтвердить подписку и отправлять обновления. Он должен отвечать так, как описано в разделе о сервере обратных вызовов.
Затем предоставьте маркер подтверждения. Он будет отправляться только при регистрации, чтобы подтвердить, что подписка отправляется из защищенного источника. Для обычных обновлений Webhook этот маркер не отправляется.
Перед сохранением подписки проверьте настройки обратных вызовов. При этом к конечной точке будет отправлен запрос подтверждения GET с параметрами hub.mode
, hub.challenge
и hub.verify_token
. Это позволит убедиться, что вы правильно обрабатываете эти параметры. Например, конечная точка должна возвращать полученное от Facebook значение hub.challenge
:
Указав данные о подписке, нажмите "Сохранить изменения" внизу страницы. Чтобы отредактировать подписку, измените содержимое полей, повторите проверку и сохраните форму.
Настроить подписку также можно программным способом через API Graph. Вам потребуется маркер доступа приложения access token
, который можно получить с помощью инструмента маркеров доступа или конечной точки /oauth
API Graph.
API подписки доступен на конечной точке https://graph.facebook.com/[APP_ID]/subscriptions
.
С его помощью можно выполнять три действия:
POST
);GET
).Чтобы настроить подписку, отправьте запрос POST
с перечисленными далее параметрами. Обратите внимание: они соответствуют полям в форме, показанной выше.
object
— как и выше, это тип объекта, о котором вы хотите получать уведомления. Задайте значение payments
.fields
— список разделенных запятыми свойств типа объекта, об изменениях в котором вы хотите получать уведомления. Задайте значения actions (действия) и disputes (споры).callback_url
— действующая общедоступная конечная точка сервера.verify_token
— произвольная строка. Отправляется на конечную точку при подтверждении подписки.Получив этот запрос (как и в случае с формой выше), мы отправляем запрос GET
к вашему обратному вызову, чтобы убедиться, что он действителен и может получать обновления. В частности, конечная точка должна возвращать полученное от Facebook значение hub.challenge
.
Обратите внимание: у приложения может быть только одна подписка на каждый тип объекта. Если подписка на определенный тип объекта уже существует, новые данные заменят существующие.
При отправке запроса HTTP GET
к API подписки возвращается список подписок в кодировке JSON. Пример:
[ { "object": "payments", "callback_url": "https://www.friendsmash.com/rtu.php", "fields": ["actions", "disputes"], "active": true } ]
Чтобы непосредственно поэкспериментировать с API, воспользуйтесь Graph API Explorer (не забудьте использовать маркер доступа своего приложения).
Ваш сервер обратных вызовов должен обрабатывать два вида запросов. Чтобы мы могли отправлять эти запросы, сервер должен находиться на общедоступном URL.
Когда вы добавляете или изменяете подписку, сервер Facebook отправляет один запрос HTTPS GET
к вашему URL обратного вызова. К этому URL обратного вызова добавляется строка запроса со следующими параметрами:
Параметр | Описание |
---|---|
| В этом параметре передается строка |
| Случайная строка. |
| Значение |
Конечная точка должна в первую очередь подтвердить hub.verify_token
. Это нужно, чтобы сообщить серверу, что запрос отправлен Facebook и связан с только что настроенной подпиской.
Затем конечная точка должна отправить только значение hub.challenge
: таким образом Facebook узнает, что сервер может принимать обратные вызовы и опасность атак типа "отказ в обслуживании" (DDoS) устраняется.
Примечание для разработчиков на PHP. На языке PHP точки и пробелы в именах параметров запроса автоматически преобразуются в знаки подчеркивания. Если ваша конечная точка обратных вызовов написана на этом языке, обращайтесь к параметрам как $_GET['hub_mode']
, $_GET['hub_challenge']
и $_GET['hub_verify_token']
. Подробнее см. в этом примечании в руководстве по языку PHP.
После успешной подписки мы отправляем к конечной точке вашего сервера запрос HTTPS POST
каждый раз, когда происходят какие-либо изменения (в выбранных полях или подключениях). На этот запрос нужно ответить кодом HTTP 200
.
Примечание. Все ответы HTTP, кроме 200
, считаются ошибкой. В таком случае мы будем пытаться отправить обновление повторно. Если не предоставить правильный ответ, вы можете получить одно и то же обновление несколько раз.
Запрос будет иметь тип контента 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
, внесены изменения. Получив обновление, отправьте запрос к API Graph, чтобы получить информацию о транзакции и правильно обработать ее.
Примечание. Вызовы Webhook для объектов других типов можно объединить в пакеты, однако обновления о платежах никогда не объединяются.
Каждый раз, когда пользователь или администратор обновляет информацию о транзакции, вы будете получать новое уведомление.
В случае сбоя отправки обновления на сервер мы сразу же повторим попытку. Затем в течение следующих 24 часов мы отправим обновления ещё несколько раз, постепенно увеличивая интервалы времени между попытками.
В каждом запросе мы отправляем заголовок HTTP X-Hub-Signature-256
, содержащий подпись полезной нагрузки запроса, хэшированную с применением алгоритма SHA256 (в качестве ключа используется секрет приложения). Подпись содержит префикс sha256=
. Конечная точка обратного вызова может использовать эту подпись, чтобы подтвердить целостность полезных данных и их источник.
Получив обновление, отправьте запрос к API Graph и укажите поле id
, чтобы получить информацию о новом статусе транзакции. Затем выполните действия в зависимости от статуса.
В следующих разделах перечислены все возможные изменения статуса, из-за которых отправляются обновления. В целом они делятся на:
Каждый объект payment
содержит массив actions
. В нем указана история изменений состояния транзакции. У каждого элемента массива actions
есть свойство type
, которое описывает тип произошедшего действия. Свойство type
может иметь одно из следующих значений: charge
, refund
, chargeback
, chargeback_reversal
и decline
. Подробное описание этих значений см. в этом разделе.
Пример ответа API Graph на объект платежа со связанными действиями:
{ "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,}`
Ниже перечислены изменения массива, при которых мы будем отправлять уведомления, в зависимости от поля действий, на которое вы подписались при регистрации Webhook.
Изначально все заказы содержат элемент списания со статусом "status": "initiated"
. Если платеж запущен (имеет статус "initiated"), это означает, что он ещё не выполнен. Мы не будем отправлять обновления для платежей в этом состоянии.
Когда платеж будет выполнен, "status": "initiated"
изменится на "status": "completed"
и мы отправим обновление. Получив обновление, проверьте данные о платежах и определите, новая это транзакция или существующая. После этого выполните соответствующие действия:
initiated
, выполните заказ, присвоив потребителю соответствующий виртуальный товар или валюту. Затем платеж можно пометить как выполненный.Вы также будете получать уведомления о платежах со статусом "status": "failed"
. Их не нужно выполнять.
Каждый раз при создании возврата с помощью API Graph вы будете получать обновление. Как и в случае типа "type": "charge"
, у возврата могут быть разные статусы. Важно: возврат может завершиться ошибкой (обычно из-за проблем с обработкой или подключением). В этом случае вам следует отправить возврат повторно.
Если произошло оспаривание транзакции, отмена оспаривания или отклонение транзакции, вы получите уведомление, как и в случае с возвратом. При этом в массив действий в ответе API Graph для платежа будет добавлен соответствующий объект.
При создании спора мы также отправим обновление. В этом случае в объекте payment
будет новый массив "disputes"
. Он будет содержать время создания спора, причину, по которой клиент создал спор, и электронный адрес клиента, по которому вы можете связаться с ним и разрешить спор.
Пример полного ответа API Graph на оспоренную транзакцию:
{ "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" } ] }
Подробнее о том, как отвечать на споры и отправлять возвраты, см. в руководстве по платежам: разрешение споров и возврат средств.