Partilhar via


Como controlar e orientar chamadas com o Call Automation

A Automação de Chamadas usa uma interface de API REST para receber solicitações de ações e fornecer respostas para notificar se a solicitação foi enviada com êxito ou não. Devido à natureza assíncrona da chamada, a maioria das ações tem eventos correspondentes que são acionados quando a ação é concluída com êxito ou falha. Este guia aborda as ações disponíveis para direcionar chamadas, como CreateCall, Transferir, Redirecionar e gerenciar participantes. As ações são acompanhadas de código de exemplo sobre como invocar a referida ação e diagramas de sequência descrevendo os eventos esperados depois de invocar uma ação. Esses diagramas ajudam você a visualizar como programar seu aplicativo de serviço com o Call Automation.

A Automação de Chamadas suporta várias outras ações para gerenciar a mídia e a gravação de chamadas que têm guias separados.

Como pré-requisito, recomendamos que leia estes artigos para tirar o máximo partido deste guia:

  1. Guia de conceitos de automação de chamadas que descreve o modelo de programação de eventos de ação e retornos de chamada de eventos.
  2. Saiba mais sobre identificadores de usuário como CommunicationUserIdentifier e PhoneNumberIdentifier usados neste guia.

Para todos os exemplos de código, client é o objeto CallAutomationClient que pode ser criado conforme mostrado e callConnection é o objeto CallConnection obtido da resposta Answer ou CreateCall. Você também pode obtê-lo de eventos de retorno de chamada recebidos pelo seu aplicativo.

var client = new CallAutomationClient("<resource_connection_string>"); 

Fazer uma chamada de saída

Você pode fazer uma chamada 1:1 ou em grupo para um usuário de comunicação ou número de telefone (público ou de propriedade dos Serviços de Comunicação). Ao chamar um ponto de extremidade PSTN, você também precisa fornecer um número de telefone que seja usado como o ID do chamador de origem e mostrado na notificação de chamada para o ponto de extremidade PSTN de destino. Para fazer uma chamada para um usuário dos Serviços de Comunicação, você precisa fornecer um objeto CommunicationUserIdentifier em vez de PhoneNumberIdentifier.

Uri callbackUri = new Uri("https://<myendpoint>/Events"); //the callback endpoint where you want to receive subsequent events 
var callerIdNumber = new PhoneNumberIdentifier("+16044561234"); // This is the Azure Communication Services provisioned phone number for the caller  
var callThisPerson = new CallInvite(new PhoneNumberIdentifier("+16041234567"), callerIdNumber); // person to call
CreateCallResult response = await client.CreateCallAsync(callThisPerson, callbackUri);

Ao fazer uma chamada em grupo que inclua um número de telefone, você deve fornecer um número de telefone que seja usado como um número de identificação de chamador para o ponto de extremidade PSTN.

Uri callbackUri = new Uri("https://<myendpoint>/Events"); //the callback endpoint where you want to receive subsequent events 
var pstnEndpoint = new PhoneNumberIdentifier("+16041234567");
var voipEndpoint = new CommunicationUserIdentifier("<user_id_of_target>"); //user id looks like 8:a1b1c1-...
var groupCallOptions = new CreateGroupCallOptions(new List<CommunicationIdentifier>{ pstnEndpoint, voipEndpoint }, callbackUri)
{
    SourceCallerIdNumber = new PhoneNumberIdentifier("+16044561234"), // This is the Azure Communication Services provisioned phone number for the caller
};
CreateCallResult response = await client.CreateGroupCallAsync(groupCallOptions);

A resposta fornece o objeto CallConnection que você pode usar para executar outras ações nessa chamada depois que ela estiver conectada. Depois que a chamada é atendida, dois eventos são publicados no ponto de extremidade de retorno de chamada fornecido anteriormente:

  1. CallConnected notificando que a chamada foi estabelecida com o destinatário.
  2. ParticipantsUpdated evento que contém a lista mais recente de participantes na chamada. Diagrama de sequência para fazer uma chamada de saída.

No caso em que a chamada falhar, você receberá um CallDisconnected evento e CreateCallFailed com códigos de erro para solução de problemas adicionais (consulte esta página para obter mais informações sobre códigos de erro).

Ligar a uma chamada

