通话自动化使用 REST API 接口来接收操作请求,并提供响应以告知请求是否已成功提交。 由于通话的异步性,大多数操作将在操作成功完成或失败时触发相应的事件。 本指南将介绍可用于操控通话的操作,例如 CreateCall、转接、重定向和管理参与者。 操作随附了有关如何调用所述操作的示例代码,以及描述调用操作后预期发生的事件的序列图。 这些图可帮助你直观地了解如何使用通话自动化对服务应用程序进行编程。
通话自动化支持使用其他各种操作来管理具有单独指南的通话媒体和录音。
作为先决条件,我们建议阅读以下文章以充分理解本指南:
- 介绍操作事件编程模型和事件回调的通话自动化概念指南。
- 了解本指南中使用的用户标识符,例如 CommunicationUserIdentifier 和 PhoneNumberIdentifier。
对于所有代码示例,client
是可以按示例所示创建的 CallAutomationClient 对象,callConnection
是从 Answer 或 CreateCall 响应中获取的 CallConnection 对象。 也可以从应用程序收到的回调事件中获取该对象。
var client = new CallAutomationClient("<resource_connection_string>");
CallAutomationClient client = new CallAutomationClientBuilder().connectionString("<resource_connection_string>").buildClient();
const client = new CallAutomationClient("<resource_connection_string>");
call_automation_client = CallAutomationClient.from_connection_string("<resource_connection_string>")
发起传出通话
可以向通信用户或电话号码(公共电话号码或通信服务拥有的号码)发起一对一通话或群组通话。
呼叫 PSTN 终结点时,还需要提供一个电话号码作为源呼叫方 ID,该号码将显示在发送到目标 PSTN 终结点的通话通知中。
若要向通信服务用户发起通话,需要提供 CommunicationUserIdentifier 对象而不是 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);
String callbackUri = "https://<myendpoint>/Events"; //the callback endpoint where you want to receive subsequent events
PhoneNumberIdentifier callerIdNumber = new PhoneNumberIdentifier("+18001234567"); // This is the Azure Communication Services provisioned phone number for the caller
CallInvite callInvite = new CallInvite(new PhoneNumberIdentifier("+16471234567"), callerIdNumber); // person to call
CreateCallResult response = client.createCall(callInvite, callbackUri).block();
const callInvite = {
targetParticipant: { phoneNumber: "+18008008800" }, // person to call
sourceCallIdNumber: { phoneNumber: "+18888888888" } // This is the Azure Communication Services provisioned phone number for the caller
};
const callbackUri = "https://<myendpoint>/Events"; // the callback endpoint where you want to receive subsequent events
const response = await client.createCall(callInvite, callbackUri);
callback_uri = "https://<myendpoint>/Events" # the callback endpoint where you want to receive subsequent events
caller_id_number = PhoneNumberIdentifier(
"+18001234567"
) # This is the Azure Communication Services provisioned phone number for the caller
call_invite = CallInvite(
target=PhoneNumberIdentifier("+16471234567"),
source_caller_id_number=caller_id_number,
)
call_connection_properties = client.create_call(call_invite, callback_uri)
发出包含电话号码的组呼叫时,必须向 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);
String callbackUri = "https://<myendpoint>/Events"; //the callback endpoint where you want to receive subsequent events
PhoneNumberIdentifier callerIdNumber = new PhoneNumberIdentifier("+18001234567"); // This is the Azure Communication Services provisioned phone number for the caller
List<CommunicationIdentifier> targets = new ArrayList<>(Arrays.asList(new PhoneNumberIdentifier("+16471234567"), new CommunicationUserIdentifier("<user_id_of_target>")));
CreateGroupCallOptions groupCallOptions = new CreateGroupCallOptions(targets, callbackUri);
groupCallOptions.setSourceCallIdNumber(callerIdNumber);
Response<CreateCallResult> response = client.createGroupCallWithResponse(createGroupCallOptions).block();
const callbackUri = "https://<myendpoint>/Events"; // the callback endpoint where you want to receive subsequent events
const participants = [
{ phoneNumber: "+18008008800" },
{ communicationUserId: "<user_id_of_target>" }, //user id looks like 8:a1b1c1-...
];
const createCallOptions = {
sourceCallIdNumber: { phoneNumber: "+18888888888" }, // This is the Azure Communication Services provisioned phone number for the caller
};
const response = await client.createGroupCall(participants, callbackUri, createCallOptions);
callback_uri = "https://<myendpoint>/Events" # the callback endpoint where you want to receive subsequent events
caller_id_number = PhoneNumberIdentifier(
"+18888888888"
) # This is the Azure Communication Services provisioned phone number for the caller
pstn_endpoint = PhoneNumberIdentifier("+18008008800")
voip_endpoint = CommunicationUserIdentifier(
"<user_id_of_target>"
) # user id looks like 8:a1b1c1-...
call_connection_properties = client.create_group_call(
target_participants=[voip_endpoint, pstn_endpoint],
callback_url=callback_uri,
source_caller_id_number=caller_id_number,
)
响应将提供 CallConnection 对象,在连接后你可以使用该对象对此通话执行进一步的操作。 接听电话后,以下两个事件将发布到先前提供的回调终结点:
CallConnected
事件,告知已与被呼叫方建立通话。
ParticipantsUpdated
事件,其中包含最新的通话参与者列表。

