A simple way for sending SMS via sms.ru with Java.
At first sign up on sms.ru and receive your api_id, login, password which would be needed for authenticating your requests. sms.ru API description, unfortunately the page is still only in Russian.
Use SenderServiceConfigurationBuilder to create SenderServiceConfiguration which should be passed as argument into constructor of SenderService or AsyncSenderService.
There are necessary fields in configuration, which are used by authentication provider you picked. Authentication providers are implementations of AuthProvider, by default DefaultAuthProvider is used.
CloseableHttpClient, AuthProvider class to use, SenderService to use in the AsyncSenderService, list of retry policies and other params are arbitrary in SenderServiceConfiguration.
SenderService and AsyncSenderService throw IllegalStateException during construction if some necessary fields are missing.
Configuration parameters could be set from java code or loaded from the FileInputStream or Properties object
SenderServiceConfiguration senderConfiguration = SenderServiceConfigurationBuilder.create()
.load(new FileInputStream("test.properties"))
.build();
Library has sync and async services
- SenderService executes the request parse response and retries request if needed in the same thread
- AsyncSenderService works asynchronously using ExecutorService from the configuration or
Executors.newSingleThreadExecutor()
if no ExecutorService was provided. Async service has twoexecute(...)
methods: the first one returns Future, the second has an optional argument array of ApiCallback which would be called after receiving and parsing response from the API.
For further information look at the "Usage examples" section located at the end of the file.
All requests extend ApiRequest class, which has number of execution attempts, [InvocationStatus] (https://github.com/dezhik/sms-sender/blob/master/src/main/java/ru/dezhik/sms/sender/api/InvocationStatus.java) status, exception which would be set iff status.isAbnormal() and attachment.
Attachment could be usefull if you use AsyncSenderService with callbacks and want to use some additional information related with request in callbacks, e.g. id of DB row which corresponds to the SMS sending.
Responses extend ApiResponse class, which contains plain response of the remote system (if this option is enabled in configuration) and response status specific to remote API.
- SMSRuSendRequest — sends a message to a single or multiple receivers.
- SMSRuBatchSendRequest — sends different messages to a single or different receivers.
- SMSRuSendersRequest
- SMSRuStatusRequest — checks status of previously sent message.
- SMSRuCostRequest — determines the price of the message for the selected receiver.
- SMSRuStopListAddRequest — adds phone to the black list.
- SMSRuStopListDeleteRequest — deletes phone from the black list.
- SMSRuStopListGetRequest — fetches the whole black list.
SMSRuResponseStatus is the enum containing possible response statuses of sms.ru API. Each status has a comment explaining the situation then it could be received. For further and more accurate information go to the sms.ru API description page.
There are 3 ways for authenticating your API requests:
- DefaultAuthProvider — uses api_id. This provider is used by default
- PasswordAuthProvider — uses password and login.
- TokenAuthProvider — fetches api token using api_id and then authenticates each request with SHA-512 digest of password and token.
You can add policies/conditions under which the request should be retried and specify a delay before next retry. All retry policies should implement [RetryPolicy] (https://github.com/dezhik/sms-sender/blob/master/src/main/java/ru/dezhik/sms/sender/RetryPolicy.java) interface. SenderServiceConfigurationBuilder addRetryPolicy(RetryPolicy)
By default there is only a NetworkErrorRetryPolicy
Don't forget to shutdown sender service during shutting down your application, use shutdown()
for this.
This is especially necessary if you use AsyncSenderService, which has ExecutorService under the hood.
There is a special setting for AsyncSenderService shutdown()
in SenderServiceConfiguration, asyncTerminationTimeoutMs
which specifies how much time to wait befare call shutdownNow()
on the ExecutorService if it still has running threads.
The most efficient way to use the library is to create SenderService or AsyncSenderService instance once then share it between threads and use numerous times.
Creating simple SenderServiceConfiguration. Note that you should provide your own ApiID:
SenderServiceConfiguration config = SenderServiceConfigurationBuilder.create()
.setApiId("00000000-0000-0000-0000-000000000000")
.setTestSendingEnabled(true)
.setReturnPlainResponse(true)
.build();
Synchronous SMSRuCostRequest execution example:
SenderService sender = new SenderService(senderConfiguration);
SMSRuCostRequest sendRequest = new SMSRuCostRequest();
sendRequest.setReceiver("+79123456789");
sendRequest.setText("Hello world");
SMSRuCostResponse getCostResponse = sender.execute(sendRequest);
if (sendRequest.getStatus() == InvocationStatus.SUCCESS) {
/**
* request was executed successfully now you can handle sendResponse
* always check service API manual page for determine which codes should be treated as successful
*/
if (getCostResponse.getResponseStatus() == SMSRuResponseStatus.IN_QUEUE) {
System.out.println(String.format("Success. Price %4.2f, smsNeeded %d", getCostResponse.getPrice(), getCostResponse.getSmsNeeded()));
} else {
System.out.println(String.format("Failed with status %s", getCostResponse.getResponseStatus()));
}
} else {
/**
* Something went wrong and request failed, check sendRequest.getStatus()
* usually the problem is in params validation or network or parsing response from the remote API.
* {@link ru.dezhik.sms.sender.api.InvocationStatus}
*/
if (sendRequest.getStatus().isAbnormal()) {
sendRequest.getException().printStackTrace();
}
}
...
sender.shutdown();
Synchronous SMSRuSendRequest execution example:
SenderService sender = new SenderService(config);
SMSRuSendRequest sendRequest = new SMSRuSendRequest();
sendRequest.setReceivers(Collections.singleton("+79123456789"));
sendRequest.setText("Hello world");
SMSRuSendResponse sendResponse = sender.execute(sendRequest);
if (sendRequest.getStatus() == InvocationStatus.SUCCESS) {
/**
* request was executed successfully now you can handle sendResponse
* always check service API manual page for determine which codes should be treated as successful
*/
if (sendResponse.getResponseStatus() == SMSRuResponseStatus.IN_QUEUE) {
System.out.println(String.format("Success. Balance %4.2f, smsIds %s",
sendResponse.getBalance(), Arrays.toString(sendResponse.getMsgIds().toArray())));
} else {
System.out.println(String.format("Failed with status %s", sendResponse.getResponseStatus()));
}
} else {
/**
* Something went wrong and request failed, check sendRequest.getStatus()
* usually the problem is in params validation or network or parsing response from the remote API.
* {@link ru.dezhik.sms.sender.api.InvocationStatus}
*/
if (sendRequest.getStatus().isAbnormal()) {
sendRequest.getException().printStackTrace();
}
}
Simple asynchronous request execution:
AsyncSenderService asyncSender = new AsyncSenderService(senderConfiguration);
SMSRuCostRequest sendRequest = new SMSRuCostRequest();
sendRequest.setReceiver("+79123456789");
sendRequest.setText("Hello world");
Future<SMSRuSendResponse> sendFuture = asyncSender.execute(sendResponse);
...
SMSRuSendResponse sendResponse = sendFuture.get();
if (sendRequest.getStatus() == InvocationStatus.SUCCESS) {
;//request was executed successfully now you can handle sendResponse
}
...
asyncSender.shutdown();
Asynchronous request execution with callbacks, ApiCallback:
AsyncSenderService asyncSender = new AsyncSenderService(senderConfiguration);
SMSRuCostRequest sendRequest = new SMSRuCostRequest();
sendRequest.setReceiver("+79123456789");
sendRequest.setText("Hello world");
ApiCallback successCallback = new ApiCallback() {
@Override
public boolean apply(ApiRequest request, SimpleResponse response) {
return request.getStatus() == InvocationStatus.SUCCESS;
}
@Override
public void execute(ApiRequest request, SimpleResponse response) {
//handle successful request, e.g. update sms status in your database or smth else
}
};
ApiCallback failCallback = new ApiCallback() {
@Override
public boolean apply(ApiRequest request, SimpleResponse response) {
return request.getStatus() != InvocationStatus.SUCCESS;
}
@Override
public void execute(ApiRequest request, SimpleResponse response) {
//handle failed request, e.g. print error or try to send email instead of sms
}
};
asyncSender.execute(sendResponse, successCallback, failCallback);
...
asyncSender.shutdown();