A ação Connect permite que seu serviço estabeleça uma conexão com uma chamada em andamento e execute ações nela. Isso é útil para gerenciar uma chamada de salas ou quando os aplicativos cliente iniciaram uma chamada 1:1 ou de grupo da qual a automação de chamadas não faz parte. A conexão é estabelecida usando a propriedade CallLocator e pode ser dos tipos: ServerCallLocator, GroupCallLocator e RoomCallLocator. Essas IDs podem ser encontradas quando a chamada é originalmente estabelecida ou uma Sala é criada, e também publicadas como parte do evento CallStarted .

Para se conectar a qualquer chamada 1:1 ou de grupo, use o ServerCallLocator. Se você iniciou uma chamada usando GroupCallId, você também pode usar o GroupCallLocator.

Uri callbackUri = new Uri("https://<myendpoint>/Events"); //the callback endpoint where you want to receive subsequent events
CallLocator serverCallLocator = new ServerCallLocator("<ServerCallId>");
ConnectCallResult response = await client.ConnectCallAsync(serverCallLocator, callbackUri);

Para se conectar a uma chamada de quartos, use RoomCallLocator que usa RoomId. Saiba mais sobre Salas e como a API de Automação de Chamadas pode ser usada para gerenciar chamadas de Salas contínuas.

Uri callbackUri = new Uri("https://<myendpoint>/Events"); //the callback endpoint where you want to receive subsequent events
CallLocator roomCallLocator = new RoomCallLocator("<RoomId>");
ConnectCallResult response = await client.ConnectCallAsync(roomCallLocator, callbackUri);

Uma resposta bem-sucedida fornece o objeto CallConnection que você pode usar para executar outras ações nessa chamada. Dois eventos são publicados no ponto de extremidade de retorno de chamada fornecido anteriormente:

  1. CallConnected notificando que você se conecta com êxito à chamada.
  2. ParticipantsUpdated evento que contém a lista mais recente de participantes na chamada.

A qualquer momento após uma conexão bem-sucedida, se o seu serviço for desconectado dessa chamada, você será notificado por meio de um evento CallDisconected. A falha ao se conectar à chamada em primeiro lugar resulta no evento ConnectFailed.

Diagrama de sequência para ligar à chamada.

Atender uma chamada recebida

Depois de se inscrever para receber notificações de chamadas recebidas para o seu recurso, você atenderá uma chamada recebida. Ao atender uma chamada, é necessário fornecer um URL de retorno de chamada. Os Serviços de Comunicação publicam todos os eventos subsequentes sobre essa chamada nessa url.

string incomingCallContext = "<IncomingCallContext_From_IncomingCall_Event>"; 
Uri callBackUri = new Uri("https://<myendpoint_where_I_want_to_receive_callback_events"); 

var answerCallOptions = new AnswerCallOptions(incomingCallContext, callBackUri);  
AnswerCallResult answerResponse = await client.AnswerCallAsync(answerCallOptions);
CallConnection callConnection = answerResponse.CallConnection; 

A resposta fornece o objeto CallConnection que você pode usar para executar outras ações nessa chamada depois que ela estiver conectada. Depois que a chamada é atendida, dois eventos são publicados no ponto de extremidade de retorno de chamada fornecido anteriormente:

  1. CallConnected evento notificando que a chamada foi estabelecida com o chamador.
  2. ParticipantsUpdated evento que contém a lista mais recente de participantes na chamada.

Diagrama de sequência para atender uma chamada recebida.

No caso em que a operação de resposta falhar, você receberá um AnswerFailed evento com códigos de erro para solução de problemas adicionais (consulte esta página para obter mais informações sobre códigos de erro).

Rejeitar uma chamada

Você pode optar por rejeitar uma chamada de entrada, conforme mostrado abaixo. Você pode fornecer um motivo de rejeição: nenhum, ocupado ou proibido. Se nada for fornecido, nenhum será escolhido por padrão.

string incomingCallContext = "<IncomingCallContext_From_IncomingCall_Event>"; 
var rejectOption = new RejectCallOptions(incomingCallContext); 
rejectOption.CallRejectReason = CallRejectReason.Forbidden; 
_ = await client.RejectCallAsync(rejectOption); 

Nenhum evento é publicado para a ação de rejeição.

Redirecionar uma chamada

Você pode optar por redirecionar uma chamada de entrada para outro ponto de extremidade sem atendê-la. O redirecionamento de uma chamada remove a capacidade do aplicativo de controlar a chamada usando a Automação de Chamadas.

