Lição 18: Interagindo com serviços externos via webhooks
Um webhook é uma função de callback baseada em HTTP que um serviço externo chama para notificar sobre algum evento, passando junto um payload de dados. Os webhooks permitem que diferentes aplicações web e serviços se comuniquem entre si.
Alguns exemplos de serviços que invocam webhooks incluem:
- GitHub, quando um commit é enviado para um repositório
- Dropbox, quando um documento é atualizado
- WooCommerce, quando um pedido é adicionado
- Microsoft Teams, para receber mensagens em texto formatado e publicar em canais públicos
- ConvertKit, quando um assinante é ativado
Com o Gato GraphQL, podemos criar Persisted Queries que atuam como webhooks:
- Como a Persisted Query é exposta sob sua própria URL, ela pode ser usada como destino do webhook
- Cada Persisted Query pode lidar exclusivamente com um webhook específico
Nesta lição do tutorial, criaremos uma Persisted Query para interagir com o ConvertKit.
Consultando a documentação do webhook
O primeiro passo é ler a documentação do site e entender quais dados são enviados via payload.
Analisando os webhooks no ConvertKit, os eventos relacionados a assinantes enviam uma requisição POST para nossa URL com um payload JSON como este:
{
"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"
}
}
}Extraindo os dados do payload
Como a requisição é enviada via POST, precisamos extrair os dados do corpo da requisição HTTP (o que é suportado pela extensão HTTP Request via Schema).
Se a requisição HTTP for executada via GET, a Persisted Query pode diretamente obter os itens de dados dos parâmetros da URL.
Esta query GraphQL recupera o corpo da requisição e o converte em um objeto JSON. Em seguida, extrai os itens "subscriber.first_name" e "subscriber.email_address" do objeto JSON e os exporta como variáveis dinâmicas:
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")
}A extensão HTTP Request via Schema nos permite recuperar todos os dados da requisição HTTP atual, por meio dos seguintes campos:
_httpRequestBody: Corpo da requisição HTTP_httpRequestClientHost: Host do cliente_httpRequestClientIP: Endereço IP do cliente (ounullse o servidor não estiver configurado corretamente)_httpRequestCookie: Valor do cookie da requisição_httpRequestCookies: Cookies da requisição_httpRequestDomain: Domínio da URL solicitada_httpRequestFullURL: URL solicitada (incluindo os parâmetros de query)_httpRequestHasCookie: A requisição contém um determinado cookie?_httpRequestHasHeader: A requisição contém um determinado header?_httpRequestHasParam: A requisição contém um determinado parâmetro?_httpRequestHeader: Valor do header da requisição_httpRequestHeaders: Headers da requisição_httpRequestHost: Host da URL solicitada_httpRequestMethod: Método da requisição_httpRequestStringParam: Valor de um parâmetro (passado via POST ou GET) do tipo?param=value_httpRequestStringListParam: Valor de um parâmetro (passado via POST ou GET) do tipo?param[]=value1¶m[]=value2_httpRequestParams: Parâmetros passados via POST ou via a query da URL_httpRequestProtocol: Protocolo da requisição_httpRequestQuery: String dos parâmetros de query_httpRequestReferer: Referer da requisição_httpRequestRequestTime: Timestamp do início da requisição_httpRequestScheme: Esquema da URL solicitada_httpRequestServerIP: Endereço IP do servidor_httpRequestURL: URL solicitada (sem os parâmetros de query)_httpRequestURLPath: Caminho absoluto (começando com "/") da URL solicitada_httpRequestUserAgent: User agent
Executando uma ação com os dados
Assim que extraímos os dados do payload, podemos executar alguma ação com eles.
Esta query GraphQL lida com o evento subscriber.subscriber_unsubscribe, para enviar um e-mail à pessoa que cancelou a assinatura, solicitando um feedback.
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
}
}