sending sms from java web app using aws sns - amazon-web-services

A user will create an account on my web app. The app will need to authenticate the user by sending a text message to the mobile phone number that the user provides. The text message is a short unique code, which the user will need to type in to the web browser in order for the app to authenticate the user.
How can I configure Amazon AWS SNS for this use case?
From what I have read, SNS works by the webmaster selecting a topic and then each user subscribes to that topic. Then the webmaster sends messages broadcast style to all the subscribers to the topic. This would not meet my requirements of sending a unique message to each user. Alternatively, creating a separate topic for every phone number would be too cumbersome, not to mention creating security issues with respect to protecting the privacy of all the phone numbers.
Can Amazon AWS SNS be configured for this use case? If so, how?
I am using Java.

SNS topics are only nedded when you need to send a SMS message to multiple mobile numbers. If you want to send a SMS message to a single number you can use the Amazon AWS SDK.
Docs are available at http://docs.aws.amazon.com/sns/latest/dg/sms_publish-to-phone.html#sms_publish_sdk.
Example code:
public static void main(String[] args) {
AWSCredentials awsCredentials = new BasicAWSCredentials("YOUR_Client_ID", "YOUR_Client_secret");
final AmazonSNSClient client = new AmazonSNSClient(awsCredentials);
client.setRegion(Region.getRegion(Regions.REGION_YOU_WANT_TO_USE));
AmazonSNSClient snsClient = new AmazonSNSClient(awsCredentials);
String message = "My SMS message";
String phoneNumber = "+1XXX5550100";
Map<String, MessageAttributeValue> smsAttributes =
new HashMap<String, MessageAttributeValue>();
//<set SMS attributes>
sendSMSMessage(snsClient, message, phoneNumber, smsAttributes);
}
public static void sendSMSMessage(AmazonSNSClient snsClient, String message,
String phoneNumber, Map<String, MessageAttributeValue> smsAttributes) {
PublishResult result = snsClient.publish(new PublishRequest()
.withMessage(message)
.withPhoneNumber(phoneNumber)
.withMessageAttributes(smsAttributes));
System.out.println(result); // Prints the message ID.
}
Remember to create an user on IAM console adding a permission to access the SNS Service. You need to add AmazonSNSFullAccess role.
Replace YOUR_Client_ID and YOUR_Client_secret with user credentials you have created.

Some methods have been deprecated in AWS SDK.
BasicAWSCredentials awsCredentials = new BasicAWSCredentials("CLIENT-ID", "SECRET-KEY");
AmazonSNS snsClient = AmazonSNSClientBuilder.standard()
.withRegion(Regions.fromName("YOUR_REGION"))
.withCredentials(new AWSStaticCredentialsProvider(awsCredentials)).build();
Map<String, MessageAttributeValue> smsAttributes = new HashMap<String, MessageAttributeValue>();
smsAttributes.put("AWS.SNS.SMS.SenderID",new MessageAttributeValue().withStringValue("SENDER-ID").withDataType("String"));
smsAttributes.put("AWS.SNS.SMS.SMSType",new MessageAttributeValue().withStringValue("Transactional").withDataType("String"));
PublishRequest request = new PublishRequest();
request.withMessage("YOUR MESSAGE")
.withPhoneNumber("E.164-PhoneNumber")
.withMessageAttributes(smsAttributes);
PublishResult result=snsClient.publish(request);

Sending an SMS using the AWS SDK for Java:
public static void main(String[] args) {
AmazonSNSClient snsClient = new AmazonSNSClient();
String message = "My SMS message";
String phoneNumber = "+1XXX5550100";
Map<String, MessageAttributeValue> smsAttributes =
new HashMap<String, MessageAttributeValue>();
//<set SMS attributes>
sendSMSMessage(snsClient, message, phoneNumber, smsAttributes);
}
public static void sendSMSMessage(AmazonSNSClient snsClient, String message,
String phoneNumber, Map<String, MessageAttributeValue> smsAttributes) {
PublishResult result = snsClient.publish(new PublishRequest()
.withMessage(message)
.withPhoneNumber(phoneNumber)
.withMessageAttributes(smsAttributes));
System.out.println(result); // Prints the message ID.
}
For this particular use case you should consider the AWS Customer Engagement Service Amazon Pinpoint. It allows sending SMS, emails and push notifications, with tools for marketing campaigns as well as analytics:
Amazon Pinpoint Developer Guide
The documentation includes a tutorial for your specific use case:
Setting Up an SMS Registration System Using Amazon Pinpoint
For what you described, while it could be done using SNS with the AWS SDK for Java, Pinpoint is designed to interact with application users, so it's probably a better alternative

Individual SMS/MMS messaging is outside the apparent use cases of AWS SNS.
If you need to send proper SMS/MMS text messages to arbitrary phone numbers, you'll need to turn to other platforms, such as Twilio or Bandwidth.

Related

AWS Lambda Java - Execute DynamoDB save and send SNS SMS in same function call

