diff --git a/getting-started/compile.sh b/getting-started/compile.sh
index df08e87..bdd9a85 100755
--- a/getting-started/compile.sh
+++ b/getting-started/compile.sh
@@ -1,9 +1,15 @@
#!/bin/sh
DIRECTORIES="
+conversation/send-text-message/client
+numbers/rent-and-configure/client
+numbers/rent-first-available-number/client
+numbers/search-available/client
+sms/send-sms-message/client
sms/respond-to-incoming-message/server
verification/user-verification-using-sms-pin/client
voice/respond-to-incoming-call/server
+voice/make-a-call/client
"
for DIRECTORY in $DIRECTORIES
diff --git a/getting-started/conversation/send-text-message/client/README.md b/getting-started/conversation/send-text-message/client/README.md
new file mode 100644
index 0000000..05d5fe5
--- /dev/null
+++ b/getting-started/conversation/send-text-message/client/README.md
@@ -0,0 +1,5 @@
+# Sinch Getting started
+
+Code is related to [Send a Conversation Message with the Sinch Java SDK](https://developers.sinch.com/docs/conversation/getting-started/java-sdk/send-message).
+
+See [Client template README](https://github.com/sinch/sinch-sdk-java-quickstart/blob/main/templates/client/README.md) for details about configuration and usage.
diff --git a/getting-started/conversation/send-text-message/client/pom.xml b/getting-started/conversation/send-text-message/client/pom.xml
new file mode 100644
index 0000000..823a8e2
--- /dev/null
+++ b/getting-started/conversation/send-text-message/client/pom.xml
@@ -0,0 +1,85 @@
+
+
+ 4.0.0
+
+ my.company.com
+ sinch-java-sdk-client-application
+ 1.0-SNAPSHOT
+ jar
+ Sinch Java SDK Client Application
+
+
+ [1.5.0,)
+ 8
+ 8
+ 3.13.0
+ UTF-8
+
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+ 3.6.0
+
+
+ add-sources
+ generate-sources
+
+ add-source
+
+
+
+ src/main/java
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+
+
+
+
+ Application
+
+
+
+
+ jar-with-dependencies
+
+
+
+
+ package
+
+ single
+
+
+
+
+
+
+
+
+
+
+ com.sinch.sdk
+ sinch-sdk-java
+ ${sinch.sdk.java.version}
+
+
+
+ org.slf4j
+ slf4j-jdk14
+ 2.0.9
+
+
+
+
+
diff --git a/getting-started/conversation/send-text-message/client/src/main/java/Application.java b/getting-started/conversation/send-text-message/client/src/main/java/Application.java
new file mode 100644
index 0000000..431d975
--- /dev/null
+++ b/getting-started/conversation/send-text-message/client/src/main/java/Application.java
@@ -0,0 +1,42 @@
+import com.sinch.sdk.SinchClient;
+import conversation.ConversationQuickStart;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.logging.LogManager;
+import java.util.logging.Logger;
+
+public abstract class Application {
+
+ private static final String LOGGING_PROPERTIES_FILE = "logging.properties";
+ private static final Logger LOGGER = initializeLogger();
+
+ public static void main(String[] args) {
+ try {
+
+ SinchClient client = SinchClientHelper.initSinchClient();
+ LOGGER.info("Application initiated. SinchClient ready.");
+
+ ConversationQuickStart conversation = new ConversationQuickStart(client.conversation().v1());
+
+ } catch (Exception e) {
+ LOGGER.severe(String.format("Application failure: %s", e.getMessage()));
+ }
+ }
+
+ static Logger initializeLogger() {
+ try (InputStream logConfigInputStream =
+ Application.class.getClassLoader().getResourceAsStream(LOGGING_PROPERTIES_FILE)) {
+
+ if (logConfigInputStream != null) {
+ LogManager.getLogManager().readConfiguration(logConfigInputStream);
+ } else {
+ throw new RuntimeException(
+ String.format("The file '%s' couldn't be loaded.", LOGGING_PROPERTIES_FILE));
+ }
+
+ } catch (IOException e) {
+ throw new RuntimeException(e.getMessage());
+ }
+ return Logger.getLogger(Application.class.getName());
+ }
+}
diff --git a/getting-started/conversation/send-text-message/client/src/main/java/SinchClientHelper.java b/getting-started/conversation/send-text-message/client/src/main/java/SinchClientHelper.java
new file mode 100644
index 0000000..fdc54f1
--- /dev/null
+++ b/getting-started/conversation/send-text-message/client/src/main/java/SinchClientHelper.java
@@ -0,0 +1,90 @@
+import com.sinch.sdk.SinchClient;
+import com.sinch.sdk.models.Configuration;
+import com.sinch.sdk.models.ConversationRegion;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Optional;
+import java.util.Properties;
+import java.util.logging.Logger;
+
+public class SinchClientHelper {
+
+ private static final Logger LOGGER = Logger.getLogger(SinchClientHelper.class.getName());
+
+ private static final String SINCH_PROJECT_ID = "SINCH_PROJECT_ID";
+ private static final String SINCH_KEY_ID = "SINCH_KEY_ID";
+ private static final String SINCH_KEY_SECRET = "SINCH_KEY_SECRET";
+
+ private static final String CONVERSATION_REGION = "CONVERSATION_REGION";
+
+ private static final String CONFIG_FILE = "config.properties";
+
+ public static SinchClient initSinchClient() {
+
+ LOGGER.info("Initializing client");
+
+ Configuration configuration = getConfiguration();
+
+ return new SinchClient(configuration);
+ }
+
+ private static Configuration getConfiguration() {
+
+ Properties properties = loadProperties();
+
+ Configuration.Builder builder = Configuration.builder();
+
+ manageUnifiedCredentials(properties, builder);
+ manageConversationConfiguration(properties, builder);
+
+ return builder.build();
+ }
+
+ private static Properties loadProperties() {
+
+ Properties properties = new Properties();
+
+ try (InputStream input =
+ SinchClientHelper.class.getClassLoader().getResourceAsStream(CONFIG_FILE)) {
+ if (input != null) {
+ properties.load(input);
+ } else {
+ LOGGER.severe(String.format("'%s' file could not be loaded", CONFIG_FILE));
+ }
+ } catch (IOException e) {
+ LOGGER.severe(String.format("Error loading properties from '%s'", CONFIG_FILE));
+ }
+
+ return properties;
+ }
+
+ static void manageUnifiedCredentials(Properties properties, Configuration.Builder builder) {
+
+ Optional projectId = getConfigValue(properties, SINCH_PROJECT_ID);
+ Optional keyId = getConfigValue(properties, SINCH_KEY_ID);
+ Optional keySecret = getConfigValue(properties, SINCH_KEY_SECRET);
+
+ projectId.ifPresent(builder::setProjectId);
+ keyId.ifPresent(builder::setKeyId);
+ keySecret.ifPresent(builder::setKeySecret);
+ }
+
+ private static void manageConversationConfiguration(
+ Properties properties, Configuration.Builder builder) {
+
+ Optional region = getConfigValue(properties, CONVERSATION_REGION);
+
+ region.ifPresent(value -> builder.setConversationRegion(ConversationRegion.from(value)));
+ }
+
+ private static Optional getConfigValue(Properties properties, String key) {
+ String value = null != System.getenv(key) ? System.getenv(key) : properties.getProperty(key);
+
+ // empty value means setting not set
+ if (null != value && value.trim().isEmpty()) {
+ return Optional.empty();
+ }
+
+ return Optional.ofNullable(value);
+ }
+}
diff --git a/getting-started/conversation/send-text-message/client/src/main/java/conversation/ConversationQuickStart.java b/getting-started/conversation/send-text-message/client/src/main/java/conversation/ConversationQuickStart.java
new file mode 100644
index 0000000..f994556
--- /dev/null
+++ b/getting-started/conversation/send-text-message/client/src/main/java/conversation/ConversationQuickStart.java
@@ -0,0 +1,15 @@
+package conversation;
+
+import com.sinch.sdk.domains.conversation.api.v1.ConversationService;
+
+public class ConversationQuickStart {
+
+ private final ConversationService conversationService;
+
+ public ConversationQuickStart(ConversationService conversationService) {
+ this.conversationService = conversationService;
+
+ // replace by your code and business logic
+ Snippet.execute(this.conversationService);
+ }
+}
diff --git a/getting-started/conversation/send-text-message/client/src/main/java/conversation/Snippet.java b/getting-started/conversation/send-text-message/client/src/main/java/conversation/Snippet.java
new file mode 100644
index 0000000..773b8f8
--- /dev/null
+++ b/getting-started/conversation/send-text-message/client/src/main/java/conversation/Snippet.java
@@ -0,0 +1,55 @@
+package conversation;
+
+import com.sinch.sdk.domains.conversation.api.v1.ConversationService;
+import com.sinch.sdk.domains.conversation.api.v1.MessagesService;
+import com.sinch.sdk.domains.conversation.models.v1.*;
+import com.sinch.sdk.domains.conversation.models.v1.messages.*;
+import com.sinch.sdk.domains.conversation.models.v1.messages.request.*;
+import com.sinch.sdk.domains.conversation.models.v1.messages.response.SendMessageResponse;
+import com.sinch.sdk.domains.conversation.models.v1.messages.types.text.*;
+import java.util.*;
+import java.util.Collections;
+import java.util.logging.Logger;
+
+public class Snippet {
+
+ private static final Logger LOGGER = Logger.getLogger(Snippet.class.getName());
+
+ static void execute(ConversationService conversationService) {
+
+ MessagesService messagesService = conversationService.messages();
+
+ String appId = "YOUR_app_id";
+ String from = "YOUR_sms_sender";
+ String to = "RECIPIENT_number";
+
+ String body = "This is a test Conversation message using the Sinch Java SDK.";
+ String smsSender = "SMS_SENDER";
+
+ ChannelRecipientIdentities recipients =
+ ChannelRecipientIdentities.of(
+ ChannelRecipientIdentity.builder()
+ .setChannel(ConversationChannel.SMS)
+ .setIdentity(to)
+ .build());
+
+ AppMessage message =
+ AppMessage.builder()
+ .setBody(TextMessage.builder().setText(body).build())
+ .build();
+
+ SendMessageRequest request =
+ SendMessageRequest.builder()
+ .setAppId(appId)
+ .setRecipient(recipients)
+ .setMessage(message)
+ .setChannelProperties(Collections.singletonMap(smsSender, from))
+ .build();
+
+ LOGGER.info("Sending SMS Text using Conversation API");
+
+ SendMessageResponse value = messagesService.sendMessage(request);
+
+ LOGGER.info("Response: " + value);
+ }
+}
diff --git a/getting-started/conversation/send-text-message/client/src/main/resources/config.properties b/getting-started/conversation/send-text-message/client/src/main/resources/config.properties
new file mode 100644
index 0000000..ea97bca
--- /dev/null
+++ b/getting-started/conversation/send-text-message/client/src/main/resources/config.properties
@@ -0,0 +1,7 @@
+# Required credentials for using the Conversation API
+SINCH_PROJECT_ID=
+SINCH_KEY_ID=
+SINCH_KEY_SECRET=
+
+# See https://github.com/sinch/sinch-sdk-java/blob/main/client/src/main/com/sinch/sdk/models/ConversationRegion.java for list of supported values
+#CONVERSATION_REGION = us
\ No newline at end of file
diff --git a/getting-started/conversation/send-text-message/client/src/main/resources/logging.properties b/getting-started/conversation/send-text-message/client/src/main/resources/logging.properties
new file mode 100644
index 0000000..5ed611e
--- /dev/null
+++ b/getting-started/conversation/send-text-message/client/src/main/resources/logging.properties
@@ -0,0 +1,8 @@
+
+handlers = java.util.logging.ConsoleHandler
+java.util.logging.ConsoleHandler.level = INFO
+com.sinch.level = INFO
+
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+java.util.logging.SimpleFormatter.format=[%1$tF %1$tT] [%4$-7s %2$s] %5$s %n
+
diff --git a/getting-started/numbers/rent-and-configure/client/README.md b/getting-started/numbers/rent-and-configure/client/README.md
new file mode 100644
index 0000000..af483df
--- /dev/null
+++ b/getting-started/numbers/rent-and-configure/client/README.md
@@ -0,0 +1,5 @@
+# Sinch Getting started
+
+Code is related to [Rent and configure your virtual number using Java](https://developers.sinch.com/docs/numbers/getting-started/java-sdk/rentandconfig).
+
+See [Client template README](https://github.com/sinch/sinch-sdk-java-quickstart/blob/main/templates/client/README.md) for details about configuration and usage.
diff --git a/getting-started/numbers/rent-and-configure/client/pom.xml b/getting-started/numbers/rent-and-configure/client/pom.xml
new file mode 100644
index 0000000..823a8e2
--- /dev/null
+++ b/getting-started/numbers/rent-and-configure/client/pom.xml
@@ -0,0 +1,85 @@
+
+
+ 4.0.0
+
+ my.company.com
+ sinch-java-sdk-client-application
+ 1.0-SNAPSHOT
+ jar
+ Sinch Java SDK Client Application
+
+
+ [1.5.0,)
+ 8
+ 8
+ 3.13.0
+ UTF-8
+
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+ 3.6.0
+
+
+ add-sources
+ generate-sources
+
+ add-source
+
+
+
+ src/main/java
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+
+
+
+
+ Application
+
+
+
+
+ jar-with-dependencies
+
+
+
+
+ package
+
+ single
+
+
+
+
+
+
+
+
+
+
+ com.sinch.sdk
+ sinch-sdk-java
+ ${sinch.sdk.java.version}
+
+
+
+ org.slf4j
+ slf4j-jdk14
+ 2.0.9
+
+
+
+
+
diff --git a/getting-started/numbers/rent-and-configure/client/src/main/java/Application.java b/getting-started/numbers/rent-and-configure/client/src/main/java/Application.java
new file mode 100644
index 0000000..f029b86
--- /dev/null
+++ b/getting-started/numbers/rent-and-configure/client/src/main/java/Application.java
@@ -0,0 +1,42 @@
+import com.sinch.sdk.SinchClient;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.logging.LogManager;
+import java.util.logging.Logger;
+import numbers.NumbersQuickStart;
+
+public abstract class Application {
+
+ private static final String LOGGING_PROPERTIES_FILE = "logging.properties";
+ private static final Logger LOGGER = initializeLogger();
+
+ public static void main(String[] args) {
+ try {
+
+ SinchClient client = SinchClientHelper.initSinchClient();
+ LOGGER.info("Application initiated. SinchClient ready.");
+
+ NumbersQuickStart numbers = new NumbersQuickStart(client.numbers().v1());
+
+ } catch (Exception e) {
+ LOGGER.severe(String.format("Application failure: %s", e.getMessage()));
+ }
+ }
+
+ static Logger initializeLogger() {
+ try (InputStream logConfigInputStream =
+ Application.class.getClassLoader().getResourceAsStream(LOGGING_PROPERTIES_FILE)) {
+
+ if (logConfigInputStream != null) {
+ LogManager.getLogManager().readConfiguration(logConfigInputStream);
+ } else {
+ throw new RuntimeException(
+ String.format("The file '%s' couldn't be loaded.", LOGGING_PROPERTIES_FILE));
+ }
+
+ } catch (IOException e) {
+ throw new RuntimeException(e.getMessage());
+ }
+ return Logger.getLogger(Application.class.getName());
+ }
+}
diff --git a/getting-started/numbers/rent-and-configure/client/src/main/java/SinchClientHelper.java b/getting-started/numbers/rent-and-configure/client/src/main/java/SinchClientHelper.java
new file mode 100644
index 0000000..b454c50
--- /dev/null
+++ b/getting-started/numbers/rent-and-configure/client/src/main/java/SinchClientHelper.java
@@ -0,0 +1,78 @@
+import com.sinch.sdk.SinchClient;
+import com.sinch.sdk.models.Configuration;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Optional;
+import java.util.Properties;
+import java.util.logging.Logger;
+
+public class SinchClientHelper {
+
+ private static final Logger LOGGER = Logger.getLogger(SinchClientHelper.class.getName());
+
+ private static final String SINCH_PROJECT_ID = "SINCH_PROJECT_ID";
+ private static final String SINCH_KEY_ID = "SINCH_KEY_ID";
+ private static final String SINCH_KEY_SECRET = "SINCH_KEY_SECRET";
+
+ private static final String CONFIG_FILE = "config.properties";
+
+ public static SinchClient initSinchClient() {
+
+ LOGGER.info("Initializing client");
+
+ Configuration configuration = getConfiguration();
+
+ return new SinchClient(configuration);
+ }
+
+ private static Configuration getConfiguration() {
+
+ Properties properties = loadProperties();
+
+ Configuration.Builder builder = Configuration.builder();
+
+ manageUnifiedCredentials(properties, builder);
+
+ return builder.build();
+ }
+
+ private static Properties loadProperties() {
+
+ Properties properties = new Properties();
+
+ try (InputStream input =
+ SinchClientHelper.class.getClassLoader().getResourceAsStream(CONFIG_FILE)) {
+ if (input != null) {
+ properties.load(input);
+ } else {
+ LOGGER.severe(String.format("'%s' file could not be loaded", CONFIG_FILE));
+ }
+ } catch (IOException e) {
+ LOGGER.severe(String.format("Error loading properties from '%s'", CONFIG_FILE));
+ }
+
+ return properties;
+ }
+
+ static void manageUnifiedCredentials(Properties properties, Configuration.Builder builder) {
+
+ Optional projectId = getConfigValue(properties, SINCH_PROJECT_ID);
+ Optional keyId = getConfigValue(properties, SINCH_KEY_ID);
+ Optional keySecret = getConfigValue(properties, SINCH_KEY_SECRET);
+
+ projectId.ifPresent(builder::setProjectId);
+ keyId.ifPresent(builder::setKeyId);
+ keySecret.ifPresent(builder::setKeySecret);
+ }
+
+ private static Optional getConfigValue(Properties properties, String key) {
+ String value = null != System.getenv(key) ? System.getenv(key) : properties.getProperty(key);
+
+ // empty value means setting not set
+ if (null != value && value.trim().isEmpty()) {
+ return Optional.empty();
+ }
+
+ return Optional.ofNullable(value);
+ }
+}
diff --git a/getting-started/numbers/rent-and-configure/client/src/main/java/numbers/NumbersQuickStart.java b/getting-started/numbers/rent-and-configure/client/src/main/java/numbers/NumbersQuickStart.java
new file mode 100644
index 0000000..f221e06
--- /dev/null
+++ b/getting-started/numbers/rent-and-configure/client/src/main/java/numbers/NumbersQuickStart.java
@@ -0,0 +1,15 @@
+package numbers;
+
+import com.sinch.sdk.domains.numbers.api.v1.NumbersService;
+
+public class NumbersQuickStart {
+
+ private final NumbersService numbersService;
+
+ public NumbersQuickStart(NumbersService numbersService) {
+ this.numbersService = numbersService;
+
+ // replace by your code and business logic
+ Snippet.execute(this.numbersService);
+ }
+}
diff --git a/getting-started/numbers/rent-and-configure/client/src/main/java/numbers/Snippet.java b/getting-started/numbers/rent-and-configure/client/src/main/java/numbers/Snippet.java
new file mode 100644
index 0000000..f460ce1
--- /dev/null
+++ b/getting-started/numbers/rent-and-configure/client/src/main/java/numbers/Snippet.java
@@ -0,0 +1,36 @@
+package numbers;
+
+import com.sinch.sdk.domains.numbers.api.v1.NumbersService;
+import com.sinch.sdk.domains.numbers.models.v1.ActiveNumber;
+import com.sinch.sdk.domains.numbers.models.v1.SmsConfiguration;
+import com.sinch.sdk.domains.numbers.models.v1.request.AvailableNumberRentRequest;
+import java.util.logging.Logger;
+
+public class Snippet {
+
+ private static final Logger LOGGER = Logger.getLogger(Snippet.class.getName());
+
+ static void execute(NumbersService numbersService) {
+
+ // Available numbers list can be retrieved by using list() function from available service, see:
+ // https://developers.sinch.com/docs/numbers/getting-started/java-sdk/searchavailable
+ String phoneNumber = "available_phone_number_to_be_rented";
+ String servicePlanId = "YOUR_service_plan_id";
+
+ SmsConfiguration smsConfiguration =
+ SmsConfiguration.builder().setServicePlanId(servicePlanId).build();
+
+ LOGGER.info(
+ String.format(
+ "Sending request to rent the virtual number: '%s' and configure it with the"
+ + " pre-configured service plan id '%s' to use the SMS capability",
+ phoneNumber, servicePlanId));
+
+ AvailableNumberRentRequest rentRequest =
+ AvailableNumberRentRequest.builder().setSmsConfiguration(smsConfiguration).build();
+
+ ActiveNumber response = numbersService.rent(phoneNumber, rentRequest);
+
+ LOGGER.info(String.format("Rented number: %s", response));
+ }
+}
diff --git a/getting-started/numbers/rent-and-configure/client/src/main/resources/config.properties b/getting-started/numbers/rent-and-configure/client/src/main/resources/config.properties
new file mode 100644
index 0000000..2ff29a1
--- /dev/null
+++ b/getting-started/numbers/rent-and-configure/client/src/main/resources/config.properties
@@ -0,0 +1,4 @@
+# Required credentials for using the Numbers API
+SINCH_PROJECT_ID=
+SINCH_KEY_ID=
+SINCH_KEY_SECRET=
diff --git a/getting-started/numbers/rent-and-configure/client/src/main/resources/logging.properties b/getting-started/numbers/rent-and-configure/client/src/main/resources/logging.properties
new file mode 100644
index 0000000..5ed611e
--- /dev/null
+++ b/getting-started/numbers/rent-and-configure/client/src/main/resources/logging.properties
@@ -0,0 +1,8 @@
+
+handlers = java.util.logging.ConsoleHandler
+java.util.logging.ConsoleHandler.level = INFO
+com.sinch.level = INFO
+
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+java.util.logging.SimpleFormatter.format=[%1$tF %1$tT] [%4$-7s %2$s] %5$s %n
+
diff --git a/getting-started/numbers/rent-first-available-number/client/README.md b/getting-started/numbers/rent-first-available-number/client/README.md
new file mode 100644
index 0000000..03b738c
--- /dev/null
+++ b/getting-started/numbers/rent-first-available-number/client/README.md
@@ -0,0 +1,5 @@
+# Sinch Getting started
+
+Code is related to [Rent the first available number using the Java SDK](https://developers.sinch.com/docs/numbers/getting-started/java-sdk/rentany).
+
+See [Client template README](https://github.com/sinch/sinch-sdk-java-quickstart/blob/main/templates/client/README.md) for details about configuration and usage.
diff --git a/getting-started/numbers/rent-first-available-number/client/pom.xml b/getting-started/numbers/rent-first-available-number/client/pom.xml
new file mode 100644
index 0000000..823a8e2
--- /dev/null
+++ b/getting-started/numbers/rent-first-available-number/client/pom.xml
@@ -0,0 +1,85 @@
+
+
+ 4.0.0
+
+ my.company.com
+ sinch-java-sdk-client-application
+ 1.0-SNAPSHOT
+ jar
+ Sinch Java SDK Client Application
+
+
+ [1.5.0,)
+ 8
+ 8
+ 3.13.0
+ UTF-8
+
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+ 3.6.0
+
+
+ add-sources
+ generate-sources
+
+ add-source
+
+
+
+ src/main/java
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+
+
+
+
+ Application
+
+
+
+
+ jar-with-dependencies
+
+
+
+
+ package
+
+ single
+
+
+
+
+
+
+
+
+
+
+ com.sinch.sdk
+ sinch-sdk-java
+ ${sinch.sdk.java.version}
+
+
+
+ org.slf4j
+ slf4j-jdk14
+ 2.0.9
+
+
+
+
+
diff --git a/getting-started/numbers/rent-first-available-number/client/src/main/java/Application.java b/getting-started/numbers/rent-first-available-number/client/src/main/java/Application.java
new file mode 100644
index 0000000..f029b86
--- /dev/null
+++ b/getting-started/numbers/rent-first-available-number/client/src/main/java/Application.java
@@ -0,0 +1,42 @@
+import com.sinch.sdk.SinchClient;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.logging.LogManager;
+import java.util.logging.Logger;
+import numbers.NumbersQuickStart;
+
+public abstract class Application {
+
+ private static final String LOGGING_PROPERTIES_FILE = "logging.properties";
+ private static final Logger LOGGER = initializeLogger();
+
+ public static void main(String[] args) {
+ try {
+
+ SinchClient client = SinchClientHelper.initSinchClient();
+ LOGGER.info("Application initiated. SinchClient ready.");
+
+ NumbersQuickStart numbers = new NumbersQuickStart(client.numbers().v1());
+
+ } catch (Exception e) {
+ LOGGER.severe(String.format("Application failure: %s", e.getMessage()));
+ }
+ }
+
+ static Logger initializeLogger() {
+ try (InputStream logConfigInputStream =
+ Application.class.getClassLoader().getResourceAsStream(LOGGING_PROPERTIES_FILE)) {
+
+ if (logConfigInputStream != null) {
+ LogManager.getLogManager().readConfiguration(logConfigInputStream);
+ } else {
+ throw new RuntimeException(
+ String.format("The file '%s' couldn't be loaded.", LOGGING_PROPERTIES_FILE));
+ }
+
+ } catch (IOException e) {
+ throw new RuntimeException(e.getMessage());
+ }
+ return Logger.getLogger(Application.class.getName());
+ }
+}
diff --git a/getting-started/numbers/rent-first-available-number/client/src/main/java/SinchClientHelper.java b/getting-started/numbers/rent-first-available-number/client/src/main/java/SinchClientHelper.java
new file mode 100644
index 0000000..b454c50
--- /dev/null
+++ b/getting-started/numbers/rent-first-available-number/client/src/main/java/SinchClientHelper.java
@@ -0,0 +1,78 @@
+import com.sinch.sdk.SinchClient;
+import com.sinch.sdk.models.Configuration;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Optional;
+import java.util.Properties;
+import java.util.logging.Logger;
+
+public class SinchClientHelper {
+
+ private static final Logger LOGGER = Logger.getLogger(SinchClientHelper.class.getName());
+
+ private static final String SINCH_PROJECT_ID = "SINCH_PROJECT_ID";
+ private static final String SINCH_KEY_ID = "SINCH_KEY_ID";
+ private static final String SINCH_KEY_SECRET = "SINCH_KEY_SECRET";
+
+ private static final String CONFIG_FILE = "config.properties";
+
+ public static SinchClient initSinchClient() {
+
+ LOGGER.info("Initializing client");
+
+ Configuration configuration = getConfiguration();
+
+ return new SinchClient(configuration);
+ }
+
+ private static Configuration getConfiguration() {
+
+ Properties properties = loadProperties();
+
+ Configuration.Builder builder = Configuration.builder();
+
+ manageUnifiedCredentials(properties, builder);
+
+ return builder.build();
+ }
+
+ private static Properties loadProperties() {
+
+ Properties properties = new Properties();
+
+ try (InputStream input =
+ SinchClientHelper.class.getClassLoader().getResourceAsStream(CONFIG_FILE)) {
+ if (input != null) {
+ properties.load(input);
+ } else {
+ LOGGER.severe(String.format("'%s' file could not be loaded", CONFIG_FILE));
+ }
+ } catch (IOException e) {
+ LOGGER.severe(String.format("Error loading properties from '%s'", CONFIG_FILE));
+ }
+
+ return properties;
+ }
+
+ static void manageUnifiedCredentials(Properties properties, Configuration.Builder builder) {
+
+ Optional projectId = getConfigValue(properties, SINCH_PROJECT_ID);
+ Optional keyId = getConfigValue(properties, SINCH_KEY_ID);
+ Optional keySecret = getConfigValue(properties, SINCH_KEY_SECRET);
+
+ projectId.ifPresent(builder::setProjectId);
+ keyId.ifPresent(builder::setKeyId);
+ keySecret.ifPresent(builder::setKeySecret);
+ }
+
+ private static Optional getConfigValue(Properties properties, String key) {
+ String value = null != System.getenv(key) ? System.getenv(key) : properties.getProperty(key);
+
+ // empty value means setting not set
+ if (null != value && value.trim().isEmpty()) {
+ return Optional.empty();
+ }
+
+ return Optional.ofNullable(value);
+ }
+}
diff --git a/getting-started/numbers/rent-first-available-number/client/src/main/java/numbers/NumbersQuickStart.java b/getting-started/numbers/rent-first-available-number/client/src/main/java/numbers/NumbersQuickStart.java
new file mode 100644
index 0000000..f221e06
--- /dev/null
+++ b/getting-started/numbers/rent-first-available-number/client/src/main/java/numbers/NumbersQuickStart.java
@@ -0,0 +1,15 @@
+package numbers;
+
+import com.sinch.sdk.domains.numbers.api.v1.NumbersService;
+
+public class NumbersQuickStart {
+
+ private final NumbersService numbersService;
+
+ public NumbersQuickStart(NumbersService numbersService) {
+ this.numbersService = numbersService;
+
+ // replace by your code and business logic
+ Snippet.execute(this.numbersService);
+ }
+}
diff --git a/getting-started/numbers/rent-first-available-number/client/src/main/java/numbers/Snippet.java b/getting-started/numbers/rent-first-available-number/client/src/main/java/numbers/Snippet.java
new file mode 100644
index 0000000..1deec16
--- /dev/null
+++ b/getting-started/numbers/rent-first-available-number/client/src/main/java/numbers/Snippet.java
@@ -0,0 +1,42 @@
+package numbers;
+
+import com.sinch.sdk.domains.numbers.api.v1.NumbersService;
+import com.sinch.sdk.domains.numbers.models.v1.ActiveNumber;
+import com.sinch.sdk.domains.numbers.models.v1.Capability;
+import com.sinch.sdk.domains.numbers.models.v1.NumberType;
+import com.sinch.sdk.domains.numbers.models.v1.SmsConfiguration;
+import com.sinch.sdk.domains.numbers.models.v1.request.AvailableNumberRentAnyRequest;
+import java.util.Collections;
+import java.util.logging.Logger;
+
+public class Snippet {
+
+ private static final Logger LOGGER = Logger.getLogger(Snippet.class.getName());
+
+ static void execute(NumbersService numbersService) {
+
+ String servicePlanId = "YOUR_service_plan_id";
+ String regionCode = "YOUR_region_code";
+
+ Capability capability = Capability.SMS;
+ NumberType numberType = NumberType.LOCAL;
+
+ LOGGER.info(
+ String.format(
+ "Sending request to rent the first available number and configure it with the"
+ + " pre-configured service plan id '%s' to use the SMS capability",
+ servicePlanId));
+
+ ActiveNumber response =
+ numbersService.rentAny(
+ AvailableNumberRentAnyRequest.builder()
+ .setCapabilities(Collections.singletonList(capability))
+ .setType(numberType)
+ .setRegionCode(regionCode)
+ .setSmsConfiguration(
+ SmsConfiguration.builder().setServicePlanId(servicePlanId).build())
+ .build());
+
+ LOGGER.info(String.format("Rented number: %s", response));
+ }
+}
diff --git a/getting-started/numbers/rent-first-available-number/client/src/main/resources/config.properties b/getting-started/numbers/rent-first-available-number/client/src/main/resources/config.properties
new file mode 100644
index 0000000..2ff29a1
--- /dev/null
+++ b/getting-started/numbers/rent-first-available-number/client/src/main/resources/config.properties
@@ -0,0 +1,4 @@
+# Required credentials for using the Numbers API
+SINCH_PROJECT_ID=
+SINCH_KEY_ID=
+SINCH_KEY_SECRET=
diff --git a/getting-started/numbers/rent-first-available-number/client/src/main/resources/logging.properties b/getting-started/numbers/rent-first-available-number/client/src/main/resources/logging.properties
new file mode 100644
index 0000000..5ed611e
--- /dev/null
+++ b/getting-started/numbers/rent-first-available-number/client/src/main/resources/logging.properties
@@ -0,0 +1,8 @@
+
+handlers = java.util.logging.ConsoleHandler
+java.util.logging.ConsoleHandler.level = INFO
+com.sinch.level = INFO
+
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+java.util.logging.SimpleFormatter.format=[%1$tF %1$tT] [%4$-7s %2$s] %5$s %n
+
diff --git a/getting-started/numbers/search-available/client/README.md b/getting-started/numbers/search-available/client/README.md
new file mode 100644
index 0000000..713ef77
--- /dev/null
+++ b/getting-started/numbers/search-available/client/README.md
@@ -0,0 +1,5 @@
+# Sinch Getting started
+
+Code is related to [Search for virtual number using the Java SDK](https://developers.sinch.com/docs/numbers/getting-started/java-sdk/searchavailable).
+
+See [Client template README](https://github.com/sinch/sinch-sdk-java-quickstart/blob/main/templates/client/README.md) for details about configuration and usage.
diff --git a/getting-started/numbers/search-available/client/pom.xml b/getting-started/numbers/search-available/client/pom.xml
new file mode 100644
index 0000000..823a8e2
--- /dev/null
+++ b/getting-started/numbers/search-available/client/pom.xml
@@ -0,0 +1,85 @@
+
+
+ 4.0.0
+
+ my.company.com
+ sinch-java-sdk-client-application
+ 1.0-SNAPSHOT
+ jar
+ Sinch Java SDK Client Application
+
+
+ [1.5.0,)
+ 8
+ 8
+ 3.13.0
+ UTF-8
+
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+ 3.6.0
+
+
+ add-sources
+ generate-sources
+
+ add-source
+
+
+
+ src/main/java
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+
+
+
+
+ Application
+
+
+
+
+ jar-with-dependencies
+
+
+
+
+ package
+
+ single
+
+
+
+
+
+
+
+
+
+
+ com.sinch.sdk
+ sinch-sdk-java
+ ${sinch.sdk.java.version}
+
+
+
+ org.slf4j
+ slf4j-jdk14
+ 2.0.9
+
+
+
+
+
diff --git a/getting-started/numbers/search-available/client/src/main/java/Application.java b/getting-started/numbers/search-available/client/src/main/java/Application.java
new file mode 100644
index 0000000..f029b86
--- /dev/null
+++ b/getting-started/numbers/search-available/client/src/main/java/Application.java
@@ -0,0 +1,42 @@
+import com.sinch.sdk.SinchClient;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.logging.LogManager;
+import java.util.logging.Logger;
+import numbers.NumbersQuickStart;
+
+public abstract class Application {
+
+ private static final String LOGGING_PROPERTIES_FILE = "logging.properties";
+ private static final Logger LOGGER = initializeLogger();
+
+ public static void main(String[] args) {
+ try {
+
+ SinchClient client = SinchClientHelper.initSinchClient();
+ LOGGER.info("Application initiated. SinchClient ready.");
+
+ NumbersQuickStart numbers = new NumbersQuickStart(client.numbers().v1());
+
+ } catch (Exception e) {
+ LOGGER.severe(String.format("Application failure: %s", e.getMessage()));
+ }
+ }
+
+ static Logger initializeLogger() {
+ try (InputStream logConfigInputStream =
+ Application.class.getClassLoader().getResourceAsStream(LOGGING_PROPERTIES_FILE)) {
+
+ if (logConfigInputStream != null) {
+ LogManager.getLogManager().readConfiguration(logConfigInputStream);
+ } else {
+ throw new RuntimeException(
+ String.format("The file '%s' couldn't be loaded.", LOGGING_PROPERTIES_FILE));
+ }
+
+ } catch (IOException e) {
+ throw new RuntimeException(e.getMessage());
+ }
+ return Logger.getLogger(Application.class.getName());
+ }
+}
diff --git a/getting-started/numbers/search-available/client/src/main/java/SinchClientHelper.java b/getting-started/numbers/search-available/client/src/main/java/SinchClientHelper.java
new file mode 100644
index 0000000..b454c50
--- /dev/null
+++ b/getting-started/numbers/search-available/client/src/main/java/SinchClientHelper.java
@@ -0,0 +1,78 @@
+import com.sinch.sdk.SinchClient;
+import com.sinch.sdk.models.Configuration;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Optional;
+import java.util.Properties;
+import java.util.logging.Logger;
+
+public class SinchClientHelper {
+
+ private static final Logger LOGGER = Logger.getLogger(SinchClientHelper.class.getName());
+
+ private static final String SINCH_PROJECT_ID = "SINCH_PROJECT_ID";
+ private static final String SINCH_KEY_ID = "SINCH_KEY_ID";
+ private static final String SINCH_KEY_SECRET = "SINCH_KEY_SECRET";
+
+ private static final String CONFIG_FILE = "config.properties";
+
+ public static SinchClient initSinchClient() {
+
+ LOGGER.info("Initializing client");
+
+ Configuration configuration = getConfiguration();
+
+ return new SinchClient(configuration);
+ }
+
+ private static Configuration getConfiguration() {
+
+ Properties properties = loadProperties();
+
+ Configuration.Builder builder = Configuration.builder();
+
+ manageUnifiedCredentials(properties, builder);
+
+ return builder.build();
+ }
+
+ private static Properties loadProperties() {
+
+ Properties properties = new Properties();
+
+ try (InputStream input =
+ SinchClientHelper.class.getClassLoader().getResourceAsStream(CONFIG_FILE)) {
+ if (input != null) {
+ properties.load(input);
+ } else {
+ LOGGER.severe(String.format("'%s' file could not be loaded", CONFIG_FILE));
+ }
+ } catch (IOException e) {
+ LOGGER.severe(String.format("Error loading properties from '%s'", CONFIG_FILE));
+ }
+
+ return properties;
+ }
+
+ static void manageUnifiedCredentials(Properties properties, Configuration.Builder builder) {
+
+ Optional projectId = getConfigValue(properties, SINCH_PROJECT_ID);
+ Optional keyId = getConfigValue(properties, SINCH_KEY_ID);
+ Optional keySecret = getConfigValue(properties, SINCH_KEY_SECRET);
+
+ projectId.ifPresent(builder::setProjectId);
+ keyId.ifPresent(builder::setKeyId);
+ keySecret.ifPresent(builder::setKeySecret);
+ }
+
+ private static Optional getConfigValue(Properties properties, String key) {
+ String value = null != System.getenv(key) ? System.getenv(key) : properties.getProperty(key);
+
+ // empty value means setting not set
+ if (null != value && value.trim().isEmpty()) {
+ return Optional.empty();
+ }
+
+ return Optional.ofNullable(value);
+ }
+}
diff --git a/getting-started/numbers/search-available/client/src/main/java/numbers/NumbersQuickStart.java b/getting-started/numbers/search-available/client/src/main/java/numbers/NumbersQuickStart.java
new file mode 100644
index 0000000..f221e06
--- /dev/null
+++ b/getting-started/numbers/search-available/client/src/main/java/numbers/NumbersQuickStart.java
@@ -0,0 +1,15 @@
+package numbers;
+
+import com.sinch.sdk.domains.numbers.api.v1.NumbersService;
+
+public class NumbersQuickStart {
+
+ private final NumbersService numbersService;
+
+ public NumbersQuickStart(NumbersService numbersService) {
+ this.numbersService = numbersService;
+
+ // replace by your code and business logic
+ Snippet.execute(this.numbersService);
+ }
+}
diff --git a/getting-started/numbers/search-available/client/src/main/java/numbers/Snippet.java b/getting-started/numbers/search-available/client/src/main/java/numbers/Snippet.java
new file mode 100644
index 0000000..9352d65
--- /dev/null
+++ b/getting-started/numbers/search-available/client/src/main/java/numbers/Snippet.java
@@ -0,0 +1,31 @@
+package numbers;
+
+import com.sinch.sdk.domains.numbers.api.v1.NumbersService;
+import com.sinch.sdk.domains.numbers.models.v1.NumberType;
+import com.sinch.sdk.domains.numbers.models.v1.request.AvailableNumberListRequest;
+import com.sinch.sdk.domains.numbers.models.v1.response.AvailableNumberListResponse;
+import java.util.logging.Logger;
+
+public class Snippet {
+
+ private static final Logger LOGGER = Logger.getLogger(Snippet.class.getName());
+
+ static void execute(NumbersService numbersService) {
+
+ String regionCode = "US";
+ NumberType type = NumberType.LOCAL;
+
+ AvailableNumberListRequest parameters =
+ AvailableNumberListRequest.builder().setRegionCode(regionCode).setType(type).build();
+
+ LOGGER.info(
+ String.format("Listing available number type '%s' for region '%s'", type, regionCode));
+
+ AvailableNumberListResponse response = numbersService.searchForAvailableNumbers(parameters);
+
+ response
+ .iterator()
+ .forEachRemaining(
+ number -> LOGGER.info(String.format("Available number details: %s", number)));
+ }
+}
diff --git a/getting-started/numbers/search-available/client/src/main/resources/config.properties b/getting-started/numbers/search-available/client/src/main/resources/config.properties
new file mode 100644
index 0000000..2ff29a1
--- /dev/null
+++ b/getting-started/numbers/search-available/client/src/main/resources/config.properties
@@ -0,0 +1,4 @@
+# Required credentials for using the Numbers API
+SINCH_PROJECT_ID=
+SINCH_KEY_ID=
+SINCH_KEY_SECRET=
diff --git a/getting-started/numbers/search-available/client/src/main/resources/logging.properties b/getting-started/numbers/search-available/client/src/main/resources/logging.properties
new file mode 100644
index 0000000..5ed611e
--- /dev/null
+++ b/getting-started/numbers/search-available/client/src/main/resources/logging.properties
@@ -0,0 +1,8 @@
+
+handlers = java.util.logging.ConsoleHandler
+java.util.logging.ConsoleHandler.level = INFO
+com.sinch.level = INFO
+
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+java.util.logging.SimpleFormatter.format=[%1$tF %1$tT] [%4$-7s %2$s] %5$s %n
+
diff --git a/getting-started/sms/respond-to-incoming-message/server/src/main/java/com/mycompany/app/Config.java b/getting-started/sms/respond-to-incoming-message/server/src/main/java/com/mycompany/app/Config.java
index be44878..e0404a9 100644
--- a/getting-started/sms/respond-to-incoming-message/server/src/main/java/com/mycompany/app/Config.java
+++ b/getting-started/sms/respond-to-incoming-message/server/src/main/java/com/mycompany/app/Config.java
@@ -4,23 +4,26 @@
import com.sinch.sdk.core.utils.StringUtil;
import com.sinch.sdk.models.Configuration;
import com.sinch.sdk.models.SMSRegion;
+import java.util.logging.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
@org.springframework.context.annotation.Configuration
public class Config {
- @Value("${credentials.project-id}")
+ private static final Logger LOGGER = Logger.getLogger(Config.class.getName());
+
+ @Value("${credentials.project-id: }")
String projectId;
- @Value("${credentials.key-id}")
+ @Value("${credentials.key-id: }")
String keyId;
- @Value("${credentials.key-secret}")
+ @Value("${credentials.key-secret: }")
String keySecret;
- @Value("${sms.region}")
- String region;
+ @Value("${sms.region: }")
+ String smsRegion;
@Bean
public SinchClient sinchClient() {
@@ -30,14 +33,17 @@ public SinchClient sinchClient() {
if (!StringUtil.isEmpty(projectId)) {
builder.setProjectId(projectId);
}
+
if (!StringUtil.isEmpty(keyId)) {
builder.setKeyId(keyId);
}
if (!StringUtil.isEmpty(keySecret)) {
builder.setKeySecret(keySecret);
}
- if (!StringUtil.isEmpty(region)) {
- builder.setSmsRegion(SMSRegion.from(region));
+
+ if (!StringUtil.isEmpty(smsRegion)) {
+ builder.setSmsRegion(SMSRegion.from(smsRegion));
+ LOGGER.info(String.format("SMS region: '%s'", smsRegion));
}
return new SinchClient(builder.build());
diff --git a/getting-started/sms/respond-to-incoming-message/server/src/main/java/com/mycompany/app/sms/Controller.java b/getting-started/sms/respond-to-incoming-message/server/src/main/java/com/mycompany/app/sms/Controller.java
index 0707396..a30397e 100644
--- a/getting-started/sms/respond-to-incoming-message/server/src/main/java/com/mycompany/app/sms/Controller.java
+++ b/getting-started/sms/respond-to-incoming-message/server/src/main/java/com/mycompany/app/sms/Controller.java
@@ -22,7 +22,7 @@ public class Controller {
private final SinchClient sinchClient;
private final ServerBusinessLogic webhooksBusinessLogic;
- @Value("${sms.webhooks.secret}")
+ @Value("${sms.webhooks.secret: }")
private String webhooksSecret;
@Autowired
@@ -45,11 +45,23 @@ public ResponseEntity smsDeliveryEvent(
// https://developers.sinch.com/docs/sms/api-reference/sms/tag/Webhooks/#tag/Webhooks/section/Callbacks
// Contact your account manager to configure your callback sending headers validation or comment
// following line
- var validAuth = webhooks.validateAuthenticationHeader(webhooksSecret, headers, body);
+ // set this value to true to validate request from Sinch servers
+ // see https://developers.sinch.com/docs/numbers/api-reference/numbers/tag/Numbers-Callbacks for
+ // more information
+ boolean ensureValidAuthentication = false;
+ if (ensureValidAuthentication) {
+ var validAuth =
+ webhooks.validateAuthenticationHeader(
+ webhooksSecret,
+ // request headers
+ headers,
+ // request payload body
+ body);
- // token validation failed
- if (!validAuth) {
- throw new ResponseStatusException(HttpStatus.UNAUTHORIZED);
+ // token validation failed
+ if (!validAuth) {
+ throw new ResponseStatusException(HttpStatus.UNAUTHORIZED);
+ }
}
// decode the request payload
diff --git a/getting-started/sms/respond-to-incoming-message/server/src/main/resources/application.yaml b/getting-started/sms/respond-to-incoming-message/server/src/main/resources/application.yaml
index 2a0ef28..06400ee 100644
--- a/getting-started/sms/respond-to-incoming-message/server/src/main/resources/application.yaml
+++ b/getting-started/sms/respond-to-incoming-message/server/src/main/resources/application.yaml
@@ -8,17 +8,18 @@ server:
port: 8090
credentials:
- # Unified related credentials, used by:
- # - Numbers
- # - SMS
+ # Required credentials for using the SMS API
+ # US/EU are the only supported regions with unified credentials
project-id:
key-id:
key-secret:
sms:
# Sets the region for SMS
- # valid values are US and EU
- region:
+ # valid values are "us" and "eu"
+ # See https://github.com/sinch/sinch-sdk-java/blob/main/client/src/main/com/sinch/sdk/models/SMSRegion.java for full list of supported values but with servicePlanID
+ #region:
+ webhooks:
+ secret:
-sms.webhooks.secret:
\ No newline at end of file
diff --git a/getting-started/sms/send-sms-message/client/README.md b/getting-started/sms/send-sms-message/client/README.md
new file mode 100644
index 0000000..88a7d45
--- /dev/null
+++ b/getting-started/sms/send-sms-message/client/README.md
@@ -0,0 +1,5 @@
+# Sinch Getting started
+
+Code is related to [Send an SMS Message with the Sinch Java SDK](https://developers.sinch.com/docs/sms/getting-started/java/send-sms-sdk).
+
+See [Client template README](https://github.com/sinch/sinch-sdk-java-quickstart/blob/main/templates/client/README.md) for details about configuration and usage.
diff --git a/getting-started/sms/send-sms-message/client/pom.xml b/getting-started/sms/send-sms-message/client/pom.xml
new file mode 100644
index 0000000..af9a3b8
--- /dev/null
+++ b/getting-started/sms/send-sms-message/client/pom.xml
@@ -0,0 +1,85 @@
+
+
+ 4.0.0
+
+ my.company.com
+ sinch-java-sdk-client-application
+ 1.0-SNAPSHOT
+ jar
+ Sinch Java SDK Client Application
+
+
+ [1.5.0,)
+ 8
+ 8
+ 3.13.0
+ UTF-8
+
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+ 3.6.0
+
+
+ add-sources
+ generate-sources
+
+ add-source
+
+
+
+ src/main/java
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+
+
+
+
+ Application
+
+
+
+
+ jar-with-dependencies
+
+
+
+
+ package
+
+ single
+
+
+
+
+
+
+
+
+
+
+ com.sinch.sdk
+ sinch-sdk-java
+ ${sinch.sdk.java.version}
+
+
+
+ org.slf4j
+ slf4j-jdk14
+ 2.0.9
+
+
+
+
+
diff --git a/getting-started/sms/send-sms-message/client/src/main/java/Application.java b/getting-started/sms/send-sms-message/client/src/main/java/Application.java
new file mode 100644
index 0000000..9295865
--- /dev/null
+++ b/getting-started/sms/send-sms-message/client/src/main/java/Application.java
@@ -0,0 +1,42 @@
+import com.sinch.sdk.SinchClient;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.logging.LogManager;
+import java.util.logging.Logger;
+import sms.SmsQuickStart;
+
+public abstract class Application {
+
+ private static final String LOGGING_PROPERTIES_FILE = "logging.properties";
+ private static final Logger LOGGER = initializeLogger();
+
+ public static void main(String[] args) {
+ try {
+
+ SinchClient client = SinchClientHelper.initSinchClient();
+ LOGGER.info("Application initiated. SinchClient ready.");
+
+ SmsQuickStart sms = new SmsQuickStart(client.sms().v1());
+
+ } catch (Exception e) {
+ LOGGER.severe(String.format("Application failure: %s", e.getMessage()));
+ }
+ }
+
+ static Logger initializeLogger() {
+ try (InputStream logConfigInputStream =
+ Application.class.getClassLoader().getResourceAsStream(LOGGING_PROPERTIES_FILE)) {
+
+ if (logConfigInputStream != null) {
+ LogManager.getLogManager().readConfiguration(logConfigInputStream);
+ } else {
+ throw new RuntimeException(
+ String.format("The file '%s' couldn't be loaded.", LOGGING_PROPERTIES_FILE));
+ }
+
+ } catch (IOException e) {
+ throw new RuntimeException(e.getMessage());
+ }
+ return Logger.getLogger(Application.class.getName());
+ }
+}
diff --git a/getting-started/sms/send-sms-message/client/src/main/java/SinchClientHelper.java b/getting-started/sms/send-sms-message/client/src/main/java/SinchClientHelper.java
new file mode 100644
index 0000000..3e45ad7
--- /dev/null
+++ b/getting-started/sms/send-sms-message/client/src/main/java/SinchClientHelper.java
@@ -0,0 +1,95 @@
+import com.sinch.sdk.SinchClient;
+import com.sinch.sdk.models.Configuration;
+import com.sinch.sdk.models.SMSRegion;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Optional;
+import java.util.Properties;
+import java.util.logging.Logger;
+
+public class SinchClientHelper {
+
+ private static final Logger LOGGER = Logger.getLogger(SinchClientHelper.class.getName());
+
+ private static final String SINCH_PROJECT_ID = "SINCH_PROJECT_ID";
+ private static final String SINCH_KEY_ID = "SINCH_KEY_ID";
+ private static final String SINCH_KEY_SECRET = "SINCH_KEY_SECRET";
+
+ private static final String SMS_SERVICE_PLAN_ID = "SMS_SERVICE_PLAN_ID";
+ private static final String SMS_SERVICE_PLAN_TOKEN = "SMS_SERVICE_PLAN_TOKEN";
+ private static final String SMS_REGION = "SMS_REGION";
+
+ private static final String CONFIG_FILE = "config.properties";
+
+ public static SinchClient initSinchClient() {
+
+ LOGGER.info("Initializing client");
+
+ Configuration configuration = getConfiguration();
+
+ return new SinchClient(configuration);
+ }
+
+ private static Configuration getConfiguration() {
+
+ Properties properties = loadProperties();
+
+ Configuration.Builder builder = Configuration.builder();
+
+ manageUnifiedCredentials(properties, builder);
+ manageSmsConfiguration(properties, builder);
+
+ return builder.build();
+ }
+
+ private static Properties loadProperties() {
+
+ Properties properties = new Properties();
+
+ try (InputStream input =
+ SinchClientHelper.class.getClassLoader().getResourceAsStream(CONFIG_FILE)) {
+ if (input != null) {
+ properties.load(input);
+ } else {
+ LOGGER.severe(String.format("'%s' file could not be loaded", CONFIG_FILE));
+ }
+ } catch (IOException e) {
+ LOGGER.severe(String.format("Error loading properties from '%s'", CONFIG_FILE));
+ }
+
+ return properties;
+ }
+
+ static void manageUnifiedCredentials(Properties properties, Configuration.Builder builder) {
+
+ Optional projectId = getConfigValue(properties, SINCH_PROJECT_ID);
+ Optional keyId = getConfigValue(properties, SINCH_KEY_ID);
+ Optional keySecret = getConfigValue(properties, SINCH_KEY_SECRET);
+
+ projectId.ifPresent(builder::setProjectId);
+ keyId.ifPresent(builder::setKeyId);
+ keySecret.ifPresent(builder::setKeySecret);
+ }
+
+ private static void manageSmsConfiguration(Properties properties, Configuration.Builder builder) {
+
+ Optional servicePlanId = getConfigValue(properties, SMS_SERVICE_PLAN_ID);
+ Optional servicePlanToken = getConfigValue(properties, SMS_SERVICE_PLAN_TOKEN);
+ Optional region = getConfigValue(properties, SMS_REGION);
+
+ servicePlanId.ifPresent(builder::setSmsServicePlanId);
+ servicePlanToken.ifPresent(builder::setSmsApiToken);
+ region.ifPresent(value -> builder.setSmsRegion(SMSRegion.from(value)));
+ }
+
+ private static Optional getConfigValue(Properties properties, String key) {
+ String value = null != System.getenv(key) ? System.getenv(key) : properties.getProperty(key);
+
+ // empty value means setting not set
+ if (null != value && value.trim().isEmpty()) {
+ return Optional.empty();
+ }
+
+ return Optional.ofNullable(value);
+ }
+}
diff --git a/getting-started/sms/send-sms-message/client/src/main/java/sms/SmsQuickStart.java b/getting-started/sms/send-sms-message/client/src/main/java/sms/SmsQuickStart.java
new file mode 100644
index 0000000..3228327
--- /dev/null
+++ b/getting-started/sms/send-sms-message/client/src/main/java/sms/SmsQuickStart.java
@@ -0,0 +1,15 @@
+package sms;
+
+import com.sinch.sdk.domains.sms.api.v1.SMSService;
+
+public class SmsQuickStart {
+
+ private final SMSService smsService;
+
+ public SmsQuickStart(SMSService smsService) {
+ this.smsService = smsService;
+
+ // replace by your code and business logic
+ Snippet.execute(this.smsService);
+ }
+}
diff --git a/getting-started/sms/send-sms-message/client/src/main/java/sms/Snippet.java b/getting-started/sms/send-sms-message/client/src/main/java/sms/Snippet.java
new file mode 100644
index 0000000..37398eb
--- /dev/null
+++ b/getting-started/sms/send-sms-message/client/src/main/java/sms/Snippet.java
@@ -0,0 +1,34 @@
+package sms;
+
+import com.sinch.sdk.domains.sms.api.v1.BatchesService;
+import com.sinch.sdk.domains.sms.api.v1.SMSService;
+import com.sinch.sdk.domains.sms.models.v1.batches.request.TextRequest;
+import com.sinch.sdk.domains.sms.models.v1.batches.response.BatchResponse;
+import java.util.Collections;
+import java.util.logging.Logger;
+
+public class Snippet {
+
+ private static final Logger LOGGER = Logger.getLogger(Snippet.class.getName());
+
+ static void execute(SMSService smsService) {
+
+ BatchesService batchesService = smsService.batches();
+
+ String from = "YOUR_sinch_phone_number";
+ String recipient = "YOUR_recipient_phone_number";
+ String body = "This is a test SMS message using the Sinch Java SDK.";
+
+ LOGGER.info(String.format("Submitting batch to send SMS to '%s'", recipient));
+
+ BatchResponse value =
+ batchesService.send(
+ TextRequest.builder()
+ .setTo(Collections.singletonList(recipient))
+ .setBody(body)
+ .setFrom(from)
+ .build());
+
+ LOGGER.info("Response: " + value);
+ }
+}
diff --git a/getting-started/sms/send-sms-message/client/src/main/resources/config.properties b/getting-started/sms/send-sms-message/client/src/main/resources/config.properties
new file mode 100644
index 0000000..735ee84
--- /dev/null
+++ b/getting-started/sms/send-sms-message/client/src/main/resources/config.properties
@@ -0,0 +1,12 @@
+# Required credentials for using the SMS API
+SINCH_PROJECT_ID=
+SINCH_KEY_ID=
+SINCH_KEY_SECRET=
+
+# Service related configuration
+#SMS_REGION = us
+
+# SMS Service Plan ID related credentials
+# if set, these credentials will be used and enable to use regions different of US/EU
+#SMS_SERVICE_PLAN_ID =
+#SMS_SERVICE_PLAN_TOKEN =
diff --git a/getting-started/sms/send-sms-message/client/src/main/resources/logging.properties b/getting-started/sms/send-sms-message/client/src/main/resources/logging.properties
new file mode 100644
index 0000000..5ed611e
--- /dev/null
+++ b/getting-started/sms/send-sms-message/client/src/main/resources/logging.properties
@@ -0,0 +1,8 @@
+
+handlers = java.util.logging.ConsoleHandler
+java.util.logging.ConsoleHandler.level = INFO
+com.sinch.level = INFO
+
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+java.util.logging.SimpleFormatter.format=[%1$tF %1$tT] [%4$-7s %2$s] %5$s %n
+
diff --git a/getting-started/verification/user-verification-using-sms-pin/README.md b/getting-started/verification/user-verification-using-sms-pin/README.md
index 3d72656..04167ce 100644
--- a/getting-started/verification/user-verification-using-sms-pin/README.md
+++ b/getting-started/verification/user-verification-using-sms-pin/README.md
@@ -2,4 +2,4 @@
Code is related to [Verify a user using SMS PIN with the Java SDK](https://developers.sinch.com/docs/verification/getting-started/java-sdk/sms-verification/).
-See [Server template README](https://github.com/sinch/sinch-sdk-java-quickstart/blob/main/templates/server/README.md) for details about configuration and usage.
+See [Client template README](https://github.com/sinch/sinch-sdk-java-quickstart/blob/main/templates/client/README.md) for details about configuration and usage.
diff --git a/getting-started/verification/user-verification-using-sms-pin/client/src/main/java/SinchClientHelper.java b/getting-started/verification/user-verification-using-sms-pin/client/src/main/java/SinchClientHelper.java
index 49ed29b..4b78d21 100644
--- a/getting-started/verification/user-verification-using-sms-pin/client/src/main/java/SinchClientHelper.java
+++ b/getting-started/verification/user-verification-using-sms-pin/client/src/main/java/SinchClientHelper.java
@@ -1,6 +1,5 @@
import com.sinch.sdk.SinchClient;
import com.sinch.sdk.models.Configuration;
-import com.sinch.sdk.models.SMSRegion;
import java.io.IOException;
import java.io.InputStream;
import java.util.Optional;
@@ -11,17 +10,9 @@ public class SinchClientHelper {
private static final Logger LOGGER = Logger.getLogger(SinchClientHelper.class.getName());
- private static final String SINCH_PROJECT_ID = "SINCH_PROJECT_ID";
- private static final String SINCH_KEY_ID = "SINCH_KEY_ID";
- private static final String SINCH_KEY_SECRET = "SINCH_KEY_SECRET";
-
private static final String APPLICATION_API_KEY = "APPLICATION_API_KEY";
private static final String APPLICATION_API_SECRET = "APPLICATION_API_SECRET";
- private static final String SMS_SERVICE_PLAN_ID = "SMS_SERVICE_PLAN_ID";
- private static final String SMS_SERVICE_PLAN_TOKEN = "SMS_SERVICE_PLAN_TOKEN";
- private static final String SMS_REGION = "SMS_REGION";
-
private static final String CONFIG_FILE = "config.properties";
public static SinchClient initSinchClient() {
@@ -39,9 +30,7 @@ private static Configuration getConfiguration() {
Configuration.Builder builder = Configuration.builder();
- manageUnifiedCredentials(properties, builder);
manageApplicationCredentials(properties, builder);
- manageSmsConfiguration(properties, builder);
return builder.build();
}
@@ -64,17 +53,6 @@ private static Properties loadProperties() {
return properties;
}
- static void manageUnifiedCredentials(Properties properties, Configuration.Builder builder) {
-
- Optional projectId = getConfigValue(properties, SINCH_PROJECT_ID);
- Optional keyId = getConfigValue(properties, SINCH_KEY_ID);
- Optional keySecret = getConfigValue(properties, SINCH_KEY_SECRET);
-
- projectId.ifPresent(builder::setProjectId);
- keyId.ifPresent(builder::setKeyId);
- keySecret.ifPresent(builder::setKeySecret);
- }
-
private static void manageApplicationCredentials(
Properties properties, Configuration.Builder builder) {
@@ -85,17 +63,6 @@ private static void manageApplicationCredentials(
verificationApiSecret.ifPresent(builder::setApplicationSecret);
}
- private static void manageSmsConfiguration(Properties properties, Configuration.Builder builder) {
-
- Optional servicePlanId = getConfigValue(properties, SMS_SERVICE_PLAN_ID);
- Optional servicePlanToken = getConfigValue(properties, SMS_SERVICE_PLAN_TOKEN);
- Optional region = getConfigValue(properties, SMS_REGION);
-
- servicePlanId.ifPresent(builder::setSmsServicePlanId);
- servicePlanToken.ifPresent(builder::setSmsApiToken);
- region.ifPresent(value -> builder.setSmsRegion(SMSRegion.from(value)));
- }
-
private static Optional getConfigValue(Properties properties, String key) {
String value = null != System.getenv(key) ? System.getenv(key) : properties.getProperty(key);
diff --git a/getting-started/verification/user-verification-using-sms-pin/client/src/main/resources/config.properties b/getting-started/verification/user-verification-using-sms-pin/client/src/main/resources/config.properties
index 037d872..ff60106 100644
--- a/getting-started/verification/user-verification-using-sms-pin/client/src/main/resources/config.properties
+++ b/getting-started/verification/user-verification-using-sms-pin/client/src/main/resources/config.properties
@@ -1,2 +1,3 @@
+# Required credentials for using the Verification API
APPLICATION_API_KEY=
APPLICATION_API_SECRET=
diff --git a/getting-started/voice/make-a-call/client/README.md b/getting-started/voice/make-a-call/client/README.md
new file mode 100644
index 0000000..ca38b66
--- /dev/null
+++ b/getting-started/voice/make-a-call/client/README.md
@@ -0,0 +1,5 @@
+# Sinch Getting started
+
+Code is related to [Make a call with Java SDK](https://developers.sinch.com/docs/voice/getting-started/java-sdk/make-call/#make-a-call-with-java-sdk).
+
+See [Client template README](https://github.com/sinch/sinch-sdk-java-quickstart/blob/main/templates/client/README.md) for details about configuration and usage.
diff --git a/getting-started/voice/make-a-call/client/pom.xml b/getting-started/voice/make-a-call/client/pom.xml
new file mode 100644
index 0000000..823a8e2
--- /dev/null
+++ b/getting-started/voice/make-a-call/client/pom.xml
@@ -0,0 +1,85 @@
+
+
+ 4.0.0
+
+ my.company.com
+ sinch-java-sdk-client-application
+ 1.0-SNAPSHOT
+ jar
+ Sinch Java SDK Client Application
+
+
+ [1.5.0,)
+ 8
+ 8
+ 3.13.0
+ UTF-8
+
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+ 3.6.0
+
+
+ add-sources
+ generate-sources
+
+ add-source
+
+
+
+ src/main/java
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+
+
+
+
+ Application
+
+
+
+
+ jar-with-dependencies
+
+
+
+
+ package
+
+ single
+
+
+
+
+
+
+
+
+
+
+ com.sinch.sdk
+ sinch-sdk-java
+ ${sinch.sdk.java.version}
+
+
+
+ org.slf4j
+ slf4j-jdk14
+ 2.0.9
+
+
+
+
+
diff --git a/getting-started/voice/make-a-call/client/src/main/java/Application.java b/getting-started/voice/make-a-call/client/src/main/java/Application.java
new file mode 100644
index 0000000..de21eb8
--- /dev/null
+++ b/getting-started/voice/make-a-call/client/src/main/java/Application.java
@@ -0,0 +1,42 @@
+import com.sinch.sdk.SinchClient;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.logging.LogManager;
+import java.util.logging.Logger;
+import voice.VoiceQuickStart;
+
+public abstract class Application {
+
+ private static final String LOGGING_PROPERTIES_FILE = "logging.properties";
+ private static final Logger LOGGER = initializeLogger();
+
+ public static void main(String[] args) {
+ try {
+
+ SinchClient client = SinchClientHelper.initSinchClient();
+ LOGGER.info("Application initiated. SinchClient ready.");
+
+ VoiceQuickStart voice = new VoiceQuickStart(client.voice().v1());
+
+ } catch (Exception e) {
+ LOGGER.severe(String.format("Application failure: %s", e.getMessage()));
+ }
+ }
+
+ static Logger initializeLogger() {
+ try (InputStream logConfigInputStream =
+ Application.class.getClassLoader().getResourceAsStream(LOGGING_PROPERTIES_FILE)) {
+
+ if (logConfigInputStream != null) {
+ LogManager.getLogManager().readConfiguration(logConfigInputStream);
+ } else {
+ throw new RuntimeException(
+ String.format("The file '%s' couldn't be loaded.", LOGGING_PROPERTIES_FILE));
+ }
+
+ } catch (IOException e) {
+ throw new RuntimeException(e.getMessage());
+ }
+ return Logger.getLogger(Application.class.getName());
+ }
+}
diff --git a/getting-started/voice/make-a-call/client/src/main/java/SinchClientHelper.java b/getting-started/voice/make-a-call/client/src/main/java/SinchClientHelper.java
new file mode 100644
index 0000000..4b78d21
--- /dev/null
+++ b/getting-started/voice/make-a-call/client/src/main/java/SinchClientHelper.java
@@ -0,0 +1,76 @@
+import com.sinch.sdk.SinchClient;
+import com.sinch.sdk.models.Configuration;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Optional;
+import java.util.Properties;
+import java.util.logging.Logger;
+
+public class SinchClientHelper {
+
+ private static final Logger LOGGER = Logger.getLogger(SinchClientHelper.class.getName());
+
+ private static final String APPLICATION_API_KEY = "APPLICATION_API_KEY";
+ private static final String APPLICATION_API_SECRET = "APPLICATION_API_SECRET";
+
+ private static final String CONFIG_FILE = "config.properties";
+
+ public static SinchClient initSinchClient() {
+
+ LOGGER.info("Initializing client");
+
+ Configuration configuration = getConfiguration();
+
+ return new SinchClient(configuration);
+ }
+
+ private static Configuration getConfiguration() {
+
+ Properties properties = loadProperties();
+
+ Configuration.Builder builder = Configuration.builder();
+
+ manageApplicationCredentials(properties, builder);
+
+ return builder.build();
+ }
+
+ private static Properties loadProperties() {
+
+ Properties properties = new Properties();
+
+ try (InputStream input =
+ SinchClientHelper.class.getClassLoader().getResourceAsStream(CONFIG_FILE)) {
+ if (input != null) {
+ properties.load(input);
+ } else {
+ LOGGER.severe(String.format("'%s' file could not be loaded", CONFIG_FILE));
+ }
+ } catch (IOException e) {
+ LOGGER.severe(String.format("Error loading properties from '%s'", CONFIG_FILE));
+ }
+
+ return properties;
+ }
+
+ private static void manageApplicationCredentials(
+ Properties properties, Configuration.Builder builder) {
+
+ Optional verificationApiKey = getConfigValue(properties, APPLICATION_API_KEY);
+ Optional verificationApiSecret = getConfigValue(properties, APPLICATION_API_SECRET);
+
+ verificationApiKey.ifPresent(builder::setApplicationKey);
+ verificationApiSecret.ifPresent(builder::setApplicationSecret);
+ }
+
+ private static Optional getConfigValue(Properties properties, String key) {
+ String value = null != System.getenv(key) ? System.getenv(key) : properties.getProperty(key);
+
+ // empty value means setting not set
+ if (null != value && value.trim().isEmpty()) {
+ return Optional.empty();
+ }
+
+ return Optional.ofNullable(value);
+ }
+}
diff --git a/getting-started/voice/make-a-call/client/src/main/java/voice/Snippet.java b/getting-started/voice/make-a-call/client/src/main/java/voice/Snippet.java
new file mode 100644
index 0000000..4b844ca
--- /dev/null
+++ b/getting-started/voice/make-a-call/client/src/main/java/voice/Snippet.java
@@ -0,0 +1,34 @@
+package voice;
+
+import com.sinch.sdk.domains.voice.api.v1.CalloutsService;
+import com.sinch.sdk.domains.voice.api.v1.VoiceService;
+import com.sinch.sdk.domains.voice.models.v1.callouts.request.CalloutRequestTTS;
+import com.sinch.sdk.domains.voice.models.v1.destination.DestinationPstn;
+import java.util.logging.Logger;
+
+public class Snippet {
+
+ private static final Logger LOGGER = Logger.getLogger(Snippet.class.getName());
+
+ public static String execute(VoiceService voiceService) {
+
+ CalloutsService calloutsService = voiceService.callouts();
+
+ String phoneNumber = "YOUR_phone_number";
+ String message = "Hello, this is a call from Sinch. Congratulations! You made your first call.";
+
+ LOGGER.info("Calling '" + phoneNumber + '"');
+
+ CalloutRequestTTS parameters =
+ CalloutRequestTTS.builder()
+ .setDestination(DestinationPstn.from(phoneNumber))
+ .setText(message)
+ .build();
+
+ String callId = calloutsService.textToSpeech(parameters);
+
+ LOGGER.info("Call started with id: '" + callId + '"');
+
+ return callId;
+ }
+}
diff --git a/getting-started/voice/make-a-call/client/src/main/java/voice/VoiceQuickStart.java b/getting-started/voice/make-a-call/client/src/main/java/voice/VoiceQuickStart.java
new file mode 100644
index 0000000..a7ecc89
--- /dev/null
+++ b/getting-started/voice/make-a-call/client/src/main/java/voice/VoiceQuickStart.java
@@ -0,0 +1,15 @@
+package voice;
+
+import com.sinch.sdk.domains.voice.api.v1.VoiceService;
+
+public class VoiceQuickStart {
+
+ private final VoiceService voiceService;
+
+ public VoiceQuickStart(VoiceService voiceService) {
+ this.voiceService = voiceService;
+
+ // replace by your code and business logic
+ Snippet.execute(this.voiceService);
+ }
+}
diff --git a/getting-started/voice/make-a-call/client/src/main/resources/config.properties b/getting-started/voice/make-a-call/client/src/main/resources/config.properties
new file mode 100644
index 0000000..9e32513
--- /dev/null
+++ b/getting-started/voice/make-a-call/client/src/main/resources/config.properties
@@ -0,0 +1,3 @@
+# Required credentials for using the Voice API
+APPLICATION_API_KEY=
+APPLICATION_API_SECRET=
diff --git a/getting-started/voice/make-a-call/client/src/main/resources/logging.properties b/getting-started/voice/make-a-call/client/src/main/resources/logging.properties
new file mode 100644
index 0000000..5ed611e
--- /dev/null
+++ b/getting-started/voice/make-a-call/client/src/main/resources/logging.properties
@@ -0,0 +1,8 @@
+
+handlers = java.util.logging.ConsoleHandler
+java.util.logging.ConsoleHandler.level = INFO
+com.sinch.level = INFO
+
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+java.util.logging.SimpleFormatter.format=[%1$tF %1$tT] [%4$-7s %2$s] %5$s %n
+
diff --git a/getting-started/voice/respond-to-incoming-call/server/src/main/java/com/mycompany/app/Config.java b/getting-started/voice/respond-to-incoming-call/server/src/main/java/com/mycompany/app/Config.java
index 23b3ace..424ef34 100644
--- a/getting-started/voice/respond-to-incoming-call/server/src/main/java/com/mycompany/app/Config.java
+++ b/getting-started/voice/respond-to-incoming-call/server/src/main/java/com/mycompany/app/Config.java
@@ -3,16 +3,19 @@
import com.sinch.sdk.SinchClient;
import com.sinch.sdk.core.utils.StringUtil;
import com.sinch.sdk.models.Configuration;
+import java.util.logging.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
@org.springframework.context.annotation.Configuration
public class Config {
- @Value("${credentials.application-api-key}")
+ private static final Logger LOGGER = Logger.getLogger(Config.class.getName());
+
+ @Value("${credentials.application-api-key: }")
String applicationKey;
- @Value("${credentials.application-api-secret}")
+ @Value("${credentials.application-api-secret: }")
String applicationSecret;
@Bean
diff --git a/getting-started/voice/respond-to-incoming-call/server/src/main/java/com/mycompany/app/voice/Controller.java b/getting-started/voice/respond-to-incoming-call/server/src/main/java/com/mycompany/app/voice/Controller.java
index 7f97aab..e56f348 100644
--- a/getting-started/voice/respond-to-incoming-call/server/src/main/java/com/mycompany/app/voice/Controller.java
+++ b/getting-started/voice/respond-to-incoming-call/server/src/main/java/com/mycompany/app/voice/Controller.java
@@ -1,9 +1,9 @@
package com.mycompany.app.voice;
import com.sinch.sdk.SinchClient;
-import com.sinch.sdk.domains.voice.WebHooksService;
-import com.sinch.sdk.domains.voice.models.webhooks.DisconnectCallEvent;
-import com.sinch.sdk.domains.voice.models.webhooks.IncomingCallEvent;
+import com.sinch.sdk.domains.voice.api.v1.WebHooksService;
+import com.sinch.sdk.domains.voice.models.v1.webhooks.DisconnectedCallEvent;
+import com.sinch.sdk.domains.voice.models.v1.webhooks.IncomingCallEvent;
import java.util.Map;
import java.util.logging.Logger;
import org.springframework.beans.factory.annotation.Autowired;
@@ -36,33 +36,41 @@ public Controller(SinchClient sinchClient, ServerBusinessLogic webhooksBusinessL
public ResponseEntity VoiceEvent(
@RequestHeader Map headers, @RequestBody String body) {
- WebHooksService webhooks = sinchClient.voice().webhooks();
+ WebHooksService webhooks = sinchClient.voice().v1().webhooks();
// ensure valid authentication to handle request
- var validAuth =
- webhooks.validateAuthenticatedRequest(
- // The HTTP verb this controller is managing
- "POST",
- // The URI this controller is managing
- "/VoiceEvent",
- // request headers
- headers,
- // request payload body
- body);
+ // set this value to true to validate request from Sinch servers
+ // see
+ // https://developers.sinch.com/docs/voice/api-reference/authentication/callback-signed-request
+ // for more information
+ boolean ensureValidAuthentication = false;
+ if (ensureValidAuthentication) {
+ // ensure valid authentication to handle request
+ var validAuth =
+ webhooks.validateAuthenticationHeader(
+ // The HTTP verb this controller is managing
+ "POST",
+ // The URI this controller is managing
+ "/VoiceEvent",
+ // request headers
+ headers,
+ // request payload body
+ body);
- // token validation failed
- if (!validAuth) {
- throw new ResponseStatusException(HttpStatus.UNAUTHORIZED);
+ // token validation failed
+ if (!validAuth) {
+ throw new ResponseStatusException(HttpStatus.UNAUTHORIZED);
+ }
}
// decode the payload request
- var event = webhooks.unserializeWebhooksEvent(body);
+ var event = webhooks.parseEvent(body);
// let business layer process the request
var response =
switch (event) {
case IncomingCallEvent e -> webhooksBusinessLogic.incoming(e);
- case DisconnectCallEvent e -> {
+ case DisconnectedCallEvent e -> {
webhooksBusinessLogic.disconnect(e);
yield null;
}
@@ -71,7 +79,7 @@ public ResponseEntity VoiceEvent(
String serializedResponse = "";
if (null != response) {
- serializedResponse = webhooks.serializeWebhooksResponse(response);
+ serializedResponse = webhooks.serializeResponse(response);
}
LOGGER.finest("JSON response: " + serializedResponse);
diff --git a/getting-started/voice/respond-to-incoming-call/server/src/main/java/com/mycompany/app/voice/ServerBusinessLogic.java b/getting-started/voice/respond-to-incoming-call/server/src/main/java/com/mycompany/app/voice/ServerBusinessLogic.java
index b4eb7b9..c339699 100644
--- a/getting-started/voice/respond-to-incoming-call/server/src/main/java/com/mycompany/app/voice/ServerBusinessLogic.java
+++ b/getting-started/voice/respond-to-incoming-call/server/src/main/java/com/mycompany/app/voice/ServerBusinessLogic.java
@@ -1,10 +1,10 @@
package com.mycompany.app.voice;
-import com.sinch.sdk.domains.voice.models.svaml.ActionHangUp;
-import com.sinch.sdk.domains.voice.models.svaml.InstructionSay;
-import com.sinch.sdk.domains.voice.models.svaml.SVAMLControl;
-import com.sinch.sdk.domains.voice.models.webhooks.DisconnectCallEvent;
-import com.sinch.sdk.domains.voice.models.webhooks.IncomingCallEvent;
+import com.sinch.sdk.domains.voice.models.v1.svaml.SvamlControl;
+import com.sinch.sdk.domains.voice.models.v1.svaml.action.SvamlActionHangup;
+import com.sinch.sdk.domains.voice.models.v1.svaml.instruction.SvamlInstructionSay;
+import com.sinch.sdk.domains.voice.models.v1.webhooks.DisconnectedCallEvent;
+import com.sinch.sdk.domains.voice.models.v1.webhooks.IncomingCallEvent;
import java.util.Collections;
import java.util.logging.Logger;
import org.springframework.stereotype.Component;
@@ -14,21 +14,21 @@ public class ServerBusinessLogic {
private static final Logger LOGGER = Logger.getLogger(ServerBusinessLogic.class.getName());
- public SVAMLControl incoming(IncomingCallEvent event) {
+ public SvamlControl incoming(IncomingCallEvent event) {
LOGGER.info("Handle event: " + event);
String instruction =
"Thank you for calling your Sinch number. You've just handled an incoming call.";
- return SVAMLControl.builder()
- .setAction(ActionHangUp.builder().build())
+ return SvamlControl.builder()
+ .setAction(SvamlActionHangup.builder().build())
.setInstructions(
- Collections.singletonList(InstructionSay.builder().setText(instruction).build()))
+ Collections.singletonList(SvamlInstructionSay.builder().setText(instruction).build()))
.build();
}
- public void disconnect(DisconnectCallEvent event) {
+ public void disconnect(DisconnectedCallEvent event) {
LOGGER.info("Handle event: " + event);
}
diff --git a/getting-started/voice/respond-to-incoming-call/server/src/main/resources/application.yaml b/getting-started/voice/respond-to-incoming-call/server/src/main/resources/application.yaml
index 5d82fb2..f8d0e21 100644
--- a/getting-started/voice/respond-to-incoming-call/server/src/main/resources/application.yaml
+++ b/getting-started/voice/respond-to-incoming-call/server/src/main/resources/application.yaml
@@ -8,8 +8,6 @@ server:
port: 8090
credentials:
- # Application related credentials, used by:
- # - Verification
- # - Voice
+ # Required credentials for using the Voice API
application-api-key:
application-api-secret:
diff --git a/templates/client/pom.xml b/templates/client/pom.xml
index af779f8..af9a3b8 100644
--- a/templates/client/pom.xml
+++ b/templates/client/pom.xml
@@ -74,11 +74,9 @@
${sinch.sdk.java.version}
-
org.slf4j
- slf4j-nop
+ slf4j-jdk14
2.0.9
diff --git a/templates/client/src/main/java/SinchClientHelper.java b/templates/client/src/main/java/SinchClientHelper.java
index 49ed29b..9e1b6a8 100644
--- a/templates/client/src/main/java/SinchClientHelper.java
+++ b/templates/client/src/main/java/SinchClientHelper.java
@@ -1,5 +1,6 @@
import com.sinch.sdk.SinchClient;
import com.sinch.sdk.models.Configuration;
+import com.sinch.sdk.models.ConversationRegion;
import com.sinch.sdk.models.SMSRegion;
import java.io.IOException;
import java.io.InputStream;
@@ -22,6 +23,8 @@ public class SinchClientHelper {
private static final String SMS_SERVICE_PLAN_TOKEN = "SMS_SERVICE_PLAN_TOKEN";
private static final String SMS_REGION = "SMS_REGION";
+ private static final String CONVERSATION_REGION = "CONVERSATION_REGION";
+
private static final String CONFIG_FILE = "config.properties";
public static SinchClient initSinchClient() {
@@ -41,6 +44,7 @@ private static Configuration getConfiguration() {
manageUnifiedCredentials(properties, builder);
manageApplicationCredentials(properties, builder);
+ manageConversationConfiguration(properties, builder);
manageSmsConfiguration(properties, builder);
return builder.build();
@@ -85,6 +89,14 @@ private static void manageApplicationCredentials(
verificationApiSecret.ifPresent(builder::setApplicationSecret);
}
+ private static void manageConversationConfiguration(
+ Properties properties, Configuration.Builder builder) {
+
+ Optional region = getConfigValue(properties, CONVERSATION_REGION);
+
+ region.ifPresent(value -> builder.setConversationRegion(ConversationRegion.from(value)));
+ }
+
private static void manageSmsConfiguration(Properties properties, Configuration.Builder builder) {
Optional servicePlanId = getConfigValue(properties, SMS_SERVICE_PLAN_ID);
diff --git a/templates/client/src/main/resources/config.properties b/templates/client/src/main/resources/config.properties
index f18db35..50c967f 100644
--- a/templates/client/src/main/resources/config.properties
+++ b/templates/client/src/main/resources/config.properties
@@ -1,6 +1,7 @@
-# Unified related credentials, used by:
+# Java SDK domains supporting unified credentials
# - Numbers
# - SMS: US/EU are the only supported regions with unified credentials
+# - Conversation
SINCH_PROJECT_ID =
SINCH_KEY_ID =
SINCH_KEY_SECRET =
@@ -11,9 +12,14 @@ SINCH_KEY_SECRET =
#APPLICATION_API_KEY =
#APPLICATION_API_SECRET =
-# Service related configuration
-SMS_REGION = us
# SMS Service Plan ID related credentials
# if set, these credentials will be used and enable to use regions different of US/EU
#SMS_SERVICE_PLAN_ID =
#SMS_SERVICE_PLAN_TOKEN =
+
+# See https://github.com/sinch/sinch-sdk-java/blob/main/client/src/main/com/sinch/sdk/models/SMSRegion.java for full list of supported values but with servicePlanID
+# valid values are "us" and "eu"
+#SMS_REGION = us
+
+# See https://github.com/sinch/sinch-sdk-java/blob/main/client/src/main/com/sinch/sdk/models/ConversationRegion.java for list of supported values
+#CONVERSATION_REGION = us
diff --git a/templates/server/src/main/java/com/mycompany/app/Config.java b/templates/server/src/main/java/com/mycompany/app/Config.java
index 4cbc290..427dfb3 100644
--- a/templates/server/src/main/java/com/mycompany/app/Config.java
+++ b/templates/server/src/main/java/com/mycompany/app/Config.java
@@ -3,30 +3,37 @@
import com.sinch.sdk.SinchClient;
import com.sinch.sdk.core.utils.StringUtil;
import com.sinch.sdk.models.Configuration;
+import com.sinch.sdk.models.ConversationRegion;
import com.sinch.sdk.models.SMSRegion;
+import java.util.logging.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
@org.springframework.context.annotation.Configuration
public class Config {
- @Value("${credentials.project-id}")
+ private static final Logger LOGGER = Logger.getLogger(Config.class.getName());
+
+ @Value("${credentials.project-id: }")
String projectId;
- @Value("${credentials.key-id}")
+ @Value("${credentials.key-id: }")
String keyId;
- @Value("${credentials.key-secret}")
+ @Value("${credentials.key-secret: }")
String keySecret;
- @Value("${credentials.application-api-key}")
+ @Value("${credentials.application-api-key: }")
String applicationKey;
- @Value("${credentials.application-api-secret}")
+ @Value("${credentials.application-api-secret: }")
String applicationSecret;
- @Value("${sms.region}")
- String region;
+ @Value("${conversation.region: }")
+ String conversationRegion;
+
+ @Value("${sms.region: }")
+ String smsRegion;
@Bean
public SinchClient sinchClient() {
@@ -51,8 +58,15 @@ public SinchClient sinchClient() {
if (!StringUtil.isEmpty(applicationSecret)) {
builder.setApplicationSecret(applicationSecret);
}
- if (!StringUtil.isEmpty(region)) {
- builder.setSmsRegion(SMSRegion.from(region));
+
+ if (!StringUtil.isEmpty(conversationRegion)) {
+ builder.setConversationRegion(ConversationRegion.from(conversationRegion));
+ LOGGER.info(String.format("Conversation region: '%s'", conversationRegion));
+ }
+
+ if (!StringUtil.isEmpty(smsRegion)) {
+ builder.setSmsRegion(SMSRegion.from(smsRegion));
+ LOGGER.info(String.format("SMS region: '%s'", smsRegion));
}
return new SinchClient(builder.build());
diff --git a/templates/server/src/main/java/com/mycompany/app/conversation/Controller.java b/templates/server/src/main/java/com/mycompany/app/conversation/Controller.java
index e10497f..befb083 100644
--- a/templates/server/src/main/java/com/mycompany/app/conversation/Controller.java
+++ b/templates/server/src/main/java/com/mycompany/app/conversation/Controller.java
@@ -42,7 +42,7 @@ public class Controller {
private final SinchClient sinchClient;
private final ServerBusinessLogic webhooksBusinessLogic;
- @Value("${conversation.webhooks.secret}")
+ @Value("${conversation.webhooks.secret: }")
private String webhooksSecret;
@Autowired
@@ -60,12 +60,18 @@ public ResponseEntity ConversationEvent(
WebHooksService webhooks = sinchClient.conversation().v1().webhooks();
- // ensure valid authentication to handle request
- var validAuth = webhooks.validateAuthenticationHeader(webhooksSecret, headers, body);
+ // set this value to true to validate request from Sinch servers
+ // see https://developers.sinch.com/docs/numbers/api-reference/numbers/tag/Numbers-Callbacks for
+ // more information
+ boolean ensureValidAuthentication = false;
+ if (ensureValidAuthentication) {
+ // ensure valid authentication to handle request
+ var validAuth = webhooks.validateAuthenticationHeader(webhooksSecret, headers, body);
- // token validation failed
- if (!validAuth) {
- throw new ResponseStatusException(HttpStatus.UNAUTHORIZED);
+ // token validation failed
+ if (!validAuth) {
+ throw new ResponseStatusException(HttpStatus.UNAUTHORIZED);
+ }
}
// decode the request payload
diff --git a/templates/server/src/main/java/com/mycompany/app/numbers/Controller.java b/templates/server/src/main/java/com/mycompany/app/numbers/Controller.java
index 6d923c0..c6909e9 100644
--- a/templates/server/src/main/java/com/mycompany/app/numbers/Controller.java
+++ b/templates/server/src/main/java/com/mycompany/app/numbers/Controller.java
@@ -29,7 +29,7 @@ public class Controller {
* href="https://developers.sinch.com/java-sdk/apidocs/com/sinch/sdk/domains/numbers/api/v1/CallbackConfigurationService.html#update(com.sinch.sdk.domains.numbers.models.v1.callbacks.request.CallbackConfigurationUpdateRequest)">update
* function Javadoc
*/
- @Value("${numbers.webhooks.secret}")
+ @Value("${numbers.webhooks.secret: }")
private String webhooksSecret;
@Autowired
@@ -47,18 +47,24 @@ public ResponseEntity NumbersEvent(
WebHooksService webhooks = sinchClient.numbers().v1().webhooks();
- // ensure valid authentication to handle request
- var validAuth =
- webhooks.validateAuthenticationHeader(
- webhooksSecret,
- // request headers
- headers,
- // request payload body
- body);
+ // set this value to true to validate request from Sinch servers
+ // see https://developers.sinch.com/docs/numbers/api-reference/numbers/tag/Numbers-Callbacks for
+ // more information
+ boolean ensureValidAuthentication = false;
+ if (ensureValidAuthentication) {
+ // ensure valid authentication to handle request
+ var validAuth =
+ webhooks.validateAuthenticationHeader(
+ webhooksSecret,
+ // request headers
+ headers,
+ // request payload body
+ body);
- // token validation failed
- if (!validAuth) {
- throw new ResponseStatusException(HttpStatus.UNAUTHORIZED);
+ // token validation failed
+ if (!validAuth) {
+ throw new ResponseStatusException(HttpStatus.UNAUTHORIZED);
+ }
}
// decode the request payload
diff --git a/templates/server/src/main/java/com/mycompany/app/sms/Controller.java b/templates/server/src/main/java/com/mycompany/app/sms/Controller.java
index 4041044..a7f75d1 100644
--- a/templates/server/src/main/java/com/mycompany/app/sms/Controller.java
+++ b/templates/server/src/main/java/com/mycompany/app/sms/Controller.java
@@ -23,7 +23,7 @@ public class Controller {
private final SinchClient sinchClient;
private final ServerBusinessLogic webhooksBusinessLogic;
- @Value("${sms.webhooks.secret}")
+ @Value("${sms.webhooks.secret: }")
private String webhooksSecret;
@Autowired
@@ -46,11 +46,23 @@ public ResponseEntity smsDeliveryEvent(
// https://developers.sinch.com/docs/sms/api-reference/sms/tag/Webhooks/#tag/Webhooks/section/Callbacks
// Contact your account manager to configure your callback sending headers validation or comment
// following line
- var validAuth = webhooks.validateAuthenticationHeader(webhooksSecret, headers, body);
+ // set this value to true to validate request from Sinch servers
+ // see https://developers.sinch.com/docs/numbers/api-reference/numbers/tag/Numbers-Callbacks for
+ // more information
+ boolean ensureValidAuthentication = false;
+ if (ensureValidAuthentication) {
+ var validAuth =
+ webhooks.validateAuthenticationHeader(
+ webhooksSecret,
+ // request headers
+ headers,
+ // request payload body
+ body);
- // token validation failed
- if (!validAuth) {
- throw new ResponseStatusException(HttpStatus.UNAUTHORIZED);
+ // token validation failed
+ if (!validAuth) {
+ throw new ResponseStatusException(HttpStatus.UNAUTHORIZED);
+ }
}
// decode the request payload
diff --git a/templates/server/src/main/java/com/mycompany/app/verification/Controller.java b/templates/server/src/main/java/com/mycompany/app/verification/Controller.java
index ccaa633..0884904 100644
--- a/templates/server/src/main/java/com/mycompany/app/verification/Controller.java
+++ b/templates/server/src/main/java/com/mycompany/app/verification/Controller.java
@@ -39,20 +39,27 @@ public ResponseEntity VerificationEvent(
WebHooksService webhooks = sinchClient.verification().v1().webhooks();
// ensure valid authentication to handle request
- var validAuth =
- webhooks.validateAuthenticationHeader(
- // The HTTP verb this controller is managing
- "POST",
- // The URI this controller is managing
- "/VerificationEvent",
- // request headers
- headers,
- // request payload body
- body);
+ // set this value to true to validate request from Sinch servers
+ // see
+ // https://developers.sinch.com/docs/verification/api-reference/authentication/callback-signed-request
+ // for more information
+ boolean ensureValidAuthentication = false;
+ if (ensureValidAuthentication) {
+ var validAuth =
+ webhooks.validateAuthenticationHeader(
+ // The HTTP verb this controller is managing
+ "POST",
+ // The URI this controller is managing
+ "/VerificationEvent",
+ // request headers
+ headers,
+ // request payload body
+ body);
- // token validation failed
- if (!validAuth) {
- throw new ResponseStatusException(HttpStatus.UNAUTHORIZED);
+ // token validation failed
+ if (!validAuth) {
+ throw new ResponseStatusException(HttpStatus.UNAUTHORIZED);
+ }
}
// decode the request payload
diff --git a/templates/server/src/main/java/com/mycompany/app/voice/Controller.java b/templates/server/src/main/java/com/mycompany/app/voice/Controller.java
index d109765..3332507 100644
--- a/templates/server/src/main/java/com/mycompany/app/voice/Controller.java
+++ b/templates/server/src/main/java/com/mycompany/app/voice/Controller.java
@@ -42,22 +42,29 @@ public ResponseEntity VoiceEvent(
WebHooksService webhooks = sinchClient.voice().v1().webhooks();
// ensure valid authentication to handle request
- var validAuth =
- webhooks.validateAuthenticationHeader(
- // The HTTP verb this controller is managing
- "POST",
- // The URI this controller is managing
- "/VoiceEvent",
- // request headers
- headers,
- // request payload body
- body);
+ // set this value to true to validate request from Sinch servers
+ // see
+ // https://developers.sinch.com/docs/voice/api-reference/authentication/callback-signed-request
+ // for more information
+ boolean ensureValidAuthentication = false;
+ if (ensureValidAuthentication) {
+ // ensure valid authentication to handle request
+ var validAuth =
+ webhooks.validateAuthenticationHeader(
+ // The HTTP verb this controller is managing
+ "POST",
+ // The URI this controller is managing
+ "/VoiceEvent",
+ // request headers
+ headers,
+ // request payload body
+ body);
- // token validation failed
- if (!validAuth) {
- throw new ResponseStatusException(HttpStatus.UNAUTHORIZED);
+ // token validation failed
+ if (!validAuth) {
+ throw new ResponseStatusException(HttpStatus.UNAUTHORIZED);
+ }
}
-
// decode the payload request
var event = webhooks.parseEvent(body);
diff --git a/templates/server/src/main/resources/application.yaml b/templates/server/src/main/resources/application.yaml
index 3db4ba9..c94f5ee 100644
--- a/templates/server/src/main/resources/application.yaml
+++ b/templates/server/src/main/resources/application.yaml
@@ -8,9 +8,10 @@ server:
port: 8090
credentials:
- # Unified related credentials, used by:
+ # Java SDK domains supporting unified credentials
# - Numbers
- # - SMS
+ # - SMS: US/EU are the only supported regions with unified credentials
+ # - Conversation
project-id:
key-id:
key-secret:
@@ -19,19 +20,26 @@ credentials:
# - Verification
# - Voice
application-api-key:
- application-api-secret:
-
-sms:
- # Sets the region for SMS
- # valid values are US and EU
- region:
+ application-api-secret:
# Secret value set for Numbers webhooks calls validation
-numbers.webhooks.secret:
+numbers:
+ webhooks:
+ secret:
# Secret value set for Conversation webhooks calls validation
-conversation.webhooks.secret:
+conversation:
+ # Sets the region for Conversation
+ # See https://github.com/sinch/sinch-sdk-java/blob/main/client/src/main/com/sinch/sdk/models/ConversationRegion.java for list of supported values
+ region:
+ webhooks:
+ secret:
+
+sms:
+ # Sets the region for SMS
+ # valid values are "us" and "eu"
+ # See https://github.com/sinch/sinch-sdk-java/blob/main/client/src/main/com/sinch/sdk/models/SMSRegion.java for full list of supported values but with servicePlanID
+ region:
+ webhooks:
+ secret:
-# Secret value set for Conversation webhooks calls validation
-sms.webhooks.secret:
-
\ No newline at end of file