如果呼叫失败,你将收到 CallDisconnected
和 CreateCallFailed
事件以及错误代码,以便进一步的故障排除(有关错误代码的详细信息,请参阅此页面)。
连接到呼叫
连接操作使服务能够与正在进行的调用建立连接,并对其执行操作。 这可用于管理会议室呼叫,或者在客户端应用程序启动呼叫自动化不属于的 1:1 或组调用时。 连接使用 CallLocator 属性建立,可以是以下类型:ServerCallLocator、GroupCallLocator 和 RoomCallLocator。 在最初建立呼叫或创建会议室时,还可以找到这些 ID,并作为 CallStarted 事件的一部分发布。
若要连接到任何 1:1 或组调用,请使用 ServerCallLocator。 如果使用 GroupCallId 发起调用,也可以使用 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);
String callbackUri = "https://<myendpoint>/Events"; //the callback endpoint where you want to receive subsequent events
CallLocator serverCallLocator = new ServerCallLocator("<ServerCallId>");
ConnectCallResult response = client.connectCall(serverCallLocator, callbackUri).block();
const callbackUri = "https://<myendpoint>/Events"; // the callback endpoint where you want to receive subsequent events
const serverCallLocator = { kind: "serverCallLocator", id: "<serverCallId>" };
const response = await client.connectCall(serverCallLocator, callbackUri);
callback_uri = "https://<myendpoint>/Events" # the callback endpoint where you want to receive subsequent events
server_call_locator = ServerCallLocator("<server_call_id>")
call_connection_properties = client.connect_call(call_locator=server_call_locator, callback_url=callback_uri)
若要连接到会议室呼叫,请使用 RoomCallLocator 获取 RoomId。 了解有关会议室的更多信息以及如何使用呼叫自动化 API 来管理正在进行的会议室呼叫。
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);
String callbackUri = "https://<myendpoint>/Events"; //the callback endpoint where you want to receive subsequent events
CallLocator roomCallLocator = new RoomCallLocator("<RoomId>");
ConnectCallResult response = client.connectCall(roomCallLocator, callbackUri).block();
const roomCallLocator = { kind: "roomCallLocator", id: "<RoomId>" };
const callbackUri = "https://<myendpoint>/Events"; // the callback endpoint where you want to receive subsequent events
const response = await client.connectCall(roomCallLocator, callbackUri);
callback_uri = "https://<myendpoint>/Events" # the callback endpoint where you want to receive subsequent events
room_call_locator = RoomCallLocator("<room_id>")
call_connection_properties = client.connect_call(call_locator=room_call_locator, callback_url=callback_uri)
成功的响应将提供 CallConnection 对象,可以使用该对象对此通话执行进一步的操作。 以下两个事件将发布到先前提供的回调终结点:
CallConnected
事件,通知你已成功连接到呼叫。
ParticipantsUpdated
事件,其中包含最新的通话参与者列表。
在成功连接后的任何时间点,如果服务与此呼叫断开连接,将通过 CallDisconected 事件收到通知。 未能在第一位置连接到调用会导致 ConnectFailed 事件。