I'm trying to save an item in DynamoDB and send an OTP from the same function.
I'm able to save the data but not able to receive the OTP SMS. I guess my code is exiting the function before the SMS is sent.
I'm able to save and send SMS in two separate lambda functions but unable to merge both the logic in one. I don't know what I'm doing wrong.
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.defaultClient();
DynamoDB dynamoDb = new DynamoDB(client);
try {
JSONObject event = (JSONObject) parser.parse(reader);
if (event.get("body") != null) {
Random rnd = new Random();
String otp = String.format("%06d", rnd.nextInt(999999));
Order order = new Order((String) event.get("body"));
order.setOtp(otp);
String message = otp +" is your OTP for example.com";
AmazonSNSClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(ACCESS_KEY, SECRET_KEY)))
.build()
.publish(new PublishRequest()
.withMessage(message)
.withPhoneNumber(order.getMobile()).withMessageAttributes(smsAttributes));
dynamoDb.getTable(DYNAMODB_TABLE_NAME).putItem(new PutItemSpec().withItem(
new Item()
.withString("orderid", order.getOrderid())
.withString("mobile", order.getMobile())
.withString("otp", order.getOtp())));
}
JSONObject responseBody = new JSONObject();
responseBody.put("message", "OTP Sent !!");
JSONObject headerJson = new JSONObject();
responseJson.put("statusCode", 200);
responseJson.put("headers", headerJson);
responseJson.put("body", responseBody.toString());
} catch (ParseException pex) {
responseJson.put("statusCode", 400);
responseJson.put("exception", pex);
}
AWs Documentation says that AWS SDK could fail to send SMS due to e.g "exceeded your maximum message".
You can get the deliver status in AWS Cloudwatch by following this AWS documentation
Also, as in AWS Documentation not every region has SMS service, you can try to add Region to the SNS, e.g:
AmazonSNSClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(ACCESS_KEY, SECRET_KEY)))
.withRegion(Regions.EU_WEST_1)
.build()
.publish(new PublishRequest()
.withMessage(message)
.withPhoneNumber(order.getMobile()).withMessageAttributes(smsAttributes));

AWS SNS OTP emails

I am working on sending OTP messages for user login leveraging Amazon SNS. I am able to send Text message as suggesting here. For the email notification as well I would like to use a similar approach. But looks like for email notifications, a topic has to be created in SNS and a subscriber has to be created for each email id registered in the application.
Is it not possible to send email to mail-id dynamically as done for text messages without creating topics and subscribers? If not please suggest a way to set email id dynamically based on the user logged in.
Code for Text Messaging:
public static void main(String[] args) {
AmazonSNSClient snsClient = new AmazonSNSClient();
String message = "My SMS message";
String phoneNumber = "+1XXX5550100";
Map<String, MessageAttributeValue> smsAttributes =
new HashMap<String, MessageAttributeValue>();
//<set SMS attributes>
sendSMSMessage(snsClient, message, phoneNumber, smsAttributes);
}
public static void sendSMSMessage(AmazonSNSClient snsClient, String message,
String phoneNumber, Map<String, MessageAttributeValue> smsAttributes) {
PublishResult result = snsClient.publish(new PublishRequest()
.withMessage(message)
.withPhoneNumber(phoneNumber)
.withMessageAttributes(smsAttributes));
System.out.println(result); // Prints the message ID.
}
Correct.
Amazon SNS normally uses a Public/Subscribe model for messages.
The one exception is the ability to send an SMS message to a specific recipient.
If you wish to send an email to a single recipient, you will need to use your own SMTP server, or use Amazon Simple Email Service (Amazon SES).

AWS SNS Endpoint not sending sms after 9 pm IST

I am using AWS SDK to send the sms to the mobile number for sending OTP through the SMS.
The Issue here I am facing is the SMS are only being sent during the day time according to Indian Standard Time (9 am to 9pm). If I try to send SMS request to the AWS SNS endpoint after 9 pm, then it will send the message after 9 am the next day.
The code is as below.
String ACCESS_KEY = env.getProperty("aws.access.key");
String SECRET_KEY = env.getProperty("aws.secret.access.key");
// Above we get the access and secret access key as credentials for the user.
String otp = getRandomNumberString(); // generates an OTP number of 4 digit
AmazonSNSClient snsClient = new AmazonSNSClient(new BasicAWSCredentials(ACCESS_KEY,
SECRET_KEY));
String message = "Your Connect OTP for Login/Signup is: " + otp
+ ".\nNote: Please DO NOT SHARE THIS OTP with anyone.\nThanks";
String phoneNumber = "+91" + String.valueOf(mobile); // Ex: +91XXX4374XX
String messageID = sendSMSMessage(snsClient, message, phoneNumber);
// The definition of method named "sendSMSMessage" as above is written below in next code block
//definition of method named "sendSMSMessage"
public static String sendSMSMessage(AmazonSNSClient snsClient, String message, String phoneNumber) {
PublishResult result = snsClient
.publish(new PublishRequest().withMessage(message).withPhoneNumber(phoneNumber));
return result.getMessageId();
}
There are two types of SMS that you can send.
-Promotional Messages
-Transaction Messages
Promotional messages are like Advertisment. These Messges will not be delivered to DND numbers and also these messages can only be delivered between 9Am to 9PM as per NCPR guidelines.
Transaction Messages are sent for Transaction purpose like sending OTP and sending Payment confirmation. These messages can be delivered to any number 24/7.
So the problem is you need to change your SMS type to Transaction SMS

