plugins {
id 'org.springframework.boot' version '2.3.0.RELEASE'
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
id 'java'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
test {
useJUnitPlatform()
}
2factor SMS in Spring Boot App
Upasana | July 11, 2020 | 3 min read | 87 views
Send 2factor transactional sms in Spring Boot application using Java 11 HttpClient, OkHttp Client and RestTemplate
First of all make sure that you have an active account at https://2factor.in and have SMS templates configured/approved for use. You need to get Api Key from 2factor in order to send SMS programmatically.
Perquisites
-
Java 11
-
Spring Boot 2.3
-
IDE (Eclipse or IntelliJ IDEA)
-
Account at https://2factor.in
Creating Spring Boot project
We can quickly create a gradle based spring boot starter using https://start.spring.io/
we will use three different clients to communicate to 2factor API in this tutorial:
-
Java 11 HttpClient
-
OkHttp Client
-
Spring restTemplate
Java 11 HttpClient
Java 11 ships inbuilt Java HttpClient that can be used for making remote service calls.
First of all we will create a single HttpClient bean which will be reused across components for making remote calls.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.net.http.HttpClient;
@Configuration
public class HttpClientConfig {
@Bean
public HttpClient createClient() {
HttpClient client = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_2)
.followRedirects(HttpClient.Redirect.NORMAL)
.build();
return client;
}
}
Now we will create a service that used HttpClient to send a transactional SMS using 2factor service provider.
@Service
class Scratch (private val httpClient: HttpClient) {
fun sendSms() {
val apiKey = "<insert your api key here>"
val data: MutableMap<String, String> = HashMap()
data["To"] = "mobile"
data["From"] = "SHUNYA"
data["TemplateName"] = "TEMPLATE-NAME"
data["VAR1"] = "1234"
data["VAR2"] = "testhash"
val request: HttpRequest = HttpRequest.newBuilder()
.POST(ofFormData(data))
.uri(URI.create("https://2factor.in/API/V1/$apiKey/ADDON_SERVICES/SEND/TSMS"))
.header("User-Agent", "Java 11 HttpClient")
.header("Content-Type", "application/x-www-form-urlencoded")
.build()
val response: HttpResponse<String> = httpClient.send(request, HttpResponse.BodyHandlers.ofString())
println(response.statusCode())
println(response.body())
}
fun ofFormData(data: Map<String, String>): BodyPublisher? {
val builder = StringBuilder()
for ((key, value) in data) {
if (builder.isNotEmpty()) {
builder.append("&")
}
builder.append(URLEncoder.encode(key, StandardCharsets.UTF_8))
builder.append("=")
builder.append(URLEncoder.encode(value, StandardCharsets.UTF_8))
}
return HttpRequest.BodyPublishers.ofString(builder.toString())
}
}
OkHttpClient
We will create a OkHttpClient bean that will be used across the project wherever necessary, using dependency injection.
@Configuration
class OkHttpConfig {
@Bean
fun okHttpClient(): OkHttpClient {
return OkHttpClient.Builder()
.readTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.addInterceptor(HttpLoggingInterceptor())
.build()
}
}
Now in order to send SMS using 2factor service provider, we will develop a component that used OkHttpClient bean to make remote service call.
class Scratch (private val okHttpClient: OkHttpClient){
fun sendSms() {
try {
val apiKey = "<insert API key here>"
val build = MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("To", "mobile")
.addFormDataPart("From", "SHUNYA")
.addFormDataPart("TemplateName", "TEMPLATE-NAME")
.addFormDataPart("VAR1", otp)
.build()
val request = Request.Builder()
.url("https://2factor.in/API/V1/$apiKey/ADDON_SERVICES/SEND/TSMS")
.post(build)
.build()
okHttpClient.newCall(request).execute().use { response ->
if (!response.isSuccessful) {
logger.warn("Error sending SMS {}", response.body?.string())
throw IOException("Unexpected code $response")
}
logger.info("SMS Status - {}", response.body?.string())
}
} catch (e: Exception) {
logger.warn("Error sending SMS", e)
throw e
}
}
}
RestTemplate
We will use RestTemplate to fetch balance of SMS from 2factor account.
fun getPromoBalance() {
val restTemplate= RestTemplate()
val responseEntity = restTemplate.exchange("http://2factor.in/API/V1/$apiKey/ADDON_SERVICES/BAL/PROMOTIONAL_SMS", HttpMethod.GET, HttpEntity.EMPTY, String::class.java)
if (responseEntity.statusCode.is2xxSuccessful) {
val body = responseEntity.body
logger.info("Promotional SMS Balance is {}", body)
}
}
References
Top articles in this category:
- Using Asciidoctor in Java and Spring Boot
- how to enable asciimath formula using mathjax in asciidoctorJ
- Asciidoc: How to use nofollow option in asciidoc document
- Reverting default shell to bash from Zsh in Mac OS Catalina
- Integrating PayUmoney with your Java Server Side
- Integrating PayUmoney Webhooks with your Java backend