应答传入呼叫
在资源中订阅接收来电通知后,将接听一通来电。 接听电话时,需要提供回调 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;
String incomingCallContext = "<IncomingCallContext_From_IncomingCall_Event>";
String callbackUri = "https://<myendpoint>/Events";
AnswerCallOptions answerCallOptions = new AnswerCallOptions(incomingCallContext, callbackUri);
Response<AnswerCallResult> response = client.answerCallWithResponse(answerCallOptions).block();
const incomingCallContext = "<IncomingCallContext_From_IncomingCall_Event>";
const callbackUri = "https://<myendpoint>/Events";
const { callConnection } = await client.answerCall(incomingCallContext, callbackUri);
incoming_call_context = "<IncomingCallContext_From_IncomingCall_Event>"
callback_uri = "https://<myendpoint>/Events" # the callback endpoint where you want to receive subsequent events
call_connection_properties = client.answer_call(
incoming_call_context=incoming_call_context, callback_url=callback_uri
)
响应将提供 CallConnection 对象,在连接后你可以使用该对象对此通话执行进一步的操作。 接听电话后,以下两个事件将发布到先前提供的回调终结点:
CallConnected
事件,告知已与呼叫方建立通话。
ParticipantsUpdated
事件,其中包含最新的通话参与者列表。

