你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

如何使用通话自动化操控通话

通话自动化使用 REST API 接口来接收操作请求,并提供响应以告知请求是否已成功提交。 由于通话的异步性,大多数操作将在操作成功完成或失败时触发相应的事件。 本指南将介绍可用于操控通话的操作,例如 CreateCall、转接、重定向和管理参与者。 操作随附了有关如何调用所述操作的示例代码,以及描述调用操作后预期发生的事件的序列图。 这些关系图可帮助你可视化如何使用呼叫自动化对服务应用程序进行编程。

呼叫自动化支持各种其他操作来管理具有单独指南的呼叫媒体和录制。

注意

呼叫自动化目前不支持 会议室 呼叫。

作为先决条件,建议阅读以下文章,充分利用本指南:

  1. 介绍操作事件编程模型和事件回调的通话自动化概念指南
  2. 了解本指南中使用的用户标识符,例如 CommunicationUserIdentifier 和 PhoneNumberIdentifier。

对于所有代码示例,client 是可以按示例所示创建的 CallAutomationClient 对象,callConnection 是从 Answer 或 CreateCall 响应中获取的 CallConnection 对象。 也可以从应用程序收到的回调事件中获取该对象。

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

发起传出通话

可以向通信用户或电话号码(公共电话号码或通信服务拥有的号码)发起一对一通话或群组通话。 呼叫 PSTN 终结点时,还需要提供一个电话号码,该电话号码用作源呼叫方 ID,并在呼叫通知中向目标 PSTN 终结点显示。 若要向通信服务用户发出调用,需要提供 CommunicationUserIdentifier 对象,而不是 电话NumberIdentifier。

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);

发出包含电话号码的组呼叫时,必须向 PSTN 终结点提供用作呼叫方 ID 号码的电话号码。

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);

响应将提供 CallConnection 对象,在连接后你可以使用该对象对此通话执行进一步的操作。 接听呼叫后,会将两个事件发布到前面提供的回调终结点:

  1. CallConnected 事件,告知已与被呼叫方建立通话。
  2. ParticipantsUpdated 事件,其中包含最新的通话参与者列表。 Sequence diagram for placing an outbound call.

应答传入呼叫

订阅接收 资源的传入呼叫通知 后,将接听传入呼叫。 接听电话时,需要提供回调 URL。 通信服务发布有关此 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; 

响应将提供 CallConnection 对象,在连接后你可以使用该对象对此通话执行进一步的操作。 接听呼叫后,会将两个事件发布到前面提供的回调终结点:

  1. CallConnected 事件,告知已与呼叫方建立通话。
  2. ParticipantsUpdated 事件,其中包含最新的通话参与者列表。

Sequence diagram for answering an incoming call.

拒绝通话

可以如下所示选择拒绝来电。 可以提供拒绝原因:无、忙碌或禁止。 如果未提供任何原因,则默认会选择“无”。

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

不会针对拒绝操作发布任何事件。

重定向通话

可以选择将传入呼叫重定向到另一终结点,而无需应答。 重定向呼叫可消除应用程序使用呼叫自动化控制呼叫的能力。

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); 

若要将呼叫重定向到电话号码,请使用 电话NumberIdentifier 构造目标和呼叫方 ID。

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);

不会针对重定向发布任何事件。 如果目标是通信服务用户或资源拥有的电话号码,则会生成一个新的 IncomingCall 事件,并将“to”字段设置为指定的目标。

在通话中转移参与者

当应用程序接听通话或向某个终结点发起出站通话时,该终结点可以转接到另一个目标终结点。 转移 1:1 调用会从呼叫中删除应用程序,从而删除其使用呼叫自动化控制呼叫的能力。 对目标的呼叫邀请将显示要转移的终结点的调用方 ID。 不支持提供自定义调用方 ID。

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);

当应用程序应答组呼叫或将出站组呼叫置于终结点或将参与者添加到 1:1 呼叫时,可将终结点从呼叫转移到另一个目标终结点,但呼叫自动化终结点除外。 在群组呼叫中转移参与者会删除从呼叫转移的终结点。 对目标的呼叫邀请将显示要转移的终结点的调用方 ID。 不支持提供自定义调用方 ID。

// 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);

序列图显示应用程序放置出站调用时的预期流,然后将其传输到另一终结点。

Sequence diagram for placing a 1:1 call and then transferring it.

向通话添加参与者

可以将参与者(通信服务用户或电话号码)添加到现有呼叫。 添加电话号码时,必须提供来电显示。 此来电显示给要添加的参与者的呼叫通知。

// 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); 

若要添加通信服务用户,请提供 CommunicationUserIdentifier 而不是 PhoneNumberIdentifier。 在这种情况下,调用方 ID 不是必需的。

AddParticipant 发布或AddParticipantSucceededAddParticipantFailed事件,以及ParticipantUpdated提供通话中参与者的最新列表。

Sequence diagram for adding a participant to the call.

取消添加参与者请求

// 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);

删除通话参与者

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 将发布或RemoveParticipantSucceededRemoveParticipantFailed事件,以及提供ParticipantUpdated通话中参与者的最新列表的事件。 从列表中省略已删除的参与者。
Sequence diagram for removing a participant from the call.

挂断通话

使用挂断操作可以从通话中删除应用程序,或通过将 forEveryone 参数设置为 true 来终止群组通话。 对于 1:1 呼叫,默认情况下,挂起将终止与其他参与者的通话。

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

挂断操作成功完成后,将发布 CallDisconnected 事件。

获取有关某个通话参与者的信息

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

获取有关所有通话参与者的信息

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

获取有关通话的最新信息

CallConnectionProperties callConnectionProperties = await callConnection.GetCallConnectionPropertiesAsync();