diff --git a/src/main/java/dev/resms/ReSMS.java b/src/main/java/dev/resms/ReSMS.java index 8430d14..846c458 100644 --- a/src/main/java/dev/resms/ReSMS.java +++ b/src/main/java/dev/resms/ReSMS.java @@ -1,5 +1,6 @@ package dev.resms; +import dev.resms.services.otp.Otp; import dev.resms.services.sms.Sms; import lombok.RequiredArgsConstructor; @@ -17,4 +18,13 @@ public class ReSMS { public Sms sms() { return new Sms(apiKey); } + + /** + * Returns an Otp object that can be used to interact with the Otp service. + * + * @return An Otp object. + */ + public Otp otp() { + return new Otp(apiKey); + } } diff --git a/src/main/java/dev/resms/core/net/HttpMethod.java b/src/main/java/dev/resms/core/net/HttpMethod.java index fd75db3..7a7f9a9 100644 --- a/src/main/java/dev/resms/core/net/HttpMethod.java +++ b/src/main/java/dev/resms/core/net/HttpMethod.java @@ -4,4 +4,5 @@ public enum HttpMethod { GET, POST, + DELETE, } diff --git a/src/main/java/dev/resms/services/otp/Otp.java b/src/main/java/dev/resms/services/otp/Otp.java new file mode 100644 index 0000000..e807087 --- /dev/null +++ b/src/main/java/dev/resms/services/otp/Otp.java @@ -0,0 +1,89 @@ +package dev.resms.services.otp; + +import dev.resms.core.exception.ReSMSException; +import dev.resms.core.net.AbstractHttpResponse; +import dev.resms.core.net.HttpMethod; +import dev.resms.core.service.BaseService; +import dev.resms.services.otp.model.CreateOtpOptions; +import dev.resms.services.otp.model.CreateOtpResponse; +import dev.resms.services.otp.model.DeleteOtpResponse; +import dev.resms.services.otp.model.VerifyOtpOptions; +import dev.resms.services.otp.model.VerifyOtpResponse; + +public class Otp extends BaseService { + private static final String CREATE_OTP_PATH = "/otp"; + private static final String VERIFY_OTP_PATH = "/otp/verify"; + private static final String DELETE_OTP_PATH = "/otp"; + + /** + * Constructs an instance of the {@code Otp} class. + * + * @param apiKey The apiKey used for authentication. + */ + public Otp(final String apiKey) { + super(apiKey); + } + + /** + * Create an OTP based on the provided OTP request + * + * @param createOtpOptions The request containing OTP details. + * @return The response indicating the status of the OTP creation. + * @throws ReSMSException If an error occurs while creating the OTP. + */ + public CreateOtpResponse create(CreateOtpOptions createOtpOptions) throws ReSMSException { + String payload = super.reSMSMapper.toJson(createOtpOptions); + + AbstractHttpResponse response = + super.httpClient.perform(CREATE_OTP_PATH, apiKey, HttpMethod.POST, payload); + + if (!response.isSuccessful()) { + throw new ReSMSException( + "Failed to create otp: " + response.getCode() + " " + response.getBody()); + } + + return reSMSMapper.fromJson(response.getBody(), CreateOtpResponse.class); + } + + /** + * Verify an OTP based on the provided OTP verify request + * + * @param verifyOtpOptions The request containing OTP verify details. + * @return The response indicating the status of the OTP verification. + * @throws ReSMSException If an error occurs while verifying the OTP. + */ + public VerifyOtpResponse verify(VerifyOtpOptions verifyOtpOptions) throws ReSMSException { + String payload = super.reSMSMapper.toJson(verifyOtpOptions); + + AbstractHttpResponse response = + super.httpClient.perform(VERIFY_OTP_PATH, apiKey, HttpMethod.POST, payload); + + if (!response.isSuccessful()) { + throw new ReSMSException( + "Failed to create otp: " + response.getCode() + " " + response.getBody()); + } + + return reSMSMapper.fromJson(response.getBody(), VerifyOtpResponse.class); + } + + /** + * Delete an OTP based on its id + * + * @param otpId The id of the OTP to delete. + * @return The response indicating the status of the OTP deletion. + * @throws ReSMSException If an error occurs while deleting the OTP. + */ + public DeleteOtpResponse delete(String otpId) throws ReSMSException { + String payload = "{\"otpId\": \"" + otpId + "\"}"; + + AbstractHttpResponse response = + super.httpClient.perform(DELETE_OTP_PATH, apiKey, HttpMethod.DELETE, payload); + + if (!response.isSuccessful()) { + throw new ReSMSException( + "Failed to create otp: " + response.getCode() + " " + response.getBody()); + } + + return reSMSMapper.fromJson(response.getBody(), DeleteOtpResponse.class); + } +} diff --git a/src/main/java/dev/resms/services/otp/model/CreateOtpOptions.java b/src/main/java/dev/resms/services/otp/model/CreateOtpOptions.java new file mode 100644 index 0000000..9887476 --- /dev/null +++ b/src/main/java/dev/resms/services/otp/model/CreateOtpOptions.java @@ -0,0 +1,17 @@ +package dev.resms.services.otp.model; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Builder +public class CreateOtpOptions { + private String to; + private String message; + private String senderId; + private OtpCode codeType; + private int codeLength; + private int validityMinutes; +} diff --git a/src/main/java/dev/resms/services/otp/model/CreateOtpResponse.java b/src/main/java/dev/resms/services/otp/model/CreateOtpResponse.java new file mode 100644 index 0000000..45b3c81 --- /dev/null +++ b/src/main/java/dev/resms/services/otp/model/CreateOtpResponse.java @@ -0,0 +1,15 @@ +package dev.resms.services.otp.model; + +import dev.resms.core.model.Response; +import lombok.Getter; + +@Getter +public class CreateOtpResponse extends Response { + private CreateOtpResponseData data; + + @Getter + public static class CreateOtpResponseData { + private String phoneNumber; + private String expiresAt; + } +} diff --git a/src/main/java/dev/resms/services/otp/model/DeleteOtpResponse.java b/src/main/java/dev/resms/services/otp/model/DeleteOtpResponse.java new file mode 100644 index 0000000..34ffe54 --- /dev/null +++ b/src/main/java/dev/resms/services/otp/model/DeleteOtpResponse.java @@ -0,0 +1,11 @@ +package dev.resms.services.otp.model; + +import dev.resms.core.model.Response; +import lombok.Getter; + +@Getter +public class DeleteOtpResponse extends Response { + private String otpId; + private String phoneNumber; + private String revokedAt; +} diff --git a/src/main/java/dev/resms/services/otp/model/OtpCode.java b/src/main/java/dev/resms/services/otp/model/OtpCode.java new file mode 100644 index 0000000..c33b369 --- /dev/null +++ b/src/main/java/dev/resms/services/otp/model/OtpCode.java @@ -0,0 +1,6 @@ +package dev.resms.services.otp.model; + +public enum OtpCode { + NUMERIC, + ALPHA, +} diff --git a/src/main/java/dev/resms/services/otp/model/VerifyOtpOptions.java b/src/main/java/dev/resms/services/otp/model/VerifyOtpOptions.java new file mode 100644 index 0000000..9b92fa8 --- /dev/null +++ b/src/main/java/dev/resms/services/otp/model/VerifyOtpOptions.java @@ -0,0 +1,13 @@ +package dev.resms.services.otp.model; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Builder +public class VerifyOtpOptions { + private String to; + private String code; +} diff --git a/src/main/java/dev/resms/services/otp/model/VerifyOtpResponse.java b/src/main/java/dev/resms/services/otp/model/VerifyOtpResponse.java new file mode 100644 index 0000000..e0fe935 --- /dev/null +++ b/src/main/java/dev/resms/services/otp/model/VerifyOtpResponse.java @@ -0,0 +1,16 @@ +package dev.resms.services.otp.model; + +import dev.resms.core.model.Response; +import lombok.Getter; + +@Getter +public class VerifyOtpResponse extends Response { + private VerifyOtpResponseData data; + + @Getter + public static class VerifyOtpResponseData { + private String otpId; + private String phoneNumber; + private String verifiedAt; + } +}