如果接听操作失败,你将收到 AnswerFailed
事件以及错误代码,以便进一步的故障排除(有关错误代码的详细信息,请参阅此页面)。
拒绝通话
可以如下所示选择拒绝来电。 可以提供拒绝原因:无、忙碌或禁止。 如果未提供任何原因,则默认会选择“无”。
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>";
RejectCallOptions rejectCallOptions = new RejectCallOptions(incomingCallContext)
.setCallRejectReason(CallRejectReason.BUSY);
Response<Void> response = client.rejectCallWithResponse(rejectCallOptions).block();
const incomingCallContext = "<IncomingCallContext_From_IncomingCall_Event>";
const rejectOptions = {
callRejectReason: KnownCallRejectReason.Forbidden,
};
await client.rejectCall(incomingCallContext, rejectOptions);
incoming_call_context = "<IncomingCallContext_From_IncomingCall_Event>"
client.reject_call(
incoming_call_context=incoming_call_context,
call_reject_reason=CallRejectReason.FORBIDDEN,
)
不会针对拒绝操作发布任何事件。
重定向通话
可以选择将来电重定向到另一个终结点而不接听。 重定向通话后,应用程序将无法使用通话自动化来控制通话。
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);
String incomingCallContext = "<IncomingCallContext_From_IncomingCall_Event>";
CallInvite target = new CallInvite(new CommunicationUserIdentifier("<user_id_of_target>")); //user id looks like 8:a1b1c1-...
RedirectCallOptions redirectCallOptions = new RedirectCallOptions(incomingCallContext, target);
Response<Void> response = client.redirectCallWithResponse(redirectCallOptions).block();
const incomingCallContext = "<IncomingCallContext_From_IncomingCall_Event>";
const target = { targetParticipant: { communicationUserId: "<user_id_of_target>" } }; //user id looks like 8:a1b1c1-...
await client.redirectCall(incomingCallContext, target);
incoming_call_context = "<IncomingCallContext_From_IncomingCall_Event>"
call_invite = CallInvite(
CommunicationUserIdentifier("<user_id_of_target>")
) # user id looks like 8:a1b1c1-...
client.redirect_call(
incoming_call_context=incoming_call_context, target_participant=call_invite
)
若要将通话重定向到某个电话号码,请使用 PhoneNumberIdentifier 构造目标和呼叫者 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);
PhoneNumberIdentifier callerIdNumber = new PhoneNumberIdentifier("+16044561234"); // This is the Azure Communication Services provisioned phone number for the caller
CallInvite target = new CallInvite(new PhoneNumberIdentifier("+18001234567"), callerIdNumber);
const callerIdNumber = { phoneNumber: "+16044561234" };
const target = {
targetParticipant: { phoneNumber: "+16041234567" },
sourceCallIdNumber: callerIdNumber,
};
caller_id_number = PhoneNumberIdentifier(
"+18888888888"
) # This is the Azure Communication Services provisioned phone number for the caller
call_invite = CallInvite(
target=PhoneNumberIdentifier("+16471234567"),
source_caller_id_number=caller_id_number,
)
不会针对重定向发布任何事件。 如果目标是通信服务用户或资源拥有的电话号码,它将生成新的 IncomingCall 事件,其中的“to”字段设置为指定的目标。
转接通话参与者
当应用程序接听通话或向某个终结点发起出站通话时,该终结点可以转接到另一个目标终结点。 转接一对一通话会从该通话中删除你的应用程序,从而导致它无法使用通话自动化来控制通话。 对目标的呼叫邀请将显示要转移的终结点的调用方 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);
CommunicationIdentifier transferDestination = new CommunicationUserIdentifier("<user_id>");
TransferCallToParticipantOptions options = new TransferCallToParticipantOptions(transferDestination)
.setOperationContext("<operation_context>")
.setOperationCallbackUrl("<url_endpoint>"); // Sending event to a non-default endpoint.
// set customCallingContext
options.getCustomCallingContext().addVoip("voipHeaderName", "voipHeaderValue");
Response<TransferCallResult> transferResponse = callConnectionAsync.transferToParticipantCallWithResponse(options).block();
const transferDestination = { communicationUserId: "<user_id>" };
const options = { operationContext: "<Your_context>", operationCallbackUrl: "<url_endpoint>" };
// adding customCallingContext
const customCallingContext: CustomCallingContext = [];
customCallingContext.push({ kind: "voip", key: "customVoipHeader1", value: "customVoipHeaderValue1" })
options.customCallingContext = customCallingContext;
const result = await callConnection.transferCallToParticipant(transferDestination, options);
transfer_destination = CommunicationUserIdentifier("<user_id>")
call_connection_client = call_automation_client.get_call_connection("<call_connection_id_from_ongoing_call>")
# set custom context
voip_headers = {"customVoipHeader1", "customVoipHeaderValue1"}
result = call_connection_client.transfer_call_to_participant(
target_participant=transfer_destination,
voip_headers=voip_headers,
opration_context="Your context",
operationCallbackUrl="<url_endpoint>"
)
当应用程序应答组呼叫或将出站组呼叫置于终结点或将参与者添加到 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);
// Transfer User
CommunicationIdentifier transferDestination = new CommunicationUserIdentifier("<user_id>");
CommunicationIdentifier transferee = new CommunicationUserIdentifier("<transferee_user_id>");
TransferCallToParticipantOptions options = new TransferCallToParticipantOptions(transferDestination);
options.setTransferee(transferee);
options.setOperationContext("<Your_context>");
options.setOperationCallbackUrl("<url_endpoint>");
// set customCallingContext
options.getCustomCallingContext().addVoip("voipHeaderName", "voipHeaderValue");
Response<TransferCallResult> transferResponse = callConnectionAsync.transferToParticipantCallWithResponse(options).block();
// Transfer Pstn User
CommunicationIdentifier transferDestination = new PhoneNumberIdentifier("<taget_phoneNumber>");
CommunicationIdentifier transferee = new PhoneNumberIdentifier("<transferee_phoneNumber>");
TransferCallToParticipantOptions options = new TransferCallToParticipantOptions(transferDestination);
options.setTransferee(transferee);
options.setOperationContext("<Your_context>");
options.setOperationCallbackUrl("<url_endpoint>");
// set customCallingContext
options.getCustomCallingContext().addSipUui("UUIvalue");
options.getCustomCallingContext().addSipX("sipHeaderName", "value");
Response<TransferCallResult> transferResponse = callConnectionAsync.transferToParticipantCallWithResponse(options).block();
// Transfer User
const transferDestination = { communicationUserId: "<user_id>" };
const transferee = { communicationUserId: "<transferee_user_id>" };
const options = { transferee: transferee, operationContext: "<Your_context>", operationCallbackUrl: "<url_endpoint>" };
// adding customCallingContext
const customCallingContext: CustomCallingContext = [];
customContext.push({ kind: "voip", key: "customVoipHeader1", value: "customVoipHeaderValue1" })
options.customCallingContext = customCallingContext;
const result = await callConnection.transferCallToParticipant(transferDestination, options);
// Transfer pstn User
const transferDestination = { phoneNumber: "<taget_phoneNumber>" };
const transferee = { phoneNumber: "<transferee_phoneNumber>" };
const options = { transferee: transferee, operationContext: "<Your_context>", operationCallbackUrl: "<url_endpoint>" };
// adding customCallingContext
const customCallingContext: CustomCallingContext = [];
customContext.push({ kind: "sipuui", key: "", value: "uuivalue" });
customContext.push({ kind: "sipx", key: "headerName", value: "headerValue" })
options.customCallingContext = customCallingContext;
const result = await callConnection.transferCallToParticipant(transferDestination, options);
# Transfer to user
transfer_destination = CommunicationUserIdentifier("<user_id>")
transferee = CommnunicationUserIdentifer("transferee_user_id")
call_connection_client = call_automation_client.get_call_connection("<call_connection_id_from_ongoing_call>")
# create custom context
voip_headers = {"customVoipHeader1", "customVoipHeaderValue1"}
result = call_connection_client.transfer_call_to_participant(
target_participant=transfer_destination,
transferee=transferee,
voip_headers=voip_headers,
opration_context="Your context",
operationCallbackUrl="<url_endpoint>"
)
# Transfer to PSTN user
transfer_destination = PhoneNumberIdentifer("<target_phoneNumber>")
transferee = PhoneNumberIdentifer("transferee_phoneNumber")
# create custom context
sip_headers={}
sip_headers.add("X-MS-Custom-headerName", "headerValue")
sip_headers.add("User-To-User","uuivale")
call_connection_client = call_automation_client.get_call_connection("<call_connection_id_from_ongoing_call>")
result = call_connection_client.transfer_call_to_participant(
target_participant=transfer_destination,
transferee=transferee,
sip_headers=sip_headers,
opration_context="Your context",
operationCallbackUrl="<url_endpoint>"
)
序列图显示了当应用程序发起出站通话,然后将其转接到另一个终结点时的预期流程。

