DEV Community

Cover image for Pequeno guia de webhooks com Ruby!
Giovanny Cordeiro
Giovanny Cordeiro

Posted on Edited on

Pequeno guia de webhooks com Ruby!

Nesse artigo irei explicar um pouco sobre Webhooks, seu uso e um exemplo prático ao final, espero que ajude seus estudos!

Inicio!

O conceito formal fornecido pela RedHat é:

"Um webhook é uma função de retorno de chamada baseada em HTTP que viabiliza a comunicação lightweight e orientada por eventos entre duas interfaces de programação de aplicações (APIs, na sigla em inglês)."

Para sintetizar, um webhook existe para comunicar que um evento aconteceu em um sistema A para um sistema B.

Se pararmos para pensar, esse conceito de "comunicar um evento que aconteceu em um sistema A para um sistema B" é muito útil, já que muitos sistemas precisam desse tipo de funcionalidade recorrentemente.

Um exemplo legal e bem comum é um e-commerce, que depende de muitos sistemas diferentes se comunicando para funcionar adequadamente como sistema de pagamento, entrega, o marketplace, mecanismos de recomendações, etc.

Para ficar mais fácil o exemplo que eu vou dar não irei mencionar muitas variáveis como essas no sistema, então, imagine então um sistema de e-commerce simples com apenas um serviço de pagamento.

Image description

O e-commerce é naturalmente responsável por promover a venda e captar todas as informações necessárias do cliente, validar os dados, etc.

Já o serviço de pagamento tem como objetivo de efetivamente comprovar o pagamento a respeito do pedido do cliente.

É intuitivo pensar que você só poderá atualizar a página de feedback do pedido para "pagamento efetuado" depois que realmente o pagamento for efetuado, mas como a gente vai fazer para que o e-commerce saiba que o cliente efetivamente pagou o pedido?

O serviço de pagamento é um sistema diferente do e-commerce, como a gente vai fazer para poder integrar ambos?

A primeira abordagem.

A primeira e mais obvia solução é vc fazer uma função dentro do seu e-commerce que vai ficar fazendo requisições para o serviço de pagamento, perguntando se o cliente fez o pagamento daquele pedido, você não vai querer ficar disparando toda hora essa requisição e pode fazer com que ela faça a requisição de 1 em 1 minuto, parece OK certo?

ERRADO!

Vamos supor que ocorreu o primeiro pedido do e-commerce e agora só falta o cliente realizar o pagamento, agora é só esperar ele pagar e dentro de 1 minuto sua aplicação vai atualizar a tela.

No entanto... o usuário não paga depois desse 1 minuto e nem da o ar da graça nas próximas 2hrs, o que aconteceu foi que ele, enquanto fazia o pedido no e-commerce, esqueceu que tinha que levar a vó dele para o treino de Jiu Jitsu e como ele é um bom neto, vai ficar para prestigiar o treino de sua vó e vai demorar 2hrs para voltar. Mas o mesmo usuário pensou "vou deixar o pedido aqui, quando voltar eu pago".

Nessas duas horas que se passaram seu e-commerce fez 120 requisições para o seu serviço se pagamento sem qualquer informação relevante do pagamento, sem qualquer nova atualização, perdendo capacidade computacional e gerando desperdício no sistema (Leia perca de dinheiro).

E isso foi apenas de um usuário imagina se fosse 100 usuários, que é um numero baixo, seria 12000 requisições jogadas completamente no lixo.

Image description

E qual seria uma abordagem melhor?

Abordagem com Webhook

Agora imagina que a gente pode ter um intermediário que avisa para o e-commerce que o pagamento de um pedido foi realizado? Isso seria ótimo certo? Iriamos fazer com que todo aquele desperdício da primeira abordagem fosse excluído e o sistema teria as informações atualizadas mais breve possível.

E esse intermediário ótimo tem nome, ele se chama Webhook. Com o Webhook sendo orientado a evento, podemos avisar por meio dos serviço de pagamento que um determinado pedido foi pago para o e-commerce, de forma simples e fácil, a lógica é a seguinte:

O serviço de pagamento avisa que foi pago um determinado pedido para o webhook, o webhook repassa essa informação para o e-commerce que atualiza agora a tela do usuário para "pagamento realizado" ou outra mensagem escolhida.

