Integrações com a API de Jornadas
Chamadas HTTP dentro de Jornadas
As Jornadas podem ser integradas com APIs expostas por meio de HTTP.
As funções get
, post
, put
e patch
realizam chamadas HTTP. As chamadas HTTP permitem os seguintes parâmetros:
card GetCard, then: PostCard do
get_response = get("https://example.org/endpoint",
timeout: 5_000,
cache_ttl: 60_000,
query: [
["name", "@contact.name"],
["whatsapp_id", "@contact.whatsapp_id"]
])
log("@get_response")
end
card PostCard, then: PutCard do
post_response = post("https://example.org/endpoint",
timeout: 5_000,
cache_ttl: 60_000,
body: """
{"username": @contact.whatsapp_id}
""",
headers: [["content-type", "application/json"]]
)
log("@post_response")
end
card PutCard, then: PatchCard do
put_response = put("https://example.org/endpoint",
timeout: 5_000,
cache_ttl: 60_000,
body: """
{"username": @contact.whatsapp_id}
""",
headers: [["content-type", "application/json"]]
)
log("@put_response")
end
card PatchCard do
patch_response = patch("https://example.org/endpoint",
timeout: 5_000,
cache_ttl: 60_000,
body: """
{"username": @contact.whatsapp_id}
""",
headers: [["content-type", "application/json"]]
)
log("@patch_response")
end
opção | uso |
---|---|
body | O corpo da requisição HTTP |
cache_ttl | Quanto tempo armazenar uma resposta em cache, em milissegundos (60_000 ou 60000 são 60 segundos) |
headers | Uma lista de listas com cabeçalhos HTTP. [["X-Foo", "Bar"]] adicionaria o cabeçalho X-Foo à requisição HTTP. |
mode | "sync" ou "async" |
query | Uma lista de listas com chaves e valores para usar como parâmetros de consulta. [[key, value]] adiciona ?key=value à requisição |
timeout | Quanto tempo uma requisição pode levar, em milissegundos (5_000 ou 5000 são 5 segundos). Valores acima de 20 segundos serão limitados a 20 segundos. |
url | O endpoint HTTP |
Os headers HTTP e os parâmetros de consulta podem ser expressões que são avaliadas.
Os headers HTTP especificados serão incluídos além dos seguintes headers HTTP padrão:
User-Agent: Turn/X.X.X (Webhook das Jornadas)
X-Turn-Journey-UUID: <o-uuid-da-jornada>
X-Turn-Journey-Session-UUID: <o-uuid-da-sessao>
X-Turn-Journey-Environment: "staging" se o Contato for um usuário de staging, "production" caso contrário
Por favor, note que a Turn.io impõe um limite rígido no tempo de espera para respostas de serviços externos.
Se sua chamada levar mais de 20 segundos para responder, a chamada do webhook retornará um erro de tempo limite,
mesmo que o valor do seu timeout
seja maior que 20 segundos.
Recomendamos que você garanta que os serviços externos sejam performáticos (tempo de resposta inferior a 10 segundos é preferível),
para trabalhar dentro desses limites e garantir que o usuário final no WhatsApp não fique esperando por longos períodos.
Erros de Conexão HTTP
Se o lado remoto da sua chamada HTTP expirar ou encerrar a conexão, o status da resposta será definido como null
e o atributo body
da resposta conterá o erro ocorrido.
É responsabilidade do autor da jornada garantir que erros de conexão e timeouts sejam tratados de forma adequada para assegurar uma boa experiência do usuário.
Aqui está um exemplo de como lidar com um erro de conexão:
card Webhook, then: Report do
resp =
post("https://example.org",
body: "hello world!",
timeout: 5_000,
query: [["foo", "bar"]],
headers: [
["content-type", "text/plain; charset=utf-8"]
]
)
end
card Report when not resp.status do
text("""
Pedimos desculpas, parece que estamos enfrentando alguns problemas de conexão.
O erro da resposta foi ```@resp.body```
Por favor, tente novamente mais tarde!
""")
end
card Report do
text("sucesso")
end
Integração com feed RSS
Aqui está um exemplo que lê o feed RSS do podcast Global News da BBC e permite que os usuários naveguem pelos episódios e os escutem.
card Init, "⏮ Último episódio", then: Start do
# Inicializa o cursor com o valor zero, isso significa que sempre começamos
# com a primeira, mais recente, entrada do feed RSS
cursor = 0
# Usa a API pública do rss2json.com para converter o feed RSS publicado pela
# BBC para o podcast de serviço mundial em um arquivo JSON que podemos ler.
webhook =
get(
"https://api.rss2json.com/v1/api.json?rss_url=https%3A%2F%2Fpodcasts.files.bbci.co.uk%2Fp02nq0gn.rss"
)
items = webhook.body.items
# Mantém o controle do número total de itens
total_items = count(items)
end
card Start do
# Lê o item atual
item = items[cursor]
# Envia primeiro o arquivo de áudio, já que este é um arquivo _grande_ e leva mais
# tempo para chegar no celular do que as mensagens que enviamos depois.
audio("@item.enclosure.link")
# Gera os botões
buttons([Init, NextCard]) do
# Envia o título como legenda
text("""
*@item.title*
@item.content
_Episódio @(cursor + 1) de @(total_items)_
_Publicado em @(item.pubDate)_
""")
# Infelizmente, o feed não possui imagens, então estamos usando apenas uma imagem estática
# do site da BBC
image("https://ichef.bbci.co.uk/images/ic/480x270/p09kz0v5.jpg")
end
end
# Mudamos o texto no botão dependendo se há ou não mais episódios. Se houver, exibimos "Próximo episódio ➡️", se não, exibimos "⏮ Primeiro episódio".
#
# Além disso, se chegarmos ao final do número total de episódios, redefinimos o contador para 0,
# o que nos faz começar do início novamente.
card NextCard, "@IF(cursor + 1 < total_items, \"Próximo episódio ➡️\", \"⏮ Primeiro episódio\")",
then: Start do
cursor = if cursor + 1 < total_items, do: cursor + 1, else: 0
end