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)