Send and Receive sms through Java in RingCentral

I am quite new to the ringcentral APIs and currently going through all of them.
Currently going through the following reference: https://developers.ringcentral.com/api-reference/SMS/createSMSMessage
Through Java we can use an API to send SMS, but can we receive a SMS using Java.
Can someone help me in getting the documentation/article or any kind of reference where I can get to know the simple way to send and receive the SMS using Java
A sample send SMS example with Java as follows:
import java.io.IOException;
import com.ringcentral.*;
import com.ringcentral.definitions.*;
public class Send_SMS {
String RECIPIENT_NUMBER = "<ENTER PHONE NUMBER>";
String RINGCENTRAL_CLIENTID = "<ENTER CLIENT ID>";
String RINGCENTRAL_CLIENTSECRET = "<ENTER CLIENT SECRET>";
String RINGCENTRAL_USERNAME = "<YOUR ACCOUNT PHONE NUMBER>";
String RINGCENTRAL_PASSWORD = "<YOUR ACCOUNT PASSWORD>";
String RINGCENTRAL_EXTENSION = "<YOUR EXTENSION, PROBABLY ";
public static void main(String[] args) {
var obj = new Send_SMS();
try {
obj.sendSms();
} catch (RestException | IOException e) {
e.printStackTrace();
}
}
public void sendSms() throws RestException, IOException{
RestClient rc = new RestClient(RINGCENTRAL_CLIENTID, RINGCENTRAL_CLIENTSECRET, RINGCENTRAL_SERVER);
rc.authorize(RINGCENTRAL_USERNAME, RINGCENTRAL_EXTENSION, RINGCENTRAL_PASSWORD);
CreateSMSMessage postParameters = new CreateSMSMessage();
postParameters.from = new MessageStoreCallerInfoRequest().phoneNumber(RINGCENTRAL_USERNAME);
postParameters.to = new MessageStoreCallerInfoRequest[]{new MessageStoreCallerInfoRequest().phoneNumber(RECIPIENT_NUMBER)};
postParameters.text = "Hello World from Java";
var response = rc.restapi().account().extension().sms().post(postParameters);
System.out.println("SMS sent. Message status: " + response.messageStatus);
}
}
You can download the java SDK from here: https://github.com/ringcentral/ringcentral-java
and start with documentation here: https://developers.ringcentral.com/guide/messaging/quick-start/java
Once you get the library in your application, you can start compiling it and running it.
Here is a SMS Java quickstart guide: https://developers.ringcentral.com/guide/sms/quick-start/java
Hope this helps!
Here is the official RingCentral Java SDK: https://github.com/ringcentral/ringcentral-java, it is currently 1.0.0-beta9. We are going to release a stable version this month.
Here is a list of all the API calls that you can invoke: https://github.com/ringcentral/ringcentral-java/blob/master/samples.md, including sms sending: https://github.com/ringcentral/ringcentral-java/blob/master/samples.md#create-smsmms-message
For sms receiving, you can use our subscription and notification feature: https://github.com/ringcentral/ringcentral-java#pubnub-subscriptions--notificatioins
So whenever there is new sms, you will be notified, then you can issue api call to get the message.
For technical details, you can always send email to devsupport#ringcentral.com

SMS can not send by SDK without any exception (it works with AWS Web Console)

I'm using the AWS to send SMS via my app.
I can send SMS via AWS web console, however, sending SMS via SDK is not successfull, without any exception information, the status of sending request is 200 and still receiving the returned value of AWS_REQUEST_ID.
AmazonSNSClient snsClient = new AmazonSNSClient(new BasicAWSCredentials(accessKey, secretKey));
Map<String, MessageAttributeValue> smsAttributes = new HashMap<String, MessageAttributeValue>();
smsAttributes.put("AWS.SNS.SMS.SenderID", new MessageAttributeValue()
.withStringValue("mySenderID") //The sender ID shown on the device.
.withDataType("String"));
smsAttributes.put("AWS.SNS.SMS.MaxPrice", new MessageAttributeValue()
.withStringValue("1") //Sets the max price to 0.50 USD.
.withDataType("Number"));
// Sets the type to promotional
smsAttributes.put("AWS.SNS.SMS.SMSType",
new MessageAttributeValue().withStringValue("Promotional").withDataType("String"));
JSONObject smsService = (JSONObject) new JSONObject(json).get("smsService");
String phoneNumber = smsService.getString("phoneNumber");
String message = smsService.getString("message");
PublishResult result = snsClient.publish(new PublishRequest().withMessage(message).withPhoneNumber(phoneNumber)
.withMessageAttributes(smsAttributes));
LOGGER.info("Message ID: {}", result); // Prints the message ID.
After for a while of researching, I detect that the root cause is the budget is over, so I can not send SMS anymore (I track the log to detect it).