向通话添加参与者
可以将一个参与者(通信服务用户或电话号码)添加到现有通话。 添加电话号码时,必须提供呼叫方 ID。 此呼叫方 ID 将在通话通知中显示给要添加的参与者。
// 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);
// Add user
CallInvite callInvite = new CallInvite(new CommunicationUserIdentifier("<user_id>"));
// add custom calling context
callInvite.getCustomCallingContext().addVoip("voipHeaderName", "voipHeaderValue");
AddParticipantOptions addParticipantOptions = new AddParticipantOptions(callInvite)
.setOperationContext("<operation_context>")
.setOperationCallbackUrl("<url_endpoint>");
Response<AddParticipantResult> addParticipantResultResponse = callConnectionAsync.addParticipantWithResponse(addParticipantOptions).block();
// Add PSTN user
PhoneNumberIdentifier callerIdNumber = new PhoneNumberIdentifier("+16044561234"); // This is the Azure Communication Services provisioned phone number for the caller
CallInvite callInvite = new CallInvite(new PhoneNumberIdentifier("+16041234567"), callerIdNumber);
// add custom calling context
callInvite.getCustomCallingContext().addSipUui("value");
callInvite.getCustomCallingContext().addSipX("header1", "customSipHeaderValue1");
AddParticipantOptions addParticipantOptions = new AddParticipantOptions(callInvite)
.setOperationContext("<operation_context>")
.setOperationCallbackUrl("<url_endpoint>");
Response<AddParticipantResult> addParticipantResultResponse = callConnectionAsync.addParticipantWithResponse(addParticipantOptions).block();
// Add user
// add custom calling context
const customCallingContext: CustomCallingContext = [];
customContext.push({ kind: "voip", key: "voipHeaderName", value: "voipHeaderValue" })
const addThisPerson = {
targetParticipant: { communicationUserId: "<acs_user_id>" },
customCallingContext: customCallingContext,
};
const addParticipantResult = await callConnection.addParticipant(addThisPerson, {
operationCallbackUrl: "<url_endpoint>",
operationContext: "<operation_context>"
});
// Add PSTN user
const callerIdNumber = { phoneNumber: "+16044561234" }; // This is the Azure Communication Services provisioned phone number for the caller
// add custom calling context
const customCallingContext: CustomCallingContext = [];
customContext.push({ kind: "sipuui", key: "", value: "value" });
customContext.push({ kind: "sipx", key: "headerName", value: "headerValue" })
const addThisPerson = {
targetParticipant: { phoneNumber: "+16041234567" },
sourceCallIdNumber: callerIdNumber,
customCallingContext: customCallingContext,
};
const addParticipantResult = await callConnection.addParticipant(addThisPerson, {
operationCallbackUrl: "<url_endpoint>",
operationContext: "<operation_context>"
});
# Add user
voip_headers = {"voipHeaderName", "voipHeaderValue"}
target = CommunicationUserIdentifier("<acs_user_id>")
call_connection_client = call_automation_client.get_call_connection(
"<call_connection_id_from_ongoing_call>"
)
result = call_connection_client.add_participant(
target,
voip_headers=voip_headers,
opration_context="Your context",
operationCallbackUrl="<url_endpoint>"
)
# Add PSTN user
caller_id_number = PhoneNumberIdentifier(
"+18888888888"
) # This is the Azure Communication Services provisioned phone number for the caller
sip_headers = {}
sip_headers["User-To-User"] = "value"
sip_headers["X-MS-Custom-headerName"] = "headerValue"
target = PhoneNumberIdentifier("+18008008800"),
call_connection_client = call_automation_client.get_call_connection(
"<call_connection_id_from_ongoing_call>"
)
result = call_connection_client.add_participant(
target,
sip_headers=sip_headers,
opration_context="Your context",
operationCallbackUrl="<url_endpoint>",
source_caller_id_number=caller_id_number
)
若要添加通信服务用户,请提供 CommunicationUserIdentifier 而不是 PhoneNumberIdentifier。 在这种情况下,源呼叫方 ID 不是必需的。
AddParticipant 发布 AddParticipantSucceeded
或 AddParticipantFailed
事件,以及一个提供最新通话参与者列表的 ParticipantUpdated
。

