diff --git a/client/src/main/com/sinch/sdk/domains/sms/BatchesService.java b/client/src/main/com/sinch/sdk/domains/sms/BatchesService.java index 98174434..56f83865 100644 --- a/client/src/main/com/sinch/sdk/domains/sms/BatchesService.java +++ b/client/src/main/com/sinch/sdk/domains/sms/BatchesService.java @@ -19,8 +19,9 @@ public interface BatchesService { /** - * Get a batch message
- * This operation returns a specific batch that matches the provided batch ID. + * Get a batch message. + * + *

This operation returns a specific batch that matches the provided batch ID. * * @param batchId The batch ID you received from sending a message * @param A type of Batch @@ -32,9 +33,10 @@ public interface BatchesService { > T get(String batchId) throws ApiException; /** - * Send a message or a batch of messages
- * Depending on the length of the body, one message might be split into multiple parts and charged - * accordingly.
+ * Send a message or a batch of messages. + * + *

Depending on the length of the body, one message might be split into multiple parts and + * charged accordingly.
* Any groups targeted in a scheduled batch will be evaluated at the time of sending. If a group * is deleted between batch creation and scheduled date, it will be considered empty.
* Be sure to use the correct region in the server URL. @@ -49,8 +51,9 @@ public interface BatchesService { > T send(BaseBatch batch) throws ApiException; /** - * Dry run
- * This operation will perform a dry run of a batch which calculates the bodies and number of + * Dry run. + * + *

This operation will perform a dry run of a batch which calculates the bodies and number of * parts for all messages in the batch without actually sending any messages. * * @param perRecipient Whether to include per recipient details in the response @@ -66,9 +69,10 @@ DryRun dryRun(boolean perRecipient, int numberOfRecipient, BaseBatch batch) throws ApiException; /** - * List Batches
- * With the list operation you can list batch messages created in the last 14 days that you have - * created. This operation supports pagination. + * List Batches. + * + *

With the list operation you can list batch messages created in the last 14 days that you + * have created. This operation supports pagination. * * @param parameters Query parameters filtering returned batches * @return Paginated list of Batches @@ -79,8 +83,10 @@ DryRun dryRun(boolean perRecipient, int numberOfRecipient, BaseBatch batch) BatchesListResponse list(BatchesListRequestParameters parameters) throws ApiException; /** - * Update a Batch message
- * This operation updates all specified parameters of a batch that matches the provided batch ID. + * Update a Batch message. + * + *

This operation updates all specified parameters of a batch that matches the provided batch + * ID. * * @param batchId The batch ID you received from sending a message * @param batch Batch parameters to be updated @@ -94,9 +100,10 @@ > T update(String batchId, UpdateBaseBatchRequest batch) throws ApiException; /** - * Replace a batch
- * This operation will replace all the parameters of a batch with the provided values. It is the - * same as cancelling a batch and sending a new one instead. + * Replace a batch . + * + *

This operation will replace all the parameters of a batch with the provided values. It is + * the same as cancelling a batch and sending a new one instead. * * @param batchId The batch ID you received from sending a message * @param batch Batch parameters to be used @@ -109,8 +116,9 @@ > T update(String batchId, UpdateBaseBatchRequest batch) > T replace(String batchId, BaseBatch batch) throws ApiException; /** - * Cancel a batch message
- * A batch can be canceled at any point. If a batch is canceled while it's currently being + * Cancel a batch message. + * + *

A batch can be canceled at any point. If a batch is canceled while it's currently being * delivered some messages currently being processed might still be delivered. The delivery report * will indicate which messages were canceled and which weren't.
* Canceling a batch scheduled in the future will result in an empty delivery report while @@ -126,7 +134,7 @@ > T update(String batchId, UpdateBaseBatchRequest batch) > T cancel(String batchId) throws ApiException; /** - * Send delivery feedback for a message + * Send delivery feedback for a message. * *

Send feedback if your system can confirm successful message delivery. * diff --git a/client/src/main/com/sinch/sdk/domains/sms/DeliveryReportsService.java b/client/src/main/com/sinch/sdk/domains/sms/DeliveryReportsService.java index 49c3cd36..84879c27 100644 --- a/client/src/main/com/sinch/sdk/domains/sms/DeliveryReportsService.java +++ b/client/src/main/com/sinch/sdk/domains/sms/DeliveryReportsService.java @@ -8,7 +8,7 @@ import com.sinch.sdk.domains.sms.models.responses.DeliveryReportsListResponse; /** - * Delivery reports Service + * Delivery reports Service. * *

The REST API uses message statuses and error codes in delivery reports, which refer to the * state of the batch and can be present in either - * Delivery reports can be retrieved even if no callback was requested. The difference between a - * summary and a full report is only that the full report contains the phone numbers in Delivery reports can be retrieved even if no callback was requested. The difference between + * a summary and a full report is only that the full report contains the phone numbers in E.164 format for each status * code. * @@ -40,8 +41,9 @@ DeliveryReportBatch get(String batchId, DeliveryReportBatchGetRequestParameters throws ApiException; /** - * Retrieve a recipient delivery report
- * A recipient delivery report contains the message status for a single recipient phone number. + * Retrieve a recipient delivery report. + * + *

A recipient delivery report contains the message status for a single recipient phone number. * * @param batchId The batch ID you received from sending a message param type param status param * code @@ -54,8 +56,9 @@ DeliveryReportBatch get(String batchId, DeliveryReportBatchGetRequestParameters DeliveryReportRecipient getForNumber(String batchId, String recipient) throws ApiException; /** - * Get a list of finished delivery reports.
- * This operation supports pagination. + * Get a list of finished delivery reports. + * + *

This operation supports pagination. * * @param parameters Filtering parameters * @return Delivery report related to batchId according to filters diff --git a/client/src/main/com/sinch/sdk/domains/sms/GroupsService.java b/client/src/main/com/sinch/sdk/domains/sms/GroupsService.java index 8111bb1e..e0252a2a 100644 --- a/client/src/main/com/sinch/sdk/domains/sms/GroupsService.java +++ b/client/src/main/com/sinch/sdk/domains/sms/GroupsService.java @@ -23,7 +23,7 @@ public interface GroupsService { /** - * Retrieve a group + * Retrieve a group. * *

This operation retrieves a specific group with the provided group ID. * @@ -36,7 +36,7 @@ public interface GroupsService { Group get(String groupId) throws ApiException; /** - * Create a group + * Create a group. * *

A group is a set of phone numbers (MSISDNs) that can be used as a target in the * send_batch_msg operation. An MSISDN can only occur once in a group and any attempts to @@ -50,6 +50,12 @@ public interface GroupsService { */ Group create(GroupCreateRequestParameters parameters) throws ApiException; + /** + * Create an unnamed and empty group + * + * @return See {@link #create(GroupCreateRequestParameters)} + * @since 1.0 + */ Group create() throws ApiException; /** @@ -68,6 +74,12 @@ public interface GroupsService { */ GroupsListResponse list(GroupsListRequestParameters parameters) throws ApiException; + /** + * List groups with default parameters + * + * @return See {@link #list(GroupsListRequestParameters)} + * @since 1.0 + */ GroupsListResponse list() throws ApiException; /** diff --git a/client/src/main/com/sinch/sdk/domains/sms/WebHooksService.java b/client/src/main/com/sinch/sdk/domains/sms/WebHooksService.java index 185ada01..1597965f 100644 --- a/client/src/main/com/sinch/sdk/domains/sms/WebHooksService.java +++ b/client/src/main/com/sinch/sdk/domains/sms/WebHooksService.java @@ -1,8 +1,7 @@ package com.sinch.sdk.domains.sms; import com.sinch.sdk.core.exceptions.ApiMappingException; -import com.sinch.sdk.domains.sms.models.BaseDeliveryReport; -import com.sinch.sdk.domains.sms.models.Inbound; +import com.sinch.sdk.domains.sms.models.webhooks.WebhooksEvent; /** * WebHooks @@ -41,63 +40,11 @@ public interface WebHooksService { /** - * Incoming SMS WebHook + * Parse and un-serialize incoming webhooks payload * - *

An inbound message is a message sent to one of your short codes or long numbers from a - * mobile phone. To receive inbound message callbacks, a URL needs to be added to your REST API. - * This URL can be specified in your Dashboard. - * - * @param jsonPayload The incoming message to your sinch number - * @return Decoded payload - * @see https://developers.sinch.com/docs/sms/api-reference/sms/tag/Webhooks/#tag/Webhooks/operation/incomingSMS - * @since 1.0 - */ - Inbound incomingSMS(String jsonPayload) throws ApiMappingException; - - /** - * Delivery Report WebHook - * - *

A delivery report contains the status and status code for each recipient of a batch. To get - * a delivery report callback for a message or batch of messages, set the delivery_report - * field accordingly when creating a batch. - * - *

The following is provided so you can better understand our webhooks/callbacks. Configuration - * of both webhooks and the type of delivery report requested happens when sending a batch. - * - *

Callback URL - * - *

The callback URL can either be provided for each batch or provisioned globally for your - * account in your Sinch Customer - * Dashboard. Learn how to configure a webhook/callback here - * - *

Type - * - *

The type is the type of delivery report webhook. The response will vary - * depending on the webhook delivery report you selected when the batch was sent, so choose the - * appropriate selection under "One of". - * - *

- * - * @param jsonPayload The incoming delivery report - * @return Decoded payload - * @see https://developers.sinch.com/docs/sms/api-reference/sms/tag/Webhooks/#tag/Webhooks/operation/deliveryReport - * @since 1.0 + * @param jsonPayload The incoming payload received onto webhooks call + * @return Un serialized object instance (see inherited classes) and {@link + * com.sinch.sdk.domains.sms.models.webhooks package documentation} */ - BaseDeliveryReport deliveryReport(String jsonPayload) throws ApiMappingException; + WebhooksEvent parse(String jsonPayload) throws ApiMappingException; } diff --git a/client/src/main/com/sinch/sdk/domains/sms/adapters/WebHooksService.java b/client/src/main/com/sinch/sdk/domains/sms/adapters/WebHooksService.java index 7cd2c35e..c5c64705 100644 --- a/client/src/main/com/sinch/sdk/domains/sms/adapters/WebHooksService.java +++ b/client/src/main/com/sinch/sdk/domains/sms/adapters/WebHooksService.java @@ -12,55 +12,59 @@ import com.sinch.sdk.domains.sms.models.dto.v1.MOBinaryDto; import com.sinch.sdk.domains.sms.models.dto.v1.MOTextDto; import com.sinch.sdk.domains.sms.models.dto.v1.RecipientDeliveryReportDto; +import com.sinch.sdk.domains.sms.models.webhooks.WebhooksEvent; import java.util.Objects; public class WebHooksService implements com.sinch.sdk.domains.sms.WebHooksService { - @Override - public Inbound incomingSMS(String jsonPayload) throws ApiMappingException { + public WebhooksEvent parse(String jsonPayload) throws ApiMappingException { + + WebhooksEvent event; try { - MOBinaryDto binary = Mapper.getInstance().readValue(jsonPayload, MOBinaryDto.class); - if (null != binary - && (Objects.equals(binary.getType(), MOBinaryDto.TypeEnum.MO_BINARY.getValue()))) { - return InboundsDtoConverter.convert(binary); + event = incomingSMS(jsonPayload); + if (null == event) { + event = deliveryReport(jsonPayload); } - MOTextDto text = Mapper.getInstance().readValue(jsonPayload, MOTextDto.class); - if (null != text && (Objects.equals(text.getType(), MOTextDto.TypeEnum.MO_TEXT.getValue()))) { - return InboundsDtoConverter.convert(text); + if (null == event) { + throw new ApiMappingException(jsonPayload, null); } - throw new ApiMappingException(jsonPayload, null); - } catch (JsonProcessingException e) { throw new ApiMappingException(jsonPayload, e); } + return event; } - @Override - public BaseDeliveryReport deliveryReport(String jsonPayload) throws ApiMappingException { - try { - // Can we convert payload to Recipient DeliveryReport or Batch Delivery Report ? - RecipientDeliveryReportDto recipient = - Mapper.getInstance().readValue(jsonPayload, RecipientDeliveryReportDto.class); - if (null != recipient - && (Objects.equals( - recipient.getType(), RecipientDeliveryReportDto.TypeEnum.MMS.getValue()) - || Objects.equals( - recipient.getType(), RecipientDeliveryReportDto.TypeEnum.SMS.getValue()))) { - return DeliveryReportDtoConverter.convert(recipient); - } - - DeliveryReportDto batch = - Mapper.getInstance().readValue(jsonPayload, DeliveryReportDto.class); - if (null != batch - && (Objects.equals(batch.getType(), TypeEnum.MMS.getValue()) - || Objects.equals(batch.getType(), TypeEnum.SMS.getValue()))) { - return DeliveryReportDtoConverter.convert(batch); - } + private Inbound incomingSMS(String jsonPayload) throws JsonProcessingException { + MOBinaryDto binary = Mapper.getInstance().readValue(jsonPayload, MOBinaryDto.class); + if (null != binary + && (Objects.equals(binary.getType(), MOBinaryDto.TypeEnum.MO_BINARY.getValue()))) { + return InboundsDtoConverter.convert(binary); + } + MOTextDto text = Mapper.getInstance().readValue(jsonPayload, MOTextDto.class); + if (null != text && (Objects.equals(text.getType(), MOTextDto.TypeEnum.MO_TEXT.getValue()))) { + return InboundsDtoConverter.convert(text); + } + return null; + } - throw new ApiMappingException(jsonPayload, null); + private BaseDeliveryReport deliveryReport(String jsonPayload) throws JsonProcessingException { + // Can we convert payload to Recipient DeliveryReport or Batch Delivery Report ? + RecipientDeliveryReportDto recipient = + Mapper.getInstance().readValue(jsonPayload, RecipientDeliveryReportDto.class); + if (null != recipient + && (Objects.equals(recipient.getType(), RecipientDeliveryReportDto.TypeEnum.MMS.getValue()) + || Objects.equals( + recipient.getType(), RecipientDeliveryReportDto.TypeEnum.SMS.getValue()))) { + return DeliveryReportDtoConverter.convert(recipient); + } - } catch (JsonProcessingException e) { - throw new ApiMappingException(jsonPayload, e); + DeliveryReportDto deliveryReport = + Mapper.getInstance().readValue(jsonPayload, DeliveryReportDto.class); + if (null != deliveryReport + && (Objects.equals(deliveryReport.getType(), TypeEnum.MMS.getValue()) + || Objects.equals(deliveryReport.getType(), TypeEnum.SMS.getValue()))) { + return DeliveryReportDtoConverter.convert(deliveryReport); } + return null; } } diff --git a/client/src/main/com/sinch/sdk/domains/sms/models/BaseDeliveryReport.java b/client/src/main/com/sinch/sdk/domains/sms/models/BaseDeliveryReport.java index 2b426013..f78640d0 100644 --- a/client/src/main/com/sinch/sdk/domains/sms/models/BaseDeliveryReport.java +++ b/client/src/main/com/sinch/sdk/domains/sms/models/BaseDeliveryReport.java @@ -1,5 +1,6 @@ package com.sinch.sdk.domains.sms.models; +import com.sinch.sdk.domains.sms.models.webhooks.WebhooksEvent; import java.util.Objects; import java.util.Optional; @@ -8,7 +9,7 @@ * * @since 1.0 */ -public abstract class BaseDeliveryReport { +public abstract class BaseDeliveryReport implements WebhooksEvent { private final String batchId; private final String clientReference; diff --git a/client/src/main/com/sinch/sdk/domains/sms/models/Inbound.java b/client/src/main/com/sinch/sdk/domains/sms/models/Inbound.java index 2c71c310..c32a37d9 100644 --- a/client/src/main/com/sinch/sdk/domains/sms/models/Inbound.java +++ b/client/src/main/com/sinch/sdk/domains/sms/models/Inbound.java @@ -1,5 +1,6 @@ package com.sinch.sdk.domains.sms.models; +import com.sinch.sdk.domains.sms.models.webhooks.WebhooksEvent; import java.time.Instant; import java.util.Optional; @@ -9,7 +10,7 @@ * @param Type of body * @since 1.0 */ -public abstract class Inbound { +public abstract class Inbound implements WebhooksEvent { private final T body; private final String from; diff --git a/client/src/main/com/sinch/sdk/domains/sms/models/requests/InboundsListRequestParameters.java b/client/src/main/com/sinch/sdk/domains/sms/models/requests/InboundsListRequestParameters.java index 3ea1de4a..d72abcfe 100644 --- a/client/src/main/com/sinch/sdk/domains/sms/models/requests/InboundsListRequestParameters.java +++ b/client/src/main/com/sinch/sdk/domains/sms/models/requests/InboundsListRequestParameters.java @@ -109,7 +109,7 @@ public Builder setEndDate(Instant endDate) { * @param clientReference Using a client reference in inbound messages requires additional setup * on your account. Contact your account manager to enable this feature. Only list inbound * messages that are in response to messages with a previously provided client reference. - * * @return current builder + * @return current builder */ public Builder setClientReference(String clientReference) { this.clientReference = OptionalValue.of(clientReference); diff --git a/client/src/main/com/sinch/sdk/domains/sms/models/requests/UpdateSmsBatchTextRequest.java b/client/src/main/com/sinch/sdk/domains/sms/models/requests/UpdateSmsBatchTextRequest.java index 3afc4608..7a63004b 100644 --- a/client/src/main/com/sinch/sdk/domains/sms/models/requests/UpdateSmsBatchTextRequest.java +++ b/client/src/main/com/sinch/sdk/domains/sms/models/requests/UpdateSmsBatchTextRequest.java @@ -43,7 +43,8 @@ private Builder() {} /** * @param parameters Contains the parameters that will be used for customizing the message for - * each recipient. * @return current builder + * each recipient. + * @return current builder */ public Builder setParameters(Parameters parameters) { this.parameters = OptionalValue.of(parameters); diff --git a/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/WebhooksEvent.java b/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/WebhooksEvent.java new file mode 100644 index 00000000..0c063012 --- /dev/null +++ b/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/WebhooksEvent.java @@ -0,0 +1,4 @@ +package com.sinch.sdk.domains.sms.models.webhooks; + +/** Interface defining a WebHook event */ +public interface WebhooksEvent {} diff --git a/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/package-info.java b/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/package-info.java new file mode 100644 index 00000000..225045d4 --- /dev/null +++ b/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/package-info.java @@ -0,0 +1,57 @@ +/** + * SMS API webhooks related models + * + *

Incoming SMS WebHook

+ * + *

An inbound message is a message sent to one of your short codes or long numbers from a mobile + * phone. To receive inbound message callbacks, a URL needs to be added to your REST API. + * + *

This URL can be specified in your Dashboard. + * + *

See https://developers.sinch.com/docs/sms/api-reference/sms/tag/Webhooks/#tag/Webhooks/operation/incomingSMS + * + *

Delivery Report WebHook

+ * + *

A delivery report contains the status and status code for each recipient of a batch. To get a + * delivery report callback for a message or batch of messages, set the delivery_report + * field accordingly when creating a batch. + * + *

The following is provided so you can better understand our webhooks/callbacks. Configuration + * of both webhooks and the type of delivery report requested happens when sending a batch. + * + *

Callback URL + * + *

The callback URL can either be provided for each batch or provisioned globally for your + * account in your Sinch Customer Dashboard. + * Learn how to configure a webhook/callback here + * + *

Type + * + *

The type is the type of delivery report webhook. The response will vary depending + * on the webhook delivery report you selected when the batch was sent, so choose the appropriate + * selection under "One of". + * + *

    + *
  • The delivery_report_sms and delivery_report_mms types are + * documented under Delivery report. + *

    These are reports containing either + * a full report or summary report, depending on your selection at the time the batch was + * sent. + *

  • The recipient_delivery_report_sms and recipient_delivery_report_mms + * delivery report types are documented under Recipient delivery report. + *

    These are delivery reports for recipient phone numbers. If you set per_recipient + * for the delivery_report parameter when sending the batch, a recipient + * report gets sent to you for each status change for each recipient in your batch. If you set + * per_recipient_final, a recipient report gets sent to you for the final status + * of each recipient in your batch. + *

+ * + * See https://developers.sinch.com/docs/sms/api-reference/sms/tag/Webhooks/#tag/Webhooks/operation/deliveryReport + * + * @since 1.0 + */ +package com.sinch.sdk.domains.sms.models.webhooks; diff --git a/client/src/test/java/com/sinch/sdk/domains/sms/adapters/WebHooksServiceTest.java b/client/src/test/java/com/sinch/sdk/domains/sms/adapters/WebHooksServiceTest.java index 286a1269..afe60422 100644 --- a/client/src/test/java/com/sinch/sdk/domains/sms/adapters/WebHooksServiceTest.java +++ b/client/src/test/java/com/sinch/sdk/domains/sms/adapters/WebHooksServiceTest.java @@ -10,18 +10,17 @@ import com.sinch.sdk.core.exceptions.ApiMappingException; import com.sinch.sdk.domains.sms.adapters.converters.DeliveryReportDtoConverter; import com.sinch.sdk.domains.sms.adapters.converters.InboundsDtoConverter; -import com.sinch.sdk.domains.sms.models.BaseDeliveryReport; import com.sinch.sdk.domains.sms.models.DeliveryReportBatchMMS; import com.sinch.sdk.domains.sms.models.DeliveryReportBatchSMS; import com.sinch.sdk.domains.sms.models.DeliveryReportRecipientMMS; import com.sinch.sdk.domains.sms.models.DeliveryReportRecipientSMS; -import com.sinch.sdk.domains.sms.models.Inbound; import com.sinch.sdk.domains.sms.models.InboundBinary; import com.sinch.sdk.domains.sms.models.InboundText; import com.sinch.sdk.domains.sms.models.dto.v1.DeliveryReportBatchDtoTest; import com.sinch.sdk.domains.sms.models.dto.v1.DeliveryReportRecipientDtoTest; import com.sinch.sdk.domains.sms.models.dto.v1.MOBinaryDtoTest; import com.sinch.sdk.domains.sms.models.dto.v1.MOTextDtoTest; +import com.sinch.sdk.domains.sms.models.webhooks.WebhooksEvent; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; @@ -52,7 +51,7 @@ public class WebHooksServiceTest extends BaseTest { @Test void incomingSMSBinary() throws ApiException { - Inbound response = service.incomingSMS(incomingSMSBinaryJsonString); + WebhooksEvent response = service.parse(incomingSMSBinaryJsonString); Assertions.assertThat(response).isInstanceOf(InboundBinary.class); Assertions.assertThat(response) @@ -63,7 +62,7 @@ void incomingSMSBinary() throws ApiException { @Test void incomingSMSText() throws ApiException { - Inbound response = service.incomingSMS(incomingSMSTextJsonString); + WebhooksEvent response = service.parse(incomingSMSTextJsonString); Assertions.assertThat(response).isInstanceOf(InboundText.class); Assertions.assertThat(response) @@ -76,14 +75,14 @@ void handleExceptionIncomingSMS() throws ApiException { String jsonPayload = incomingSMSBinaryJsonString.replace("mo_binary", "foo type"); ApiMappingException thrown = - assertThrows(ApiMappingException.class, () -> service.incomingSMS(jsonPayload)); + assertThrows(ApiMappingException.class, () -> service.parse(jsonPayload)); assertTrue(thrown.getMessage().contains(jsonPayload)); } @Test void deliveryReportRecipientDeliveryReportSms() throws ApiException { - BaseDeliveryReport response = service.deliveryReport(deliveryReportRecipientSMSJsonString); + WebhooksEvent response = service.parse(deliveryReportRecipientSMSJsonString); Assertions.assertThat(response).isInstanceOf(DeliveryReportRecipientSMS.class); Assertions.assertThat(response) @@ -96,7 +95,7 @@ void deliveryReportRecipientDeliveryReportSms() throws ApiException { @Test void deliveryReportRecipientDeliveryReportMms() throws ApiException { - BaseDeliveryReport response = service.deliveryReport(deliveryReportRecipientMMSJsonString); + WebhooksEvent response = service.parse(deliveryReportRecipientMMSJsonString); Assertions.assertThat(response).isInstanceOf(DeliveryReportRecipientMMS.class); Assertions.assertThat(response) @@ -109,7 +108,7 @@ void deliveryReportRecipientDeliveryReportMms() throws ApiException { @Test void deliveryReportBatchDeliveryReportSms() throws ApiException { - BaseDeliveryReport response = service.deliveryReport(deliveryReportBatchSMSJsonString); + WebhooksEvent response = service.parse(deliveryReportBatchSMSJsonString); Assertions.assertThat(response).isInstanceOf(DeliveryReportBatchSMS.class); Assertions.assertThat(response) @@ -121,7 +120,7 @@ void deliveryReportBatchDeliveryReportSms() throws ApiException { @Test void deliveryReportBatchDeliveryReportMms() throws ApiException { - BaseDeliveryReport response = service.deliveryReport(deliveryReportBatchMMSJsonString); + WebhooksEvent response = service.parse(deliveryReportBatchMMSJsonString); Assertions.assertThat(response).isInstanceOf(DeliveryReportBatchMMS.class); Assertions.assertThat(response) @@ -136,7 +135,7 @@ void handleExceptionDeliveryReport() throws ApiException { String jsonPayload = deliveryReportRecipientMMSJsonString.replace("recipient_delivery_report_mms", "foo type"); ApiMappingException thrown = - assertThrows(ApiMappingException.class, () -> service.deliveryReport(jsonPayload)); + assertThrows(ApiMappingException.class, () -> service.parse(jsonPayload)); assertTrue(thrown.getMessage().contains(jsonPayload)); } } diff --git a/pom.xml b/pom.xml index 27bf5f4c..cb1a8cf1 100644 --- a/pom.xml +++ b/pom.xml @@ -297,7 +297,8 @@ **/*.java - + + sample-app/src/main/java/com/sinch/sample/webhooks/sms/SmsController.java sample-app/src/main/java/com/sinch/sample/webhooks/verification/VerificationController.java sample-app/src/main/java/com/sinch/sample/webhooks/voice/VoiceController.java diff --git a/sample-app/README.md b/sample-app/README.md index e0fa12e6..24382cf2 100644 --- a/sample-app/README.md +++ b/sample-app/README.md @@ -109,8 +109,6 @@ See https://developers.sinch.com for details about these parameters | | Update | [com.sinch.sample.sms.groups.Update](src/main/java/com/sinch/sample/sms/groups/Update.java) | | | Inbounds | Get | [com.sinch.sample.sms.inbounds.Get](src/main/java/com/sinch/sample/sms/inbounds/Get.java) | | | | List | [com.sinch.sample.sms.inbounds.List](src/main/java/com/sinch/sample/sms/inbounds/List.java) | | -| WebHooks | DeliveryReport | [com.sinch.sample.sms.webhooks.DeliveryReport](src/main/java/com/sinch/sample/sms/webhooks/DeliveryReport.java) | | -| | IncomingSMSReport | [com.sinch.sample.sms.webhooks.IncomingSMS](src/main/java/com/sinch/sample/sms/webhooks/IncomingSMS.java) | | #### Verification @@ -165,6 +163,7 @@ Check your dashboard to retrieve Application credentials values | API | Package | Notes | |--------------|------------------------------------------------------------------------------------------------|-------| | Numbers | [com.sinch.sample.webhooks.numbers](src/main/java/com/sinch/sample/webhooks/numbers) | | +| SMS | [com.sinch.sample.webhooks.sms](src/main/java/com/sinch/sample/webhooks/sms) | | | Verification | [com.sinch.sample.webhooks.verification](src/main/java/com/sinch/sample/webhooks/verification) | | | Voice | [com.sinch.sample.webhooks.voice](src/main/java/com/sinch/sample/webhooks/voice) | | diff --git a/sample-app/src/main/java/com/sinch/sample/BaseApplication.java b/sample-app/src/main/java/com/sinch/sample/BaseApplication.java index 538c2a2f..aaf79999 100644 --- a/sample-app/src/main/java/com/sinch/sample/BaseApplication.java +++ b/sample-app/src/main/java/com/sinch/sample/BaseApplication.java @@ -8,6 +8,7 @@ import java.util.logging.Logger; public abstract class BaseApplication { + private static final String BATCH_ID_KEY = "BATCH_ID"; public static final String PHONE_NUMBER_KEY = "PHONE_NUMBER"; private static final String VIRTUAL_PHONE_NUMBER_KEY = "VIRTUAL_PHONE_NUMBER"; @@ -17,6 +18,7 @@ public abstract class BaseApplication { public static final String WEBHOOKS_URL_KEY = "WEBHOOKS_URL"; public static final String WEBHOOKS_VOICE_PATH_KEY = "WEBHOOKS_VOICE_PATH"; + public static final String WEBHOOKS_SMS_PATH_KEY = "WEBHOOKS_SMS_PATH"; protected static final Logger LOGGER = Utils.initializeLogger(BaseApplication.class.getName()); @@ -31,6 +33,7 @@ public abstract class BaseApplication { protected String applicationKey; protected String webhooksVoicePath; + protected String webhooksSmsPath; Properties properties; @@ -48,9 +51,12 @@ protected BaseApplication() throws IOException { callId = getConfigValue(CALL_ID_KEY); verificationId = getConfigValue(VERIFICATION_ID_KEY); virtualPhoneNumber = getConfigValue(VIRTUAL_PHONE_NUMBER_KEY); - String webhooksUrl = getConfigValue(WEBHOOKS_URL_KEY); - webhooksVoicePath = String.format("%s%s", webhooksUrl, getConfigValue(WEBHOOKS_VOICE_PATH_KEY)); + if (null != webhooksUrl) { + webhooksVoicePath = + String.format("%s%s", webhooksUrl, getConfigValue(WEBHOOKS_VOICE_PATH_KEY)); + webhooksSmsPath = String.format("%s%s", webhooksUrl, getConfigValue(WEBHOOKS_SMS_PATH_KEY)); + } applicationKey = configuration diff --git a/sample-app/src/main/java/com/sinch/sample/sms/batches/Send.java b/sample-app/src/main/java/com/sinch/sample/sms/batches/Send.java index 03286734..ceb21ab6 100644 --- a/sample-app/src/main/java/com/sinch/sample/sms/batches/Send.java +++ b/sample-app/src/main/java/com/sinch/sample/sms/batches/Send.java @@ -2,6 +2,7 @@ import com.sinch.sample.BaseApplication; import com.sinch.sdk.domains.sms.models.BatchText; +import com.sinch.sdk.domains.sms.models.DeliveryReportType; import com.sinch.sdk.domains.sms.models.requests.SendSmsBatchTextRequest; import java.io.IOException; import java.util.Collections; @@ -24,17 +25,21 @@ public static void main(String[] args) { public void run() { LOGGER.info("Send Text to " + phoneNumber); - BatchText value = - client - .sms() - .batches() - .send( - SendSmsBatchTextRequest.builder() - .setTo(Collections.singletonList(phoneNumber)) - .setBody("the body") - .setClientReference("a client reference") - .setFrom("+33123456789") - .build()); + + SendSmsBatchTextRequest.Builder builder = + SendSmsBatchTextRequest.builder() + .setTo(Collections.singletonList(phoneNumber)) + .setBody("the body") + .setClientReference("a client reference") + .setFrom("+33123456789") + .setDeliveryReport(DeliveryReportType.FULL); + + // Overload default dashboard webhooks URL if defined + if (null != webhooksSmsPath) { + builder.setCallbackUrl(webhooksSmsPath); + } + + BatchText value = client.sms().batches().send(builder.build()); LOGGER.info("Response: " + value); } diff --git a/sample-app/src/main/java/com/sinch/sample/sms/webhooks/DeliveryReport.java b/sample-app/src/main/java/com/sinch/sample/sms/webhooks/DeliveryReport.java deleted file mode 100644 index b0b11415..00000000 --- a/sample-app/src/main/java/com/sinch/sample/sms/webhooks/DeliveryReport.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.sinch.sample.sms.webhooks; - -import com.sinch.sample.BaseApplication; -import com.sinch.sdk.domains.sms.models.BaseDeliveryReport; -import java.io.IOException; -import java.util.logging.Logger; - -public class DeliveryReport extends BaseApplication { - private static final Logger LOGGER = Logger.getLogger(DeliveryReport.class.getName()); - - public DeliveryReport() throws IOException {} - - public static void main(String[] args) { - try { - new DeliveryReport().run(); - } catch (Exception e) { - LOGGER.severe(e.getMessage()); - e.printStackTrace(); - } - } - - public void run() { - - String payload = - "{\n" - + " \"type\": \"delivery_report_sms\",\n" - + " \"batch_id\": \"01FC66621XXXXX119Z8PMV1QPQ\",\n" - + " \"statuses\": [\n" - + " {\n" - + " \"code\": 0,\n" - + " \"count\": 1,\n" - + " \"recipients\": [\n" - + " \"44231235674\"\n" - + " ],\n" - + " \"status\": \"Delivered\"\n" - + " }\n" - + " ],\n" - + " \"total_message_count\": 1\n" - + "}"; - LOGGER.info("Convert payload" + payload); - - BaseDeliveryReport value = client.sms().webHooks().deliveryReport(payload); - - LOGGER.info("Conversion result: " + value); - } -} diff --git a/sample-app/src/main/java/com/sinch/sample/sms/webhooks/IncomingSMS.java b/sample-app/src/main/java/com/sinch/sample/sms/webhooks/IncomingSMS.java deleted file mode 100644 index 9da76d45..00000000 --- a/sample-app/src/main/java/com/sinch/sample/sms/webhooks/IncomingSMS.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.sinch.sample.sms.webhooks; - -import com.sinch.sample.BaseApplication; -import com.sinch.sdk.domains.sms.models.Inbound; -import java.io.IOException; -import java.util.logging.Logger; - -public class IncomingSMS extends BaseApplication { - private static final Logger LOGGER = Logger.getLogger(IncomingSMS.class.getName()); - - public IncomingSMS() throws IOException {} - - public static void main(String[] args) { - try { - new IncomingSMS().run(); - } catch (Exception e) { - LOGGER.severe(e.getMessage()); - e.printStackTrace(); - } - } - - public void run() { - - String payload = - "{\n" - + " \"body\": \"This is a test message.\",\n" - + " \"from\": \"16051234567\",\n" - + " \"id\": \"01XXXXX21XXXXX119Z8P1XXXXX\",\n" - + " \"operator_id\": \"string\",\n" - + " \"received_at\": \"2022-08-24T14:15:22Z\",\n" - + " \"to\": \"13185551234\",\n" - + " \"type\": \"mo_text\"\n" - + "}"; - LOGGER.info("Convert MOText payload" + payload); - - Inbound value = client.sms().webHooks().incomingSMS(payload); - - LOGGER.info("Conversion result: " + value); - - payload = - "{\n" - + " \"body\": \"a body\",\n" - + " \"client_reference\": \"a client reference\",\n" - + " \"from\": \"+11203494390\",\n" - + " \"id\": \"01FC66621XXXXX119Z8PMV1QPA\",\n" - + " \"operator_id\": \"35000\",\n" - + " \"received_at\": \"2019-08-24T14:17:22Z\",\n" - + " \"sent_at\": \"2019-08-24T14:15:22Z\",\n" - + " \"to\": \"11203453453\",\n" - + " \"type\": \"mo_binary\",\n" - + " \"udh\": \"foo udh\"\n" - + "}"; - LOGGER.info("Convert MOBinary payload" + payload); - - value = client.sms().webHooks().incomingSMS(payload); - - LOGGER.info("Conversion result: " + value); - } -} diff --git a/sample-app/src/main/java/com/sinch/sample/webhooks/sms/SmsController.java b/sample-app/src/main/java/com/sinch/sample/webhooks/sms/SmsController.java new file mode 100644 index 00000000..41c41252 --- /dev/null +++ b/sample-app/src/main/java/com/sinch/sample/webhooks/sms/SmsController.java @@ -0,0 +1,53 @@ +package com.sinch.sample.webhooks.sms; + +import com.sinch.sdk.SinchClient; +import com.sinch.sdk.domains.sms.models.DeliveryReportBatch; +import com.sinch.sdk.domains.sms.models.DeliveryReportRecipient; +import com.sinch.sdk.domains.sms.models.InboundBinary; +import com.sinch.sdk.domains.sms.models.InboundText; +import java.util.Map; +import java.util.logging.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class SmsController { + + private final SinchClient sinchClient; + private final SmsService service; + private static final Logger LOGGER = Logger.getLogger(SmsController.class.getName()); + + @Autowired + public SmsController(SinchClient sinchClient, SmsService service) { + this.sinchClient = sinchClient; + this.service = service; + } + + @PostMapping( + value = "/SmsEvent", + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + public void smsDeliveryEvent( + @RequestHeader Map headers, @RequestBody String body) { + + LOGGER.finest("Received body:" + body); + LOGGER.finest("Received headers: " + headers); + + // decode the request payload + var event = sinchClient.sms().webHooks().parse(body); + + // let business layer process the request + switch (event) { + case InboundBinary e -> service.processInboundEvent(e); + case InboundText e -> service.processInboundEvent(e); + case DeliveryReportRecipient e -> service.processDeliveryReportEvent(e); + case DeliveryReportBatch e -> service.processDeliveryReportEvent(e); + default -> throw new IllegalStateException("Unexpected value: " + event); + } + } + +} diff --git a/sample-app/src/main/java/com/sinch/sample/webhooks/sms/SmsService.java b/sample-app/src/main/java/com/sinch/sample/webhooks/sms/SmsService.java new file mode 100644 index 00000000..aa3fcd96 --- /dev/null +++ b/sample-app/src/main/java/com/sinch/sample/webhooks/sms/SmsService.java @@ -0,0 +1,35 @@ +package com.sinch.sample.webhooks.sms; + +import com.sinch.sdk.domains.sms.models.DeliveryReportBatch; +import com.sinch.sdk.domains.sms.models.DeliveryReportRecipient; +import com.sinch.sdk.domains.sms.models.InboundBinary; +import com.sinch.sdk.domains.sms.models.InboundText; +import com.sinch.sdk.domains.sms.models.webhooks.WebhooksEvent; +import java.util.logging.Logger; +import org.springframework.stereotype.Component; + +@Component +public class SmsService { + + private static final Logger LOGGER = Logger.getLogger(SmsService.class.getName()); + + public void processInboundEvent(InboundText event) { + trace(event); + } + + public void processInboundEvent(InboundBinary event) { + trace(event); + } + + public void processDeliveryReportEvent(DeliveryReportRecipient event) { + trace(event); + } + + public void processDeliveryReportEvent(DeliveryReportBatch event) { + trace(event); + } + + private void trace(WebhooksEvent event) { + LOGGER.info("Handle event :" + event); + } +}