Webhooks

Вебхуки позволяют мгновенно оповестить внешний сервис об изменениях в заказах.

Настраивается в разделе настроек https://qtickets.ru/backend/idesigning/qtickets/organizers/myaccount?tab=webhooks

При добавлении вебхуков указывается:

  • Тип события (Новый заказ, Заказ изменен, Заказ оплачен, Заказ отменен, Заказ возвращен, Гость пришёл на событие)
  • URL (куда будет отправлен запрос)
  • Секрет (если необходимо проверять цифровую подпись)

Данные передаются в формате JSON (Content-type: application/json). В заголовках передаются:

  • X-Signature — сигнатура, для проверки цифровой подписи
  • X-Event-Type — тип события (created, updated, payed, deleted, refunded, checked)
  • X-Model-Name — всегда Order
  • User-Agent — Qtickets-Webhooks/2.0

Пример данных:

{
   "id":4360,
   "uniqid":"z7rkjcV2BV",
   "payed":true,
   "payed_at":"2019-07-30T12:50:52+03:00",
   "created_at":"2019-07-30T12:50:36+03:00",
   "updated_at":"2019-07-30T12:50:52+03:00",
   "deleted_at":null,
   "client_id":235,
   "client":{
      "id":235,
      "email":"username@gmail.com",
      "details":{
         "id":167,
         "name":"Иван",
         "middlename":null,
         "surname":"Петров",
         "phone":"+79100000000",
         "vk_id":"",
         "facebook_id":""
      }
   },
   "site_id":16,
   "site":{
      "id":16,
      "host":"qtickets.ru"
   },
   "payment_id":36,
   "payment_type_id":"bankcard",
   "payment_url":"https://qtickets.test/pay/z7rkjcV2BV",
   "cancel_url":"https://qtickets.test/cancel-order/z7rkjcV2BV/a800d6bfc609003205752c42844f541c",
   "basket_user_id":2111,
   "backend_user_id":null,
   "access_code_id":null,
   "discount_id":null,
   "promo_code_id":null,
   "reserved":0,
   "reserved_to":"2019-07-31T12:50:36+03:00",
   "reserve_extended":0,
   "event_id":33,
   "price":800,
   "original_price":800,
   "currency_id":"RUB",
   "utm":[

   ],
   "custom":{
      "var1":"val1",
      "var2":"val2"
   },
   "fields":{
      "organization_name":"ИП Петров"
   },
   "baskets":[
      {
         "id":63993,
         "barcode":"877076325904",
         "show_id":41,
         "seat_id":"CENTER_PARTERRE-21;12",
         "original_price":150,
         "discount_value":null,
         "price":150,
         "quantity":1,
         "client_email":"username@gmail.com",
         "client_phone":"+79100000000",
         "client_name":"Иван",
         "client_surname":"Петров",
         "organization_name":null,
         "legal_name":null,
         "work_position":null,
         "inn":null,
         "kpp":null,
         "comment":null,
         "related_baskets":[

         ],
         "created_at":"2019-07-30T12:49:47+03:00",
         "updated_at":"2019-07-30T12:50:52+03:00",
         "deleted_at":null
      },
      {
         "id":63994,
         "barcode":"877344688530",
         "show_id":41,
         "seat_id":"CENTER_PARTERRE-21;11",
         "original_price":150,
         "discount_value":null,
         "price":150,
         "quantity":1,
         "client_email":"username@gmail.com",
         "client_phone":"+79100000000",
         "client_name":"Иван",
         "client_surname":"Петров",
         "organization_name":null,
         "legal_name":null,
         "work_position":null,
         "inn":null,
         "kpp":null,
         "comment":null,
         "related_baskets":[

         ],
         "created_at":"2019-07-30T12:49:50+03:00",
         "updated_at":"2019-07-30T12:50:52+03:00",
         "deleted_at":null
      },
      {
         "id":63995,
         "barcode":"875606411179",
         "show_id":41,
         "seat_id":"CENTER_BALCONY-1;14",
         "original_price":500,
         "discount_value":null,
         "price":500,
         "quantity":1,
         "client_email":"username@gmail.com",
         "client_phone":"+79100000000",
         "client_name":"Иван",
         "client_surname":"Петров",
         "organization_name":null,
         "legal_name":null,
         "work_position":null,
         "inn":null,
         "kpp":null,
         "comment":null,
         "related_baskets":[

         ],
         "created_at":"2019-07-30T12:49:54+03:00",
         "updated_at":"2019-07-30T12:50:52+03:00",
         "deleted_at":null
      }
   ],
   "integrations":{
      "roistat":{
         "roistat_visit":"100018"
      }
   }
}

где:

поле тип поля Описание
id int Идентификатор заказа
uniqid string Уникальный идентификатор заказа
payed boolean Флаг оплаты заказа
payed_at date Дата оплаты заказа
created_at date Дата создания заказа
updated_at date Дата обновления заказа
client_id int Идентификатор покупателя
client array Данные о покупателе
payment_id int Идентификатор получателя платежей
payment_type_id string Идентификатор способа оплаты
payment_url string URL страницы для оплаты заказа
cancel_url string URL страницы для отмены заказа
basket_user_id int
backend_user_id int Идентификатор пользователя, если заказ был оформлен через ЛК
access_code_id int Идентификатор кода доступа
discount_id int Идентификатор скидки
promo_code_id int Идентификатор промокода
reserved boolean Флаг бесконечного бронирования
reserved_to date Дата бронирования
reserve_extended boolean Флаг продления бронирования
event_id int Идентификатор мероприятия
price float Итоговая цена
original_price float Цена, без учета скидок
currency_id string Валюта
utm array UTM-метки
custom array Дополнительные данные, которые были указаны в data-custom аттрибуте кнопки покупки
fields array Дополнительные поля (Название компании, ИНН, КПП…)
baskets array Состав заказа (билеты)
integrations array Если подключена интеграция Roistat, то будет возвращен roistat_visit
refunded_baskets array Возвращенные билеты (для типа "Заказ возвращен")
checked_basket array Проверенный билет (для типа "Гость пришёл на событие")

Доставка данных

Данные считаются успешно доставленными, если сервер вернул ответ с HTTP статусом 200. Если этого не произошло, то всего будет 10 попыток отправки, где каждая попытка будет отложена на n^3 сек, где n — номер попытки. Т.е. вебхук будет пытаться отправиться в течении 50 минут.

Проверка цифровой подписи

Служит для проверки данных, чтобы исключить посторонние запросы (не от сервиса Qtickets). Для этого укажите в настройках вебхука ваш секрет и проверяйте данные на вашей стороне.

Пример кода на PHP

// Читаем содержимое POST-запроса
$body = file_get_contents("php://input");
$data = json_decode($body, true); // Массив с данными
$event = $_SERVER['HTTP_X_EVENT_TYPE']; // Тип события

print_r($data);

Пример кода на PHP (с проверкой цифровой подписи)

// Читаем содержимое POST-запроса
$body = file_get_contents("php://input");

// Генерируем код, которым должен быть подписан webhook
$sha1 = hash_hmac('sha1', $body, 'SuperSecret');

// Сравниваем полученный код подписи, с тем что пришёл с хуком
if ($sha1 == $_SERVER['HTTP_X_SIGNATURE']) {
    // webhook пришёл от сервиса Qtickets
    $data = json_decode($body, true); // Массив с данными
    $event = $_SERVER['HTTP_X_EVENT_TYPE']; // Тип события

    print_r($data);
}

Была ли эта статья вам полезна?

Статьи по теме