Учебник по схеме
Учебник по схемеУрок 18: Взаимодействие с внешними сервисами через вебхуки

Урок 18: Взаимодействие с внешними сервисами через вебхуки

Вебхук — это функция обратного вызова на основе HTTP, которую внешний сервис вызывает для уведомления о каком-либо событии, передавая вместе с ним полезную нагрузку (payload) с данными. Вебхуки позволяют различным веб-приложениям и сервисам взаимодействовать друг с другом.

Примеры сервисов, использующих вебхуки:

  • GitHub — при отправке коммита в репозиторий
  • Dropbox — при обновлении документа
  • WooCommerce — при добавлении заказа
  • Microsoft Teams — для получения форматированных текстовых сообщений и публикации в публичных каналах
  • ConvertKit — при активации подписчика

С помощью Gato GraphQL можно создавать Persisted Queries, работающие как вебхуки:

  • Поскольку Persisted Query доступна по собственному URL, она может использоваться в качестве цели для вебхука
  • Каждая Persisted Query может обрабатывать исключительно определённый вебхук

В этом уроке туториала мы создадим Persisted Query для взаимодействия с ConvertKit.

Изучение документации вебхука

Первый шаг — прочитать документацию сайта и понять, какие данные передаются в полезной нагрузке.

Анализируя вебхуки в ConvertKit, события, связанные с подписчиками, отправляют запрос POST на наш URL с JSON-полезной нагрузкой следующего вида:

{
  "subscriber": {
    "id": 1,
    "first_name": "John",
    "email_address": "John@example.com",
    "state": "active",
    "created_at": "2018-02-15T19:40:24.913Z",
    "fields": {
      "My Custom Field": "Value"
    }
  }
}

Извлечение данных из полезной нагрузки

Поскольку запрос отправляется через POST, необходимо извлечь данные из тела HTTP-запроса (это поддерживается расширением HTTP Request via Schema).

Если HTTP-запрос выполняется через GET, Persisted Query может напрямую получить элементы данных из параметров URL.

Этот GraphQL-запрос извлекает тело запроса и преобразует его в JSON-объект. Затем из JSON-объекта извлекаются элементы "subscriber.first_name" и "subscriber.email_address", которые экспортируются как динамические переменные:

query ExtractPayloadData {
  body: _httpRequestBody
  bodyJSONObject: _strDecodeJSONObject(string: $__body)
 
  subscriberFirstName: _objectProperty(
    object: $__bodyJSONObject,
    by: { path: "subscriber.first_name" }
  )
    @export(as: "subscriberFirstName")
  
  subscriberEmail: _objectProperty(
    object: $__bodyJSONObject,
    by: { path: "subscriber.email_address" }
  )
    @export(as: "subscriberEmail")
}

Расширение HTTP Request via Schema позволяет получить все данные текущего HTTP-запроса через следующие поля:

  • _httpRequestBody: Тело HTTP-запроса
  • _httpRequestClientHost: Хост клиента
  • _httpRequestClientIP: IP-адрес клиента (или null, если сервер настроен неверно)
  • _httpRequestCookie: Значение cookie запроса
  • _httpRequestCookies: Cookies запроса
  • _httpRequestDomain: Домен запрошенного URL
  • _httpRequestFullURL: Запрошенный URL (включая параметры запроса)
  • _httpRequestHasCookie: Содержит ли запрос определённый cookie?
  • _httpRequestHasHeader: Содержит ли запрос определённый заголовок?
  • _httpRequestHasParam: Содержит ли запрос определённый параметр?
  • _httpRequestHeader: Значение заголовка запроса
  • _httpRequestHeaders: Заголовки запроса
  • _httpRequestHost: Хост запрошенного URL
  • _httpRequestMethod: Метод запроса
  • _httpRequestStringParam: Значение параметра (переданного через POST или GET) вида ?param=value
  • _httpRequestStringListParam: Значение параметра (переданного через POST или GET) вида ?param[]=value1&param[]=value2
  • _httpRequestParams: Параметры, переданные через POST или через строку URL-запроса
  • _httpRequestProtocol: Протокол запроса
  • _httpRequestQuery: Строка параметров запроса
  • _httpRequestReferer: Referer запроса
  • _httpRequestRequestTime: Временная метка начала запроса
  • _httpRequestScheme: Схема запрошенного URL
  • _httpRequestServerIP: IP-адрес сервера
  • _httpRequestURL: Запрошенный URL (без параметров запроса)
  • _httpRequestURLPath: Абсолютный путь (начинающийся с «/») запрошенного URL
  • _httpRequestUserAgent: User agent

Выполнение действия с данными

После извлечения данных из полезной нагрузки можно выполнить какое-либо действие с ними.

Этот GraphQL-запрос обрабатывает событие subscriber.subscriber_unsubscribe и отправляет письмо человеку, который отписался, с просьбой оставить отзыв.

query CreateEmailMessage
  @depends(on: "ExtractPayloadData")
{
  emailMessageTemplate: _strConvertMarkdownToHTML(
    text: """
 
Hey {$subscriberFirstName}, it's sad to let you go!
 
Please be welcome to complete [this form](https://forms.gle/FpXNromWAsZYC1zB8) and let us know if there is anything we can do better.
 
Thanks. Hope to see you back!
 
    """
  )
  emailMessage: _strReplaceMultiple(
    search: ["{$subscriberFirstName}"],
    replaceWith: [$subscriberFirstName],
    in: $__emailMessageTemplate
  )
    @export(as: "emailMessage")
}
 
mutation SendEmail @depends(on: "CreateEmailMessage") {
  _sendEmail(
    input: {
      to: $subscriberEmail
      subject: "Would you like to give us feedback on how we can improve?"
      messageAs: {
        html: $emailMessage
      }
    }
  ) {
    status
  }
}