Conceitos e solução de problemas

Nesta página, detalhamos as configurações específicas necessárias para a integração, além da solução de problemas comuns.

Requisitos de rede de telefonia

Se a rede filtrar o tráfego de saída, ela precisará permitir o tráfego de saída para sinalização SIP e streaming de mídia.

Para sinalização SIP, todo o intervalo de IP 74.125.88.128/25 (TCP) na porta 5672 precisa ser permitido. Para um conjunto de regras de firewall mais restritivo, é possível restringir a sinalização SIP a apenas um ou mais servidores SIP GTP regionalizados:

  • Região dos EUA: us.telephony.goog (74.125.88.132)
  • Região da UE: eu.telephony.goog (74.125.88.133)
  • Região da Ásia-Pacífico: ap.telephony.goog (74.125.88.134)
  • Região da América do Sul: sa.telephony.goog (74.125.88.135)

Para mídia RTP, configure regras de firewall para permitir o tráfego destinado ao intervalo de IP CIDR 74.125.39.0/24. Normalmente, as portas necessárias para mídia são apenas 16384-32767 (TCP+UDP), mas esse intervalo pode ser expandido no futuro.

Fornecedores ou modelos de SBC compatíveis

A tabela a seguir lista os fornecedores ou modelos de SBC e as versões de firmware compatíveis. Instruções detalhadas de integração para cada fornecedor estão vinculadas na versão do firmware.

Fornecedores e modelos Versões de firmware
Controlador de Borda de Sessão (SBC) AudioCodes VE v7.40A.500.786
Controlador de borda de sessão da Avaya para empresas v8.1.3.2-38-22279, v10.2.0.0-86-24077
Oracle E-SBC Acme Packet 3900 SCZ9.3.0 GA (Build 46)
Ribbon Swe Core SBC v11.01.01R005
Cisco Unified Border Element (CUBE) v17.15.03a

Protocolos de mídia e sinalização SBC compatíveis

Protocolo de sinalização SIP sobre TLS
Mídia SRTP
Criptografia de mídia SDES
Pacote de criptografia de mídia compatível AES_CM_128_HMAC_SHA1_80, AEAD_AES_256_GCM
Codecs de mídia compatíveis G.711 µ-law (PCMU), G.711 A-law (PCMA), Opus

Cabeçalhos SIP

Ao configurar um perfil de conversa e um número de telefone, você criou um perfil de conversa da CCAI com o sipConfig.createConversationOnTheFly definido como true. O ID da conversa precisa ser gerado dinamicamente durante o SIP INVITE usando o valor do cabeçalho SIP de Call-Info ou UUI.

O valor do cabeçalho SIP aponta para o endpoint do Dialogflow definindo o ID do projetoGoogle Cloud e o ID da conversa:

  1. O ID do projeto Google Cloud é o projeto que você usou ao configurar um projeto do Google Cloud .
  2. O ID da conversa precisa ser gerado dinamicamente pelo SBC. O ID da conversa precisa estar em conformidade com a fórmula de expressão regular [a-zA-Z][a-zA-Z0-9_-]*, com o comprimento dos caracteres no intervalo de [3,64]. Para gerar dinamicamente o ID da conversa, um padrão comum é usar o valor Call-ID no SIP INVITE e adicionar um prefixo com letras para que ele esteja em conformidade com a expressão regular, conforme especificado anteriormente. Por exemplo, se o valor de Call-ID for 297363723_79131759_799783510, prefixar o valor de Call-ID com "CID-" o tornaria compatível com a expressão regular [a-zA-Z][a-zA-Z0-9_-]*.

Cabeçalho SIP Call-Info

Insira um cabeçalho SIP personalizado chamado Call-Info no SIP INVITE para definir exclusivamente o ID da conversa:

Call-Info: <http://dialogflow.googleapis.com/v2beta1/projects/$PROJECT_ID/conversations/$CONVERSATION_ID>;purpose=Goog-ContactCenter-Conversation

