通话自动化使用 REST API 接口来接收操作请求,并提供响应以告知请求是否已成功提交。 由于调用的异步性质,大多数操作在成功完成或失败时会触发相应的事件。 本文介绍用于指导电话操作的动作,例如CreateCall、Transfer、Redirect,以及参与者管理。 示例代码演示如何调用特定操作。 序列图描述调用作后预期的事件。 此图可帮助你可视化如何使用呼叫自动化对服务应用程序进行编程。
呼叫自动化支持其他操作来管理呼叫媒体和录制,这些功能都有单独的文章。
Prerequisites
- 介绍操作事件编程模型和事件回调的通话自动化概念指南。
- 了解本文中使用的用户标识符。
CommunicationUserIdentifierPhoneNumberIdentifier
对于所有代码示例, client 是 CallAutomationClient 可以创建的对象,如下所示。 此外,callConnection是你从CallConnection或Answer响应中获取的CreateCall对象。 还可以从应用程序收到的回调事件中获取它。
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>")
发起传出通话
可以向通信服务用户或电话号码(公用电话号码或 Azure 通信服务拥有的电话号码)发起一对一或群组通话。
呼叫公用电话交换网 (PSTN) 终端时,还需提供一个电话号码,该号码用于作为源来电 ID,并作为拨打目标 PSTN 终端时的呼叫通知进行显示。
若要向 Azure 通信服务用户发出调用,需要提供对象 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 对象,可用于在连接后对此调用执行进一步操作。 接听电话后,以下两个事件将发布到先前提供的回调终结点:
如果调用失败,则会收到一个 CallDisconnected 事件和一个 CreateCallFailed 包含错误代码的事件,以便进一步进行故障排除。 有关错误代码的详细信息,请参阅 调用端响应代码疑难解答。
连接到通话
连接操作使您的服务能够与正在进行的通话建立连接,并在通话上执行操作。 此功能在管理会议室通话时非常有用,或者当客户端应用程序启动一对一或群组通话时(不包括呼叫自动化)也同样适用。 使用属性 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:包含通话中参与者的最新列表。
在成功连接后的任何时刻,如果服务与此调用断开连接,则你会收到 CallDisconnected 事件的通知。 未能在第一位置连接到调用会导致 ConnectFailed 事件。
接听来电
订阅接收资源的 传入呼叫通知 后,可以接听传入呼叫。 接听呼叫时,需要提供回调 URL。 Azure 通信服务会发布有关此 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:包含通话中参与者的最新列表。
如果回答操作失败,您将收到带有错误代码的事件,以进一步进行故障排除。 有关错误代码的详细信息,请参阅 调用端响应代码疑难解答。
拒绝通话
可以拒绝传入呼叫。 拒绝的原因是 None, Busy或 Forbidden。 如果未提供任何内容,则默认值为 None。
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,
)
不会针对重定向发布任何事件。 如果目标是 Azure 通信服务用户或资源拥有的电话号码,则会生成一个新 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);
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,
operation_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("<target_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: "<target_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 = CommunicationUserIdentifier("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,
operation_context="Your context",
operationCallbackUrl="<url_endpoint>"
)
# Transfer to PSTN user
transfer_destination = PhoneNumberIdentifier("<target_phoneNumber>")
transferee = PhoneNumberIdentifier("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,
operation_context="Your context",
operationCallbackUrl="<url_endpoint>"
)
序列图显示了当应用程序发起出站通话,然后将其转接到另一个终结点时的预期流程。
向通话添加参与者
可以将参与者(例如 Azure 通信服务用户或电话号码)添加到现有呼叫。 添加电话号码时,必须提供呼叫方 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,
operation_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,
operation_context="Your context",
operationCallbackUrl="<url_endpoint>",
source_caller_id_number=caller_id_number
)
若要添加 Azure 通信服务用户,请提供 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, operation_context="Your context", operationCallbackUrl="<url_endpoint>")
将参与者从一个通话转移到另外一个通话
使用 Azure 通信服务呼叫自动化 SDK,可以使用 MoveParticipants API 将参与者从一个正在进行的调用移动到另一个调用中。 这可实现动态路由和灵活的呼叫业务流程-在将翻译器移动到医生-患者呼叫或将客户从大厅呼叫转移到活动支持呼叫等方案中很常见。
示例方案:
var targetParticipant = new CommunicationUserIdentifier("<user_id>");
// CallConnectionId for the call that you want to move the participant from
var fromCallId = "<callConnectionId>";
// Move a participant from another call to current call with optional parameters
var moveParticipantsOptions = new MoveParticipantOptions(
new List<CommunicationIdentifier> { targetParticipant },
fromCallId)
{
OperationContext = "operationContext",
OperationCallbackUri = new Uri("uri_endpoint") // Sending event to a non-default endpoint.
};
MoveParticipantsResult result = await callConnection.MoveParticipantsAsync(moveParticipantsOptions);
List<CommunicationIdentifier> targetParticipants = new ArrayList<>(
Arrays.asList(new CommunicationUserIdentifier("<user_id>"))
);
String fromCallId = "<callConnectionId>";
MoveParticipantsOptions moveParticipantsOptions = new MoveParticipantsOptions(targetParticipants, fromCallId)
.setOperationContext("<operation_context>")
.setOperationCallbackUrl("<url_endpoint>");
Response<MoveParticipantsResult> moveParticipantResultResponse =
callConnectionAsync.moveParticipantWithResponse(moveParticipantsOptions).block();
const targetParticipants = [{ communicationUserId: "<user_id>" }];
const fromCallId = "<callConnectionId>";
const moveParticipantResult = await callConnection.moveParticipant(
targetParticipants,
fromCallId,
{
operationCallbackUrl: "<url_endpoint>",
operationContext: "<operation_context>"
}
);
target = CommunicationUserIdentifier("<user_id>")
target_participants = [target]
from_call_id = "<call_connection_id>"
call_connection_client = call_automation_client.get_call_connection(
"<call_connection_id_from_ongoing_call>"
)
result = call_connection_client.move_participant(
target_participants,
from_call_id,
operation_context="Your context",
operationCallbackUrl="<url_endpoint>"
)
MoveParticipants 会将 MoveParticipantSucceeded 或 MoveParticipantFailed 事件发布到目标呼叫。
删除通话参与者
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, operation_context="Your context", operationCallbackUrl="<url_endpoint>")
RemoveParticipant发布RemoveParticipantSucceeded或RemoveParticipantFailed事件,并发布提供通话中参与者最新列表的ParticipantUpdated事件。 从列表中省略已删除的参与者。
挂断通话
可以使用hangUp操作,通过将forEveryone参数设置为true,来从调用中删除应用程序或终止组调用。 对于 1:1 呼叫, hangUp 默认终止与其他参与者的通话。
_ = 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 动作成功完成后,hangUp 事件被发布。
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()