取消添加参与者请求
// 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);
// Add user
CallInvite callInvite = new CallInvite(new CommunicationUserIdentifier("<user_id>"));
AddParticipantOperationOptions addParticipantOperationOptions = new AddParticipantOptions(callInvite);
Response<AddParticipantResult> addParticipantOperationResultResponse = callConnectionAsync.addParticipantWithResponse(addParticipantOptions).block();
// cancel the request
CancelAddParticipantOperationOptions cancelAddParticipantOperationOptions = new CancelAddParticipantOperationOptions(addParticipantResultResponse.invitationId)
.setOperationContext("<operation_context>")
.setOperationCallbackUrl("<url_endpoint>");
callConnectionAsync.cancelAddParticipantOperationWithResponse(cancelAddParticipantOperationOptions).block();
// Add user
const addThisPerson = {
targetParticipant: { communicationUserId: "<acs_user_id>" },
};
const { invitationId } = await callConnection.addParticipant(addThisPerson, {
operationCallbackUrl: "<url_endpoint>",
operationContext: "<operation_context>"
});
// cancel the request
await callConnection.cancelAddParticipantOperation(invitationId, {
operationCallbackUrl: "<url_endpoint>",
operationContext: "<operation_context>"
});
# Add user
target = CommunicationUserIdentifier("<acs_user_id>")
call_connection_client = call_automation_client.get_call_connection(
"<call_connection_id_from_ongoing_call>"
)
result = call_connection_client.add_participant(target)
# cancel the request
call_connection_client.cancel_add_participant_operation(result.invitation_id, opration_context="Your context", operationCallbackUrl="<url_endpoint>")
删除通话参与者
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);
CommunicationIdentifier removeThisUser = new CommunicationUserIdentifier("<user_id>");
RemoveParticipantOptions removeParticipantOptions = new RemoveParticipantOptions(removeThisUser)
.setOperationContext("<operation_context>")
.setOperationCallbackUrl("<url_endpoint>");
Response<RemoveParticipantResult> removeParticipantResultResponse = callConnectionAsync.removeParticipantWithResponse(removeParticipantOptions).block();
const removeThisUser = { communicationUserId: "<user_id>" };
const removeParticipantResult = await callConnection.removeParticipant(removeThisUser, {
operationCallbackUrl: "<url_endpoint>",
operationContext: "<operation_context>"
});
remove_this_user = CommunicationUserIdentifier("<user_id>")
call_connection_client = call_automation_client.get_call_connection(
"<call_connection_id_from_ongoing_call>"
)
result = call_connection_client.remove_participant(remove_this_user, opration_context="Your context", operationCallbackUrl="<url_endpoint>")
RemoveParticipant 发布 RemoveParticipantSucceeded
或 RemoveParticipantFailed
事件,以及一个提供最新通话参与者列表的 ParticipantUpdated
事件。 从列表中省略已删除的参与者。