Exemplo:

Call-Info: <http://dialogflow.googleapis.com/v2beta1/projects/gcp-project-id-12345/conversations/CID-297363723_79131759_799783510>;purpose=Goog-ContactCenter-Conversation

Cabeçalho SIP UUI

Se a definição do cabeçalho SIP personalizado Call-Info não for compatível, configure o cabeçalho SIP UUI (usuário para usuário) no SIP INVITE para transmitir o ID da conversa.

Use os mesmos dados solicitados em Call-Info com o URL codificado em hexadecimal e a finalidade definida como Goog-ContactCenter-Conversation. Confira a seguir um exemplo de cabeçalho, em que a string hexadecimal decodificada é http://dialogflow.googleapis.com/v2beta1/projects/gcp-project-id-12345/conversations/CID-297363723_79131759_799783510:

User-to-User: 687474703a2f2f6469616c6f67666c6f772e676f6f676c65617069732e636f6d2f763262657461312f70726f6a656374732f6763702d70726f6a6563742d69642d31323334352f636f6e766572736174696f6e732f4349442d3239373336333732335f37393133313735395f373939373833353130;encoding=hex;purpose=Goog-ContactCenter-Conversation

Se outros dados precisarem ser transmitidos para o agente de conversa e definidos como um parâmetro de sessão, passe uma lista separada por ponto e vírgula de pares de chave-valor codificados em hexadecimal, seguidos por ;encoding=hex;purpose=Goog-Session-Param. Isso vai resultar em um parâmetro de sessão criado com o nome uui-headers que contém uma lista de strings de payload decodificadas.

Por exemplo, se a string key1=value1;key2=value2 precisasse ser transmitida, o cabeçalho UUI a seguir seria enviado, em que o payload é o valor codificado em hexadecimal de key1=value1;key2=value2.

User-to-User: 6B6579313D76616C7565313B6B6579323D76616C756532;encoding=hex;purpose=Goog-Session-Param

que resultaria na criação do seguinte parâmetro de sessão.

{
    "uui-headers": ["key1=value1;key2=value2"]
}

Se o SBC aceitar o envio de vários cabeçalhos UUI, você poderá enviar strings de valor-chave individuais por cabeçalho UUI, e elas estarão disponíveis como valores individuais no parâmetro de sessão uui-headers.

O snippet a seguir usa o valor do parâmetro e o divide várias vezes para acessar o valor apropriado da variável key2 na string.

$sys.func.GET($sys.func.SPLIT($sys.func.GET($sys.func.SPLIT($session.params.uui-headers,";"),1),"="),1)

O exemplo a seguir mostra uma função que é chamada por um gatilho nos blocos de código do Playbook, por exemplo: @PlaybookStartHandler, que é chamado ao entrar no playbook. Outras funções chamam essa função para receber valores do parâmetro uui-headers.

def _get_fromuui(attribute):
    try:
        uui_headers_src = history.playbook_input.action_parameters['uui-headers']
        # If uui_headers_src is a string, split by ';'
        if isinstance(uui_headers_src, str):
            headers = uui_headers_src.split(';')
        else:
            # If it's a list, join and split
            headers = ';'.join(uui_headers_src).split(';')
        for header in headers:
            header = header.strip()
            if header.lower().startswith(f"{attribute.lower()}="):
                return header[len(attribute) + 1:]
        return ""
    except Exception:
        return ""

Outros dados podem ser enviados usando cabeçalhos UUI separados com valores de "finalidade" diferentes. Esses valores são adicionados ao objeto Conversation.telephonyConnectionInfo. Esses dados não estão disponíveis para o agente de conversação (Dialogflow CX) durante a execução.

Transmitir informações do agente humano

