Skip to content

Commit

Permalink
Refactor sms webhooks (#60)
Browse files Browse the repository at this point in the history
* refactor: SMS webhooks. Parse payload to common 'WebhookEvent' type
  • Loading branch information
JPPortier authored Feb 27, 2024
1 parent 3e601bb commit 3abe0dd
Show file tree
Hide file tree
Showing 20 changed files with 288 additions and 257 deletions.
44 changes: 26 additions & 18 deletions client/src/main/com/sinch/sdk/domains/sms/BatchesService.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@
public interface BatchesService {

/**
* Get a batch message <br>
* This operation returns a specific batch that matches the provided batch ID.
* Get a batch message.
*
* <p>This operation returns a specific batch that matches the provided batch ID.
*
* @param batchId The batch ID you received from sending a message
* @param <T> A type of Batch
Expand All @@ -32,9 +33,10 @@ public interface BatchesService {
<T extends Batch<?>> T get(String batchId) throws ApiException;

/**
* Send a message or a batch of messages <br>
* Depending on the length of the body, one message might be split into multiple parts and charged
* accordingly. <br>
* Send a message or a batch of messages.
*
* <p>Depending on the length of the body, one message might be split into multiple parts and
* charged accordingly. <br>
* 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. <br>
* Be sure to use the correct region in the server URL.
Expand All @@ -49,8 +51,9 @@ public interface BatchesService {
<T extends Batch<?>> T send(BaseBatch<?> batch) throws ApiException;

/**
* Dry run <br>
* This operation will perform a dry run of a batch which calculates the bodies and number of
* Dry run.
*
* <p>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
Expand All @@ -66,9 +69,10 @@ DryRun dryRun(boolean perRecipient, int numberOfRecipient, BaseBatch<?> batch)
throws ApiException;

/**
* List Batches <br>
* 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.
*
* <p>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
Expand All @@ -79,8 +83,10 @@ DryRun dryRun(boolean perRecipient, int numberOfRecipient, BaseBatch<?> batch)
BatchesListResponse list(BatchesListRequestParameters parameters) throws ApiException;

/**
* Update a Batch message <br>
* This operation updates all specified parameters of a batch that matches the provided batch ID.
* Update a Batch message.
*
* <p>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
Expand All @@ -94,9 +100,10 @@ <T extends Batch<?>> T update(String batchId, UpdateBaseBatchRequest<?> batch)
throws ApiException;

/**
* Replace a batch <br>
* 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 .
*
* <p>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
Expand All @@ -109,8 +116,9 @@ <T extends Batch<?>> T update(String batchId, UpdateBaseBatchRequest<?> batch)
<T extends Batch<?>> T replace(String batchId, BaseBatch<?> batch) throws ApiException;

/**
* Cancel a batch message <br>
* A batch can be canceled at any point. If a batch is canceled while it's currently being
* Cancel a batch message.
*
* <p>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. <br>
* Canceling a batch scheduled in the future will result in an empty delivery report while
Expand All @@ -126,7 +134,7 @@ <T extends Batch<?>> T update(String batchId, UpdateBaseBatchRequest<?> batch)
<T extends Batch<?>> T cancel(String batchId) throws ApiException;

/**
* Send delivery feedback for a message
* Send delivery feedback for a message.
*
* <p>Send feedback if your system can confirm successful message delivery.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import com.sinch.sdk.domains.sms.models.responses.DeliveryReportsListResponse;

/**
* Delivery reports Service
* Delivery reports Service.
*
* <p>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 <a
Expand All @@ -22,9 +22,10 @@
public interface DeliveryReportsService {

/**
* Retrieve a batch delivery report <br>
* 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 <a
* Retrieve a batch delivery report.
*
* <p>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 <a
* href="https://community.sinch.com/t5/Glossary/E-164/ta-p/7537">E.164</a> format for each status
* code.
*
Expand All @@ -40,8 +41,9 @@ DeliveryReportBatch get(String batchId, DeliveryReportBatchGetRequestParameters
throws ApiException;

/**
* Retrieve a recipient delivery report <br>
* A recipient delivery report contains the message status for a single recipient phone number.
* Retrieve a recipient delivery report.
*
* <p>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
Expand All @@ -54,8 +56,9 @@ DeliveryReportBatch get(String batchId, DeliveryReportBatchGetRequestParameters
DeliveryReportRecipient getForNumber(String batchId, String recipient) throws ApiException;

/**
* Get a list of finished delivery reports.<br>
* This operation supports pagination.
* Get a list of finished delivery reports.
*
* <p>This operation supports pagination.
*
* @param parameters Filtering parameters
* @return Delivery report related to batchId according to filters
Expand Down
16 changes: 14 additions & 2 deletions client/src/main/com/sinch/sdk/domains/sms/GroupsService.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
public interface GroupsService {

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

/**
* Create a group
* Create a group.
*
* <p>A group is a set of phone numbers (MSISDNs) that can be used as a target in the <code>
* send_batch_msg</code> operation. An MSISDN can only occur once in a group and any attempts to
Expand All @@ -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;

/**
Expand All @@ -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;

/**
Expand Down
65 changes: 6 additions & 59 deletions client/src/main/com/sinch/sdk/domains/sms/WebHooksService.java
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -41,63 +40,11 @@
public interface WebHooksService {

/**
* Incoming SMS WebHook
* Parse and un-serialize incoming webhooks payload
*
* <p>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 <a href="https://dashboard.sinch.com/sms/api">Dashboard</a>.
*
* @param jsonPayload The incoming message to your sinch number
* @return Decoded payload
* @see <a
* href="https://developers.sinch.com/docs/sms/api-reference/sms/tag/Webhooks/#tag/Webhooks/operation/incomingSMS">https://developers.sinch.com/docs/sms/api-reference/sms/tag/Webhooks/#tag/Webhooks/operation/incomingSMS</a>
* @since 1.0
*/
Inbound<?> incomingSMS(String jsonPayload) throws ApiMappingException;

/**
* Delivery Report WebHook
*
* <p>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 <code>delivery_report
* </code> field accordingly when creating a batch.
*
* <p>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.
*
* <p><b>Callback URL</b>
*
* <p>The callback URL can either be provided for each batch or provisioned globally for your
* account in your <a href="https://dashboard.sinch.com/sms/api/rest">Sinch Customer
* Dashboard</a>. Learn how to configure a webhook/callback <a
* href="https://community.sinch.com/t5/SMS/How-do-I-assign-a-callback-URL-to-an-SMS-service-plan/ta-p/8414">here</a>
*
* <p><b>Type</b>
*
* <p>The <code>type</code> 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".
*
* <ul>
* <li>The <code>delivery_report_sms</code> and <code>delivery_report_mms</code> types are
* documented under <b>Delivery report</b>. These are reports containing <a
* href="https://developers.sinch.com/docs/sms/api-reference/sms/tag/Batches/#tag/Batches/operation/SendSMS!path=0/delivery_report&amp;t=request">either
* a full report or summary report</a>, depending on your selection at the time the batch
* was sent.
* <li>The <code>recipient_delivery_report_sms</code> and <code>recipient_delivery_report_mms
* </code> delivery report types are documented under <b>Recipient delivery report</b>.
* These are delivery reports for recipient phone numbers. If you set <code>per_recipient
* </code> for the <code>delivery_report</code> 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 <code>per_recipient_final</code>, a recipient report gets sent to you
* for the final status of each recipient in your batch.
* </ul>
*
* @param jsonPayload The incoming delivery report
* @return Decoded payload
* @see <a
* href="https://developers.sinch.com/docs/sms/api-reference/sms/tag/Webhooks/#tag/Webhooks/operation/deliveryReport">https://developers.sinch.com/docs/sms/api-reference/sms/tag/Webhooks/#tag/Webhooks/operation/deliveryReport</a>
* @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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -9,7 +10,7 @@
* @param <T> Type of body
* @since 1.0
*/
public abstract class Inbound<T> {
public abstract class Inbound<T> implements WebhooksEvent {

private final T body;
private final String from;
Expand Down
Loading

0 comments on commit 3abe0dd

Please sign in to comment.