Pular para o conteúdo principal

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çãouso
bodyO corpo da requisição HTTP
cache_ttlQuanto tempo armazenar uma resposta em cache, em milissegundos (60_000 ou 60000 são 60 segundos)
headersUma lista de listas com cabeçalhos HTTP. [["X-Foo", "Bar"]] adicionaria o cabeçalho X-Foo à requisição HTTP.
mode"sync" ou "async"
queryUma lista de listas com chaves e valores para usar como parâmetros de consulta. [[key, value]] adiciona ?key=value à requisição
timeoutQuanto 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.
urlO 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
info

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.

info

É 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