Se você precisar transmitir informações específicas para agentes humanos, defina o atributo de rótulo de mídia do Protocolo de descrição de sessão (SDP), para o agente humano, o fluxo do Protocolo de transporte em tempo real (RTP) para o valor de dados necessário. Exemplo: none a=label:7382373482 Esses dados serão preenchidos no campo sip_recording_media_label e estarão disponíveis no tópico New message notification do Pub/Sub que contém as transcrições. Procure o campo sip_recording_media_label na mensagem Message.attributes do pubsub.

Configurar funções de participantes e ordem de stream de mídia

Por padrão, o primeiro fluxo de mídia é associado à função de participante END_USER, e os fluxos de mídia subsequentes são associados à função de participante HUMAN_AGENT.

Se você precisar de um comportamento diferente (por exemplo, em um sistema de chamadas externas), o URL transmitido no cabeçalho precisará ter o parâmetro "roles" anexado.

Exemplo: none http://dialogflow.googleapis.com/v2beta1/projects/gcp-project-id-12345/conversations/CID-297363723_79131759_799783510?roles=HUMAN_AGENT,END_USER

O URL especifica que o primeiro fluxo de mídia deve ter a função HUMAN_AGENT e o segundo, a função END_USER. É possível aplicar o parâmetro "roles" com o cabeçalho SIP Call-Info ou UUI.

Definir parâmetros adicionais em uma conversa específica

Para definir outros parâmetros em uma conversa específica, use a chamada de RPC MatchIntentRequest. Você pode definir query_params.parameters como os pares de valores-chave necessários e query_input.text como algo como "Definir parâmetros".

Faça a chamada de API após a resposta "200 OK" do SIP INVITE inicial, quando a conversa tiver sido criada. O ID da sessão para o MatchIntentRequest é o mesmo ID de conversa fornecido no cabeçalho Call-Info no INVITE.

Usar SIP REFER para transferir uma chamada para um endpoint SIP

Para transferir uma chamada de um agente virtual para um endpoint SIP, use o método SIP REFER. Inclua uma carga útil no campo Live agent handoff e defina o campo Telephony transfer call como o número definido no campo SIP REFER Refer-To de saída. O payload deve ser semelhante ao exemplo de código a seguir.

{
    "sip-refer": true
}

Se for necessário transmitir dados dos agentes de conversação (Dialogflow CX), os cabeçalhos da UUI poderão ser usados para transmitir strings de dados. Se você quiser fazer um SIP REFER e transmitir dois pares de chave-valor, use uma carga útil semelhante ao exemplo de código a seguir.

{
    "sip-refer": true,
    "uui-headers": [
        "key1=value1;key2=value2"
    ]
}

Isso geraria um SIP REFER com o seguinte cabeçalho UUI.

User-to-User: <hex encoded "key1=value1;key2=value2">;encoding=hex;purpose=Goog-Session-Param

Transmitir dados em um SIP BYE

A navegação até End Session vai acionar um SIP BYE. Se você quiser transmitir dados para fora dos agentes de conversação (Dialogflow CX), use cabeçalhos UUI para transmitir strings de dados. Você encaminharia a chamada para uma página que definisse o payload Live agent handoff de maneira semelhante ao exemplo de código a seguir antes da transição para End Session.

{
    "uui-headers": [
        "key1=value1;key2=value2"
    ]
}

Isso geraria um SIP BYE com o seguinte cabeçalho UUI.

User-to-User: <hex encoded "key1=value1;key2=value2">;encoding=hex;purpose=Goog-Session-Param

Acionar uma ação quando o autor da chamada remota desliga

A nova API BiDi (use_bidi_streaming=True em ConversationProfile) permite acionar uma chamada de ferramenta em um playbook ou uma chamada de webhook em um fluxo quando o autor da chamada remota desliga.

Quando o usuário remoto desliga e os agentes de conversação (Dialogflow CX) recebem uma mensagem SIP BYE, o evento personalizado sys.remote-call-disconnected é acionado. Se você criar um manipulador com esse nome de evento específico, poderá usá-lo para acionar uma chamada de ferramenta com um playbook ou uma chamada de webhook em um fluxo.