string incomingCallContext = "<IncomingCallContext_From_IncomingCall_Event>"; 
var target = new CallInvite(new CommunicationUserIdentifier("<user_id_of_target>")); //user id looks like 8:a1b1c1-... 
_ = await client.RedirectCallAsync(incomingCallContext, target); 

Para redirecionar a chamada para um número de telefone, construa o ID de destino e de chamada com PhoneNumberIdentifier.

var callerIdNumber = new PhoneNumberIdentifier("+16044561234"); // This is the Azure Communication Services provisioned phone number for the caller
var target = new CallInvite(new PhoneNumberIdentifier("+16041234567"), callerIdNumber);

Nenhum evento é publicado para redirecionamento. Se o destino for um usuário dos Serviços de Comunicação ou um número de telefone de propriedade do seu recurso, ele gerará um novo evento IncomingCall com o campo 'para' definido para o destino especificado.

Transferir um participante na chamada

Quando seu aplicativo atende uma chamada ou faz uma chamada de saída para um ponto de extremidade, esse ponto de extremidade pode ser transferido para outro ponto de extremidade de destino. A transferência de uma chamada 1:1 remove seu aplicativo da chamada e, portanto, remove sua capacidade de controlar a chamada usando a automação de chamadas. O convite de chamada para o destino exibirá o ID do chamador do ponto de extremidade que está sendo transferido. Não há suporte para o fornecimento de um ID de chamador personalizado.

var transferDestination = new CommunicationUserIdentifier("<user_id>"); 
var transferOption = new TransferToParticipantOptions(transferDestination) {
    OperationContext = "<Your_context>",
    OperationCallbackUri = new Uri("<uri_endpoint>") // Sending event to a non-default endpoint.
};
// adding customCallingContext
transferOption.CustomCallingContext.AddVoip("customVoipHeader1", "customVoipHeaderValue1");
transferOption.CustomCallingContext.AddVoip("customVoipHeader2", "customVoipHeaderValue2");

TransferCallToParticipantResult result = await callConnection.TransferCallToParticipantAsync(transferOption);

Quando seu aplicativo responde a uma chamada de grupo ou faz uma chamada de grupo de saída para um ponto de extremidade ou adiciona um participante a uma chamada 1:1, um ponto de extremidade pode ser transferido da chamada para outro ponto de extremidade de destino, exceto o ponto de extremidade de automação de chamada. A transferência de um participante em uma chamada em grupo remove o ponto de extremidade que está sendo transferido da chamada. O convite de chamada para o destino exibirá o ID do chamador do ponto de extremidade que está sendo transferido. Não há suporte para o fornecimento de um ID de chamador personalizado.

// Transfer User
var transferDestination = new CommunicationUserIdentifier("<user_id>");
var transferee = new CommunicationUserIdentifier("<transferee_user_id>"); 
var transferOption = new TransferToParticipantOptions(transferDestination);
transferOption.Transferee = transferee;

// adding customCallingContext
transferOption.CustomCallingContext.AddVoip("customVoipHeader1", "customVoipHeaderValue1");
transferOption.CustomCallingContext.AddVoip("customVoipHeader2", "customVoipHeaderValue2");

transferOption.OperationContext = "<Your_context>";
transferOption.OperationCallbackUri = new Uri("<uri_endpoint>");
TransferCallToParticipantResult result = await callConnection.TransferCallToParticipantAsync(transferOption);

// Transfer PSTN User
var transferDestination = new PhoneNumberIdentifier("<target_phoneNumber>");
var transferee = new PhoneNumberIdentifier("<transferee_phoneNumber>"); 
var transferOption = new TransferToParticipantOptions(transferDestination);
transferOption.Transferee = transferee;

// adding customCallingContext
transferOption.CustomCallingContext.AddSipUui("uuivalue");
transferOption.CustomCallingContext.AddSipX("header1", "headerValue");

transferOption.OperationContext = "<Your_context>";

// Sending event to a non-default endpoint.
transferOption.OperationCallbackUri = new Uri("<uri_endpoint>");

TransferCallToParticipantResult result = await callConnection.TransferCallToParticipantAsync(transferOption);

O diagrama de sequência mostra o fluxo esperado quando seu aplicativo faz uma chamada de saída e, em seguida, transfere-a para outro ponto de extremidade.