Image description

Fazendo o primeiro webhook simples!

Vamos colocar a mão na massa e ver como realmente como implementar webhooks. Como eu já expliquei anteriormente webhooks servem para comunicar que um evento aconteceu em um sistema A para um Sistema B, para deixar mais enxuto, vou fazer APIs simples para do webhook.

Para isso é necessário os seguintes elementos:

  • Primeira API: A primeira API fica esperando um evento acontecer na segunda, ligando com o exemplo que eu dei, poderia ser a API do e-commerce.
  • O webhook
  • Segunda API: Que acontece o evento e informa para o webhook para a primeira API, ligando com o exemplo, seria o serviço de pagamento.

As APIs nesse caso poderiam também ser um serviço ou outro sistema!

Só para deixar claro, os exemplos a seguir foram feitos em Ruby com o micro-framework Sinatra, pelo fato de ser a linguagem que eu estou mais gostando de estudar e aprender, mas você pode implementar o mesmo exemplo na sua ferramenta preferida.

Também deixei todo os códigos em um repositório no Github para que você não precise ficar copiando, clicka aqui.

Vamos começar criando a segunda API que é responsavel por notificar o evento para o webhook, o que ela precisa fazer é justamente fazer uma requisição simples para o webhook, como a gente faria para uma API normalmente. Segue o código.

require 'sinatra'
require 'rest-client'  
get '/' do
    puts 'test second app'
end    
post '/service' do
    # Logica do serviço de pagamento...     
    data_service = {
        'body' => 'dados para o primeiro serviço'
    }
    RestClient.post(
        'http://127.0.0.1:4568/webhook/event-created',
        data_service.to_json,
        {content_type: :json, accept: :json}
    )
end
Enter fullscreen mode Exit fullscreen mode

Agora vamos criar o próprio webhook, para isso você precisa criar outra API normalmente, no entanto, essa API vai receber os dados que vem da API 2 (no exemplo que dei, serviço de pagamento) e vai passar para a API 1 por meio de uma requisição POST (no exemplo que dei, e-commerce). Não atoa Webhook são chamados também como APIs inversas.

Ou seja, o webhook recebe uma requisição de uma API (ou serviço) e faz outra requisição POST passando esses dados para outra API (ou serviço).

require 'sinatra'
require 'rest-client'
post '/webhook/event-created' do
    puts 'chegou no webhook'
    request_first_app = RestClient.post(
        'http://127.0.0.1:4567/recieve_event',
        request.body,
        headers: { 'Content-Type': 'application/json' }
    )
end
Enter fullscreen mode Exit fullscreen mode

Só ficou faltando criar a primeira API, que vai receber os dados da Segunda API por meio do webhook, fazendo assim com que tudo funcione da forma adequada.

require 'sinatra'
before do
    request.body.rewind
    @request_payload = JSON.parse request.body.read
end
get '/' do
    puts 'hello world'
end
post '/recieve_event' do
    puts "evento que ocorreu no sistema 2, os dados são: #{@request_payload['body']}"
    # logica após receber o dado do body....
end
Enter fullscreen mode Exit fullscreen mode

Agora o que vai acontecer? Quando você fizer uma requisição POST na rota /service da segunda API essa ela mesma vai executar sua logica e avisar para o webhook que determinado evento evento ocorreu passando os dados escolhidos, o webhook repassa para a primeira API.

Antes de testar, se atente em rodar as APIs e o Webhook nas portas certas, caso contrario, pode ser que tenha dor de cabeça com isso, logo as portas nesse meu exemplo são as seguintes:

  • first_app: porta 4567
  • weebhook: porta 4568
  • second_app: porta 4569

Após rodar todas as aplicações com:

ruby src/nome_do_servico -p numero_da_porta

Faça uma requisição POST com body JSON para o endpoint http://127.0.0.1:4569/service, você notará que o dado mockado que você mandou no second_app vai ser logado da mesma forma no first_app, o que prova que conseguimos implementar de forma bem-sucedida o webhook.

É isso!

Espero que esse artigo tenha te ajudado a entender sobre webhooks! Qualquer coisa estou a disposição de ajudar e trocar uma ideia sobre tech nas minhas redes sociais, é isso!

Top comments (0)