Solução de problemas

A equipe do Google pode pedir que você forneça os seguintes artefatos para ajudar na solução de problemas do ping de OPTIONS do SIP e das chamadas de teste realizadas:

  1. Captura de pacote de rede
  2. Rastreamento de depuração do SIP mostrando o cabeçalho completo e o SDP do SIP:
    • Valor do ID da chamada
    • Valor Call-Info (se existir)

Captura de pacote de rede

A captura de pacote de rede precisa mostrar o seguinte:

  1. Um handshake TCP completo de três vias (SYN, SYN-ACK, ACK) entre o SBC e os servidores SIP GTP comunicados pela porta TCP 5672. Se a conexão TCP não for estabelecida, os possíveis problemas são:

    • Sua rede está bloqueando o tráfego de saída.
    • A comunicação não está sendo enviada para um dos servidores SIP GTP regionalizados. Consulte Requisito de rede para conectividade de telefonia.
    • A comunicação não está sendo enviada pela porta TCP 5672.
  2. Um handshake de conexão TLS completo com o seguinte:

    • TLS v1.2 ou mais recente iniciado pelo SBC.
    • Seu SBC iniciar um "Client Hello" e o GTP responder com "Server Hello".
    • Processo de autenticação TLS mútua.
      • O GTP responde com o próprio certificado TLS do servidor, que é autenticado pelo seu SBC.
      • O SBC envia o próprio certificado TLS do cliente, que é autenticado pelo GTP.
    • Canal criptografado estabelecido, conforme evidenciado pela "Mensagem de handshake criptografada".
    • Evidências de que os "Dados de aplicativo" estão sendo transmitidos pelo canal TLS.

    Se a conexão TLS não foi estabelecida, os possíveis problemas são:

    • O entroncamento SIP não foi criado no lado do GTP.
    • O FQDN configurado do tronco SIP não corresponde ao FQDN apresentado no certificado TLS (atributo CN ou SAN) do SBC.
    • A versão do TLS não é compatível. Apenas a versão 1.2 ou posterior é compatível.
    • O pacote de criptografia solicitado não é compatível. Consulte Configuração de TLS do SBC.
    • Provedores de certificados TLS não confiáveis. Consulte Configuração de TLS do SBC.
  3. O rastreamento de depuração do SIP deve mostrar o seguinte:

    • Cabeçalho SIP do cliente Call-Info inserido neste formato: none Call-Info: <http://dialogflow.googleapis.com/v2beta1/projects/$PROJECT_ID/conversations/$CONVERSATION_ID>;purpose=Goog-ContactCenter-Conversation

      Exemplo: none Call-Info: <http://dialogflow.googleapis.com/v2beta1/projects/gcp-project-id-12345/conversations/CID-297363723_79131759_799783510>;purpose=Goog-ContactCenter-Conversation

    • Os cabeçalhos SIP mostram o número de telefone no formato E.164 (+16501234567).

    • Os cabeçalhos SIP mostram os endereços IP públicos usados no URI da solicitação e em outros campos de cabeçalho SIP (por exemplo, "Para", "De", "Via"). Endereços IP particulares seriam rejeitados.

    • As informações de conexão SDP SIP (c= ... ) são especificadas com um endereço IP público. Endereços IP particulares seriam rejeitados.

    • Verifique se a priorização de mídia envia primeiro o fluxo dos usuários finais e depois o fluxo de mídia do agente humano, porque o GTP trata o primeiro fluxo de mídia como o dos usuários finais por padrão.

    Se você receber um código de resposta de erro SIP:

    • O código de resposta de erro SIP 400 (por exemplo, 488 Not Acceptable Here) provavelmente indica que o GTP rejeitou um cabeçalho SIP ou uma configuração SDP de mídia SIP.
    • Um código de resposta de erro SIP 600 (erro recusado SIP 603) provavelmente indica um problema relacionado à cota. Consulte a página Cotas e limites para saber como solicitar um aumento.