挂断通话
使用挂断操作可以从通话中删除应用程序,或通过将 forEveryone 参数设置为 true 来终止群组通话。 对于一对一通话,挂断操作默认将终止与另一方的通话。
_ = await callConnection.HangUpAsync(forEveryone: true);
Response<Void> response = callConnectionAsync.hangUpWithResponse(true).block();
await callConnection.hangUp(true);
call_connection_client.hang_up(is_for_everyone=True)
挂断操作成功完成后,将发布 CallDisconnected 事件。
CallParticipant participantInfo = await callConnection.GetParticipantAsync(new CommunicationUserIdentifier("<user_id>"));
CallParticipant participantInfo = callConnection.getParticipant(new CommunicationUserIdentifier("<user_id>")).block();
const participantInfo = await callConnection.getParticipant({ communicationUserId: "<user_id>" });
participant_info = call_connection_client.get_participant(
CommunicationUserIdentifier("<user_id>")
)
List<CallParticipant> participantList = (await callConnection.GetParticipantsAsync()).Value.ToList();
List<CallParticipant> participantList = Objects.requireNonNull(callConnection.listParticipants().block()).getValues();
const participantList = await callConnection.listParticipants();
participant_list = call_connection_client.list_participants()
获取有关通话的最新信息
CallConnectionProperties callConnectionProperties = await callConnection.GetCallConnectionPropertiesAsync();
CallConnectionProperties callConnectionProperties = callConnection.getCallProperties().block();
const callConnectionProperties = await callConnection.getCallConnectionProperties();
call_connection_properties = call_connection_client.get_call_properties()