Diagrama de sequência para fazer uma chamada 1:1 e, em seguida, transferi-la.

Adicionar um participante a uma chamada

Você pode adicionar um participante (usuário ou número de telefone dos Serviços de Comunicação) a uma chamada existente. Ao adicionar um número de telefone, é obrigatório fornecer um identificador de chamada. Este ID de chamada é mostrado na notificação de chamada para o participante que está sendo adicionado.

// Add user
var addThisPerson = new CallInvite(new CommunicationUserIdentifier("<user_id>"));
// add custom calling context
addThisPerson.CustomCallingContext.AddVoip("myHeader", "myValue");
AddParticipantsResult result = await callConnection.AddParticipantAsync(addThisPerson);

// Add PSTN user
var callerIdNumber = new PhoneNumberIdentifier("+16044561234"); // This is the Azure Communication Services provisioned phone number for the caller
var addThisPerson = new CallInvite(new PhoneNumberIdentifier("+16041234567"), callerIdNumber);
// add custom calling context
addThisPerson.CustomCallingContext.AddSipUui("value");
addThisPerson.CustomCallingContext.AddSipX("header1", "customSipHeaderValue1");

// Use option bag to set optional parameters
var addParticipantOptions = new AddParticipantOptions(new CallInvite(addThisPerson))
{
    InvitationTimeoutInSeconds = 60,
    OperationContext = "operationContext",
    OperationCallbackUri = new Uri("uri_endpoint"); // Sending event to a non-default endpoint.
};

AddParticipantsResult result = await callConnection.AddParticipantAsync(addParticipantOptions); 

Para adicionar um usuário dos Serviços de Comunicação, forneça um CommunicationUserIdentifier em vez de PhoneNumberIdentifier. A identificação do chamador não é obrigatória neste caso.

AddParticipant publica um AddParticipantSucceeded ou AddParticipantFailed evento, juntamente com um ParticipantUpdated fornecimento da lista mais recente de participantes na chamada.

Diagrama de sequência para adicionar um participante à chamada.

Cancelar um pedido de adicionar participante

// add a participant
var addThisPerson = new CallInvite(new CommunicationUserIdentifier("<user_id>"));
var addParticipantResponse = await callConnection.AddParticipantAsync(addThisPerson);

// cancel the request with optional parameters
var cancelAddParticipantOperationOptions = new CancelAddParticipantOperationOptions(addParticipantResponse.Value.InvitationId)
{
    OperationContext = "operationContext",
    OperationCallbackUri = new Uri("uri_endpoint"); // Sending event to a non-default endpoint.
}
await callConnection.CancelAddParticipantOperationAsync(cancelAddParticipantOperationOptions);

Remover um participante de uma chamada

var removeThisUser = new CommunicationUserIdentifier("<user_id>"); 

// remove a participant from the call with optional parameters
var removeParticipantOptions = new RemoveParticipantOptions(removeThisUser)
{
    OperationContext = "operationContext",
    OperationCallbackUri = new Uri("uri_endpoint"); // Sending event to a non-default endpoint.
}

RemoveParticipantsResult result = await callConnection.RemoveParticipantAsync(removeParticipantOptions);

RemoveParticipant publicará um RemoveParticipantSucceeded evento OR RemoveParticipantFailed , juntamente com um ParticipantUpdated evento com a lista mais recente de participantes na chamada. O participante removido é omitido da lista.
Diagrama de sequência para remover um participante da chamada.

Desligue uma chamada

A ação Desligar pode ser usada para remover seu aplicativo da chamada ou para encerrar uma chamada de grupo definindo o parâmetro forEveryone como true. Para uma chamada 1:1, desligar encerra a chamada com o outro participante por padrão.

_ = await callConnection.HangUpAsync(forEveryone: true); 

O evento CallDisconnected é publicado assim que a ação de travamento for concluída com êxito.

Obter informações sobre um participante da chamada

CallParticipant participantInfo = await callConnection.GetParticipantAsync(new CommunicationUserIdentifier("<user_id>"));

Obter informações sobre todos os participantes da chamada

List<CallParticipant> participantList = (await callConnection.GetParticipantsAsync()).Value.ToList(); 

Obter as informações mais recentes sobre uma chamada

CallConnectionProperties callConnectionProperties = await callConnection.GetCallConnectionPropertiesAsync();