Skip to content

Commit 34b5ac7

Browse files
authored
Merge pull request #217517 from ashwinder/ci-qs
update redirect call quickstart
2 parents 1be7f4c + ec48a3f commit 34b5ac7

File tree

3 files changed

+155
-89
lines changed

3 files changed

+155
-89
lines changed

articles/communication-services/how-tos/call-automation-sdk/includes/redirect-inbound-telephony-calls-csharp.md

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,30 +14,42 @@ ms.author: askaur
1414
## Prerequisites
1515

1616
- An Azure account with an active subscription.
17-
- A deployed [Communication Service resource](../../../quickstarts/create-communication-resource.md) and valid Connection String
18-
- [Acquire a PSTN phone number from the Communication Service resource](../../../quickstarts/telephony/get-phone-number.md).
17+
- A deployed [Communication Service resource](../../../quickstarts/create-communication-resource.md) and valid connection string found by selecting Keys in left side menu on Azure portal.
18+
- [Acquire a PSTN phone number from the Communication Service resource](../../../quickstarts/telephony/get-phone-number.md). Note the phone number you acquired to use in this quickstart.
1919
- The latest [.NET library](https://dotnet.microsoft.com/download/dotnet-core) for your operating system.
20-
- A [web service application](/aspnet/core/web-api) to handle web hook callback events.
21-
- Optional: [NGROK application](https://ngrok.com/) to proxy HTTP/S requests to a local development machine.
22-
- The [ARMClient application](https://github.com/projectkudu/ARMClient), used to configure the Event Grid subscription.
23-
- Obtain the NuGet package from the [Azure SDK Dev Feed](https://github.com/Azure/azure-sdk-for-net/blob/main/CONTRIBUTING.md#nuget-package-dev-feed)
24-
- [An Event Grid subscription for Incoming Call](../../../how-tos/call-automation-sdk/subscribe-to-incoming-call.md)
2520

2621
## Create a new C# application
2722

2823
In the console window of your operating system, use the `dotnet` command to create a new web application with the name 'IncomingCallRedirect':
2924

3025
```console
31-
dotnet new web -n IncomingCallSample
26+
dotnet new web -n IncomingCallRedirect
3227
```
3328

3429
## Install the NuGet package
3530

3631
During the preview phase, the NuGet package can be obtained by configuring your package manager to use the [Azure SDK Dev Feed](https://github.com/Azure/azure-sdk-for-net/blob/main/CONTRIBUTING.md#nuget-package-dev-feed)
3732

33+
Install the NuGet packages: [Azure.Communication.CallAutomation](https://dev.azure.com/azure-sdk/public/_artifacts/feed/azure-sdk-for-net/NuGet/Azure.Communication.CallAutomation/versions/) and [Azure.Messaging.EventGrid](https://dev.azure.com/azure-sdk/public/_artifacts/feed/azure-sdk-for-net/NuGet/Azure.Messaging.EventGrid/versions/) to your project.
34+
```console
35+
dotnet add <path-to-project> package Azure.Communication.CallAutomation --prerelease
36+
dotnet add <path-to-project> package Azure.Messaging.EventGrid --prerelease
37+
```
38+
39+
## Set up a public URI for the local application
40+
In this quick-start, you'll use Ngrok tool to project a public URI to the local port so that your local application can be visited by the internet. The public URI is needed to receive the Event Grid IncomingCall event and Call Automation events using webhooks.
41+
42+
First, determine the port of the .NET application. Minimal API dynamically allocates a port for the project at the time of creation. Find out the http port in <PROJECT_ROOT>\Properties\launchSettings.json.
43+
![Screenshot of demo application's launchsetting.json file.](../../../quickstarts/voice-video-calling/media/call-automation/dotnet-application-port.jpg)
44+
45+
Then, install Ngrok and run Ngrok with the following command: ngrok http <replace_with_port>. This command will create a public URI like https://ff2f-75-155-253-232.ngrok.io/, and it is your Ngrok Fully Qualified Domain Name(Ngrok_FQDN). Keep Ngrok running while following the rest of this quick-start.
46+
3847
## Configure Program.cs to redirect the call
3948

4049
Using the minimal API feature in .NET 6, we can easily add an HTTP POST map and redirect the call.
50+
51+
In this code snippet, /api/incomingCall is the default route that will be used to listen for incoming calls. At a later step, you'll register this url with Event Grid. Since Event Grid requires you to prove ownership of your Webhook endpoint before it starts delivering events to that endpoint, the code sample also handles this one time validation by processing SubscriptionValidationEvent. This requirement prevents a malicious user from flooding your endpoint with events. For more information, see this [guide](../../../../event-grid/webhook-event-delivery.md).
52+
4153
```csharp
4254
using Azure.Communication;
4355
using Azure.Communication.CallAutomation;
@@ -47,7 +59,7 @@ using System.Text.Json;
4759

4860
var builder = WebApplication.CreateBuilder(args);
4961

50-
var client = new CallAutomationClient(builder.Configuration["ACS:ConnectionString"]);
62+
var client = new CallAutomationClient("<resource_connection_string_obtained_in_pre-requisites>");
5163

5264
var app = builder.Build();
5365

@@ -56,14 +68,31 @@ app.MapPost("/api/incomingCall", async (
5668
{
5769
foreach (var eventGridEvent in eventGridEvents)
5870
{
59-
// Webhook validation is assumed to be complete
71+
if (eventGridEvent.TryGetSystemEventData(out object eventData))
72+
{
73+
// Handle the subscription validation event.
74+
if (eventData is SubscriptionValidationEventData subscriptionValidationEventData)
75+
{
76+
var responseData = new SubscriptionValidationResponse
77+
{
78+
ValidationResponse = subscriptionValidationEventData.ValidationCode
79+
};
80+
return Results.Ok(responseData);
81+
}
82+
}
83+
6084
var jsonObject = JsonNode.Parse(eventGridEvent.Data).AsObject();
6185
var incomingCallContext = (string)jsonObject["incomingCallContext"];
62-
await client.RedirectCallAsync(incomingCallContext, new CommunicationUserIdentifier("<INSERT_ACS_ID>"));
86+
await client.RedirectCallAsync(incomingCallContext, new PhoneNumberIdentifier("<phone_number_to_redirect_call_to")); //this can be any phone number you have access to and should be provided in format +(countrycode)(phonenumber)
6387
}
6488

6589
return Results.Ok();
6690
});
6791

6892
app.Run();
6993
```
94+
Update the placeholders in the code above for connection string and phone number to redirect to.
95+
96+
## Run the app
97+
Open Your_Project_Name.csproj file in your project with Visual Studio, and then select Run button or press F5 on your keyboard.
98+

articles/communication-services/how-tos/call-automation-sdk/includes/redirect-inbound-telephony-calls-java.md

Lines changed: 102 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -14,57 +14,48 @@ ms.author: askaur
1414
## Prerequisites
1515

1616
- An Azure account with an active subscription.
17-
- A deployed [Communication Service resource](../../../quickstarts/create-communication-resource.md) and valid Connection String
18-
- [Acquire a PSTN phone number from the Communication Service resource](../../../quickstarts/telephony/get-phone-number.md).
19-
- Optional: [NGROK application](https://ngrok.com/) to proxy HTTP/S requests to a local development machine.
17+
- A deployed [Communication Service resource](../../../quickstarts/create-communication-resource.md) and valid connection string found by selecting Keys in left side menu on Azure portal.
18+
- [Acquire a PSTN phone number from the Communication Service resource](../../../quickstarts/telephony/get-phone-number.md). Note the phone number you acquired to use in this quickstart.
2019
- [Java Development Kit (JDK)](/java/azure/jdk/?preserve-view=true&view=azure-java-stable) version 8 or above.
2120
- [Apache Maven](https://maven.apache.org/download.cgi).
22-
- [An Event Grid subscription for Incoming Call](../../../how-tos/call-automation-sdk/subscribe-to-incoming-call.md)
2321

24-
## Create a new Java application
22+
## Create a new Java Spring application
2523

26-
Open your terminal or command window and navigate to the directory where you would like to create your Java application. Run the command below to generate the Java project from the maven-archetype-quickstart template.
27-
```console
28-
mvn archetype:generate -DgroupId=com.communication.quickstart -DartifactId=communication-quickstart -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4 -DinteractiveMode=false
29-
```
24+
Configure the [Spring Initializr](https://start.spring.io/) to create a new Java Spring application.
3025

31-
The command above creates a directory with the same name as `artifactId` argument. Under this directory, `src/main/java` directory contains the project source code, `src/test/java` directory contains the test source.
26+
1. Set the Project to be a Maven Project.
27+
2. Leave the rest as default unless you want to have your own customization.
28+
3. Add Spring Web to Dependencies section.
29+
4. Generate the application and it will be downloaded as a zip file. Unzip the file and start coding.
3230

33-
You'll notice that the 'generate' step created a directory with the same name as the artifactId. Under this directory, `src/main/java` directory contains source code, `src/test/java` directory contains tests, and `pom.xml` file is the project's Project Object Model, or POM.
31+
## Install the Maven package
3432

35-
Update your application's POM file to use Java 8 or higher.
36-
```xml
37-
<properties>
38-
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
39-
<maven.compiler.source>1.8</maven.compiler.source>
40-
<maven.compiler.target>1.8</maven.compiler.target>
41-
</properties>
42-
```
33+
**Configure Azure Artifacts development feed:**
4334

44-
## Configure Azure SDK Dev Feed
35+
Since the Call Automation SDK version used in this QuickStart isn't yet available in Maven Central Repository, we need to configure an Azure Artifacts development feed, which contains the latest version of the Call Automation SDK.
4536

46-
Since the Call Automation SDK version used in this quick start isn't yet available in Maven Central Repository, we need to add an Azure Artifacts development feed, which contains the latest version of the Call Automation SDK.
37+
Follow the instruction [here](https://dev.azure.com/azure-sdk/public/_artifacts/feed/azure-sdk-for-java/connect/maven) for adding [azure-sdk-for-java](https://dev.azure.com/azure-sdk/public/_artifacts/feed/azure-sdk-for-java) feed to your POM file.
4738

48-
Add the [azure-sdk-for-java feed](https://dev.azure.com/azure-sdk/public/_artifacts/feed/azure-sdk-for-java) to your `pom.xml`. Follow the instructions after clicking the “Connect to Feed” button.
39+
**Add Call Automation package references:**
4940

50-
## Add package references
41+
*azure-communication-callautomation* - Azure Communication Services Call Automation SDK package is retrieved from the Azure SDK Dev Feed configured above.
5142

52-
In your POM file, add the following dependencies for the project.
43+
Look for the recently published version from [here](https://dev.azure.com/azure-sdk/public/_artifacts/feed/azure-sdk-for-java/maven/com.azure%2Fazure-communication-callautomation/versions)
5344

54-
**azure-communication-callautomation**
45+
And then add it to your POM file like this (using version 1.0.0-alpha.20221101.1 as example)
5546

56-
Azure Communication Services Call Automation SDK package is retrieved from the Azure SDK Dev Feed configured above.
5747
```xml
5848
<dependency>
59-
<groupId>com.azure</groupId>
60-
<artifactId>azure-communication-callautomation</artifactId>
61-
<version>1.0.0-alpha.20220928.2</version>
49+
<groupId>com.azure</groupId>
50+
<artifactId>azure-communication-callautomation</artifactId>
51+
<version>1.0.0-alpha.20221101.1</version>
6252
</dependency>
6353
```
6454

65-
**azure-messaging-eventgrid**
55+
**Add other packages’ references:**
56+
57+
*azure-messaging-eventgrid* - Azure Event Grid SDK package: [com.azure : azure-messaging-eventgrid](https://search.maven.org/artifact/com.azure/azure-messaging-eventgrid). Data types from this package are used to handle Call Automation IncomingCall event received from the Event Grid.
6658

67-
Azure Event Grid SDK package: [com.azure : azure-messaging-eventgrid](https://search.maven.org/artifact/com.azure/azure-messaging-eventgrid). Data types from this package are used to handle Call Automation IncomingCall event received from the Event Grid.
6859
```xml
6960
<dependency>
7061
<groupId>com.azure</groupId>
@@ -73,20 +64,8 @@ Azure Event Grid SDK package: [com.azure : azure-messaging-eventgrid](https://se
7364
</dependency>
7465
```
7566

76-
**spark-core**
77-
78-
Spark framework: com.sparkjava : spark-core. We’ll use this micro-framework to create a webhook (web api endpoint) to handle Event Grid events. You can use any framework to create a web api.
79-
```xml
80-
<dependency>
81-
<groupId>com.sparkjava</groupId>
82-
<artifactId>spark-core</artifactId>
83-
<version>2.9.4</version>
84-
</dependency>
85-
```
86-
87-
**gson**
67+
*gson* - Google Gson package: [com.google.code.gson : gson](https://search.maven.org/artifact/com.google.code.gson/gson) is a serialization/deserialization library to handle conversion between Java Objects and JSON.
8868

89-
Google Gson package: [com.google.code.gson : gson](https://search.maven.org/artifact/com.sparkjava/spark-core). A serialization/deserialization library to handle conversion between Java Objects and JSON.
9069
```xml
9170
<dependency>
9271
<groupId>com.google.code.gson</groupId>
@@ -95,44 +74,91 @@ Google Gson package: [com.google.code.gson : gson](https://search.maven.org/arti
9574
</dependency>
9675
```
9776

77+
## Set up a public URI for the local application
78+
79+
In this quick-start, you'll use [Ngrok tool](https://ngrok.com/) to project a public URI to the local port so that your local application can be visited by the internet. The public URI is needed to receive the Event Grid `IncomingCall` event and Call Automation events using webhooks.
80+
81+
First, determine the port of your java application. `8080` is the default endpoint of a spring boot application.
82+
83+
Then, [install Ngrok](https://ngrok.com/download) and run Ngrok with the following command: `ngrok http <port>`. This command will create a public URI like `https://ff2f-75-155-253-232.ngrok.io/`, and it is your Ngrok Fully Qualified Domain Name(Ngrok_FQDN). Keep Ngrok running while following the rest of this quick-start.
84+
9885
## Redirect incoming call
9986

100-
In your editor of choice, open App.java file and update it with the following code to create an endpoint to receive IncomingCall events and redirect calls to another user.
101-
```java
102-
package com.communication.quickstart;
87+
In your project folder, create a Controller.java file and update it to handle incoming calls.
10388

104-
import java.util.List;
105-
import com.azure.communication.callautomation.*;
106-
import com.azure.communication.common.CommunicationUserIdentifier;
107-
import com.azure.messaging.eventgrid.*;
108-
import com.google.gson.*;
109-
import static spark.Spark.*;
110-
111-
public class App
112-
{
113-
public static void main( String[] args )
114-
{
115-
String connectionString = "<acsConnectionString>";
116-
CallAutomationClient client = new CallAutomationClientBuilder().connectionString(connectionString).buildClient(false);
117-
118-
post("/api/incomingCall", (request, response) -> {
119-
List<EventGridEvent> eventGridEvents = EventGridEvent.fromString(request.body());
120-
121-
for (EventGridEvent eventGridEvent : eventGridEvents) {
122-
123-
// Webhook validation is assumed to be complete
124-
JsonObject data = new Gson().fromJson(eventGridEvent.getData().toString(), JsonObject.class);
125-
126-
String incomingCallContext = data.get("incomingCallContext").getAsString();
127-
client.redirectCall(incomingCallContext, new CommunicationUserIdentifier("<userId>"));
128-
}
89+
In this code snippet, /api/incomingCall is the default route that will be used to listen for incoming calls. At a later step, we'll register this url with Event Grid. Since Event Grid requires you to prove ownership of your Webhook endpoint before it starts delivering events to that endpoint, the code sample also handles this one time validation by processing SubscriptionValidationEvent. This requirement prevents a malicious user from flooding your endpoint with events. For more information, see this [guide](../../../../event-grid/webhook-event-delivery.md).
90+
91+
```Java
92+
package com.example.demo;
12993

130-
return "";
131-
});
94+
import com.azure.communication.callautomation.*;
95+
import com.azure.communication.callautomation.models.*;
96+
import com.azure.communication.callautomation.models.events.*;
97+
import com.azure.communication.common.CommunicationIdentifier;
98+
import com.azure.communication.common.PhoneNumberIdentifier;
99+
import com.azure.messaging.eventgrid.EventGridEvent;
100+
import com.azure.messaging.eventgrid.systemevents.SubscriptionValidationEventData;
101+
import com.azure.messaging.eventgrid.systemevents.SubscriptionValidationResponse;
102+
import com.google.gson.Gson;
103+
import com.google.gson.JsonObject;
104+
import org.springframework.beans.factory.annotation.Autowired;
105+
import org.springframework.http.HttpStatus;
106+
import org.springframework.http.ResponseEntity;
107+
import org.springframework.web.bind.annotation.*;
108+
import java.time.Duration;
109+
import java.util.*;
110+
import static org.springframework.web.bind.annotation.RequestMethod.POST;
111+
112+
@RestController
113+
public class ActionController {
114+
@Autowired
115+
private CallAutomationAsyncClient client;
116+
117+
private String connectionString = "<resource_connection_string>"); //noted from pre-requisite step
118+
119+
private CallAutomationAsyncClient getCallAutomationAsyncClient() {
120+
if (client == null) {
121+
client = new CallAutomationClientBuilder()
122+
.connectionString(connectionString)
123+
.buildAsyncClient();
124+
}
125+
return client;
132126
}
127+
128+
@RequestMapping(value = "/api/incomingCall", method = POST)
129+
public ResponseEntity<?> handleIncomingCall(@RequestBody(required = false) String requestBody) {
130+
List<EventGridEvent> eventGridEvents = EventGridEvent.fromString(requestBody);
131+
132+
for (EventGridEvent eventGridEvent : eventGridEvents) {
133+
// Handle the subscription validation event
134+
if (eventGridEvent.getEventType().equals("Microsoft.EventGrid.SubscriptionValidationEvent")) {
135+
SubscriptionValidationEventData subscriptionValidationEventData = eventGridEvent.getData().toObject(SubscriptionValidationEventData.class);
136+
SubscriptionValidationResponse subscriptionValidationResponse = new SubscriptionValidationResponse()
137+
.setValidationResponse(subscriptionValidationEventData.getValidationCode());
138+
ResponseEntity<SubscriptionValidationResponse> ret = new ResponseEntity<>(subscriptionValidationResponse, HttpStatus.OK);
139+
return ret;
140+
}
141+
142+
JsonObject data = new Gson().fromJson(eventGridEvent.getData().toString(), JsonObject.class);
143+
144+
String incomingCallContext = data.get("incomingCallContext").getAsString();
145+
CommunicationIdentifier target = new PhoneNumberIdentifier("<phone_number_to_redirect_to>");
146+
RedirectCallOptions redirectCallOptions = new RedirectCallOptions(incomingCallContext, target);
147+
Response<Void> response = client.redirectCallWithResponse(redirectCallOptions).block();
148+
}
149+
150+
return new ResponseEntity<>(HttpStatus.OK);
151+
}
133152
}
134153
```
154+
Update the placeholders in the code above for connection string and phone number to redirect to.
135155

136-
## Run the code
156+
## Run the app
137157

138-
To run your Java application, run maven compile, package, and execute commands. By default, SparkJava runs on port 4567, so the endpoint will be available at `http://localhost:4567/api/incomingCall`.
158+
To run your Java application, run maven compile, package, and execute commands.
159+
160+
```console
161+
mvn compile
162+
mvn package
163+
mvn exec:java -Dexec.mainClass=com.example.demo.DemoApplication -Dexec.cleanupDaemonThreads=false
164+
```

0 commit comments

Comments
 (0)