httpResponse = Unirest.get(url)
- .header(acceptEncodingHeader, "application/json")
- .header(authorizationHeader, "Bearer " + secreteKey)
- .asJson();
-
- statusCode = httpResponse.getStatus();
- return httpResponse.getBody().toString();
- }
-
- @Override
- public int getStatusCode() {
- return statusCode;
- }
-}
diff --git a/src/main/java/com/yaphet/chapa/client/IChapaClient.java b/src/main/java/com/yaphet/chapa/client/IChapaClient.java
new file mode 100644
index 0000000..db9d5f7
--- /dev/null
+++ b/src/main/java/com/yaphet/chapa/client/IChapaClient.java
@@ -0,0 +1,90 @@
+package com.yaphet.chapa.client;
+
+
+import com.yaphet.chapa.exception.ChapaException;
+import com.yaphet.chapa.model.InitializeResponse;
+import com.yaphet.chapa.model.ResponseBanks;
+import com.yaphet.chapa.model.SubAccountResponse;
+import com.yaphet.chapa.model.VerifyResponse;
+
+import java.util.Map;
+
+/**
+ * Chapa default retrofit client interface
+ *
+ * Custom implementation can be created by implementing this interface
+ */
+public interface IChapaClient {
+
+ /**
+ * Initializes transaction
+ *
+ * @see Chapa Dcoumentation
+ *
+ * @param secretKey
+ * @param fields
+ * @return InitializeResponse
+ * @throws ChapaException
+ */
+ InitializeResponse initialize(final String secretKey, Map fields) throws ChapaException;
+
+ /**
+ * An alias to {@link #initialize(String, Map)}
+ *
+ * @see Chapa Dcoumentation
+ *
+ * @param secretKey
+ * @param body
+ * @return InitializeResponse
+ * @throws ChapaException
+ */
+ InitializeResponse initialize(final String secretKey, final String body) throws ChapaException;
+
+ /**
+ * Verify a transaction
+ *
+ * @see Chapa Dcoumentation
+ *
+ * @param secretKey
+ * @param transactionReference
+ * @return VerifyResponse
+ * @throws ChapaException
+ */
+ VerifyResponse verify(String secretKey, String transactionReference) throws ChapaException;
+
+ /**
+ * Get all supported banks
+ *
+ * @see Chapa Dcoumentation
+ *
+ * @param secretKey
+ * @return ResponseBanks
+ * @throws ChapaException
+ */
+ ResponseBanks getBanks(String secretKey) throws ChapaException;
+
+ /**
+ *
+ * Create sub account for split payment
+ *
+ * @see Chapa Dcoumentation
+ *
+ * @param secretKey
+ * @param fields
+ * @return SubAccountResponse
+ * @throws ChapaException
+ */
+ SubAccountResponse createSubAccount(String secretKey, Map fields) throws ChapaException;
+
+ /**
+ * Create sub account for split payment, an alternative method to {@link #createSubAccount(String, Map)}
+ *
+ * @see Chapa Dcoumentation
+ *
+ * @param body
+ * @param secretKey
+ * @return SubAccountResponse
+ * @throws ChapaException
+ */
+ SubAccountResponse createSubAccount(String secretKey, String body) throws ChapaException;
+}
diff --git a/src/main/java/com/yaphet/chapa/client/provider/BaseRetrofitClientProvider.java b/src/main/java/com/yaphet/chapa/client/provider/BaseRetrofitClientProvider.java
new file mode 100644
index 0000000..b7fc69f
--- /dev/null
+++ b/src/main/java/com/yaphet/chapa/client/provider/BaseRetrofitClientProvider.java
@@ -0,0 +1,66 @@
+package com.yaphet.chapa.client.provider;
+
+import com.yaphet.chapa.client.ChapaClientApi;
+import okhttp3.OkHttpClient;
+import okhttp3.logging.HttpLoggingInterceptor;
+
+import java.util.concurrent.TimeUnit;
+
+public abstract class BaseRetrofitClientProvider implements RetrofitClientProvider {
+
+ private boolean debug;
+ private HttpLoggingInterceptor loggingInterceptor;
+
+ protected OkHttpClient httpClient;
+
+ protected BaseRetrofitClientProvider(long timeoutMillis) {
+ this.httpClient = createHttpClient(timeoutMillis);
+ }
+
+ @Override
+ public RetrofitClientProvider setDebug(boolean debug) {
+ if (this.debug != debug) {
+ if (debug) {
+ if (loggingInterceptor == null) {
+ loggingInterceptor = new HttpLoggingInterceptor();
+ loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
+ }
+ httpClient = httpClient.newBuilder().addInterceptor(loggingInterceptor).build();
+ } else {
+ httpClient.newBuilder().interceptors().remove(loggingInterceptor);
+ loggingInterceptor = null;
+ }
+ }
+ this.debug = debug;
+ return this;
+ }
+
+ @Override
+ public RetrofitClientProvider setClient(OkHttpClient client) {
+ if (client == null) {
+ throw new IllegalArgumentException("Client can't be null");
+ }
+ this.httpClient = client;
+ return this;
+ }
+
+ public boolean isDebug() {
+ return debug;
+ }
+
+ public OkHttpClient getHttpClient() {
+ return httpClient;
+ }
+
+ public ChapaClientApi create() {
+ return provideRetrofitBuilder().create(ChapaClientApi.class);
+ }
+
+ private static OkHttpClient createHttpClient(long timeoutMillis) {
+ return new OkHttpClient.Builder()
+ .connectTimeout(timeoutMillis, TimeUnit.MILLISECONDS)
+ .readTimeout(timeoutMillis, TimeUnit.MILLISECONDS)
+ .writeTimeout(timeoutMillis, TimeUnit.MILLISECONDS)
+ .build();
+ }
+}
diff --git a/src/main/java/com/yaphet/chapa/client/provider/DefaultRetrofitClientProvider.java b/src/main/java/com/yaphet/chapa/client/provider/DefaultRetrofitClientProvider.java
new file mode 100644
index 0000000..64b1ff2
--- /dev/null
+++ b/src/main/java/com/yaphet/chapa/client/provider/DefaultRetrofitClientProvider.java
@@ -0,0 +1,67 @@
+package com.yaphet.chapa.client.provider;
+
+import com.yaphet.chapa.utility.StringUtils;
+import retrofit2.Retrofit;
+import retrofit2.converter.gson.GsonConverterFactory;
+
+/**
+ *
+ * Provides retrofit client to make calls to chapa api.
+ *
+ * This implementation will not retry on failures.
+ *
+ * * Example usage:
+ * * public class CustomChapaClient implements IChapaClient {
+ * *
+ * * private ChapaClientApi chapaClientApi;
+ * * .
+ * * .
+ * * private void buildApiClient() {
+ * * if (isBlank(baseUrl)) throw new ChapaException("Unable to create a client. Api baseUrl can't be empty");
+ * * chapaClientApi = new DefaultRetrofitClientProvider.Builder().timeout(10000).baseUrl("https://chapa.example.com").build().createChapaClient();
+ * * }
+ * * }
+ * *
+ */
+public class DefaultRetrofitClientProvider extends BaseRetrofitClientProvider {
+
+ private static final long DEFAULT_TIMEOUT = 10000;
+
+ private final String baseUrl;
+
+ private DefaultRetrofitClientProvider(Builder builder) {
+ super(builder.timeoutMillis);
+ if (StringUtils.isBlank(builder.baseUrl)) {
+ throw new IllegalArgumentException("Api baseUrl can't be null");
+ }
+ this.baseUrl = builder.baseUrl;
+ }
+
+ @Override
+ public Retrofit provideRetrofitBuilder() {
+ return new Retrofit.Builder()
+ .baseUrl(baseUrl)
+ .addConverterFactory(GsonConverterFactory.create())
+ .client(httpClient)
+ .build();
+ }
+
+ public static class Builder {
+ private String baseUrl = "";
+ private long timeoutMillis = DEFAULT_TIMEOUT;
+
+ public Builder timeout(long timeoutMillis) {
+ this.timeoutMillis = timeoutMillis;
+ return this;
+ }
+
+ public Builder baseUrl(String baseUrl) {
+ this.baseUrl = baseUrl;
+ return this;
+ }
+
+ public DefaultRetrofitClientProvider build() {
+ return new DefaultRetrofitClientProvider(this);
+ }
+ }
+}
diff --git a/src/main/java/com/yaphet/chapa/client/provider/RetrierRetrofitClientProvider.java b/src/main/java/com/yaphet/chapa/client/provider/RetrierRetrofitClientProvider.java
new file mode 100644
index 0000000..acf309b
--- /dev/null
+++ b/src/main/java/com/yaphet/chapa/client/provider/RetrierRetrofitClientProvider.java
@@ -0,0 +1,97 @@
+package com.yaphet.chapa.client.provider;
+
+import com.yaphet.chapa.utility.StringUtils;
+import io.github.resilience4j.core.IntervalFunction;
+import io.github.resilience4j.retrofit.RetryCallAdapter;
+import io.github.resilience4j.retry.Retry;
+import io.github.resilience4j.retry.RetryConfig;
+import retrofit2.Response;
+import retrofit2.Retrofit;
+import retrofit2.converter.gson.GsonConverterFactory;
+
+/**
+ * Provides retrofit client to make calls to chapa api.
+ *
+ * This implementation will retry calls to chapa api upto 3 (default) times. You can set the number of retries too.
+ *
+ * Retry will be done with an ExponentialBackoff strategy.
+ *
+ * Timeouts are all set to 10_000 millis
+ *
+ *
+ *
+ * Example usage:
+ * public class CustomChapaClient implements IChapaClient {
+ *
+ * private ChapaClientApi chapaClientApi;
+ * .
+ * .
+ * private void buildApiClient() {
+ * if (isBlank(baseUrl)) throw new ChapaException("Unable to create a client. Api baseUrl can't be empty");
+ * chapaClientApi = new RetrierRetrofitClientProvider.Builder().timeout(10000).retryCount(3).baseUrl("https://chapa.example.com").build().create();
+ * }
+ * }
+ *
+ */
+public class RetrierRetrofitClientProvider extends BaseRetrofitClientProvider {
+
+ private static final long DEFAULT_TIMEOUT = 10000;
+ private static final int DEFAULT_RETRY_COUNT = 3;
+ private static final double BACKOFF_MULTIPLIER = 2.0;
+
+ private final RetryConfig retryConfig;
+ private final String baseUrl;
+
+ private RetrierRetrofitClientProvider(Builder builder) {
+ super(builder.timeoutMillis);
+ this.retryConfig = createRetryConfig(builder.timeoutMillis, builder.maxRetries);
+ if (StringUtils.isBlank(builder.baseUrl)) {
+ throw new IllegalArgumentException("Api baseUrl can't be null");
+ }
+ this.baseUrl = builder.baseUrl;
+ }
+
+ private static RetryConfig createRetryConfig(long initialInterval, int maxAttempts) {
+ return RetryConfig.custom()
+ .maxAttempts(maxAttempts)
+ .intervalFunction(IntervalFunction.ofExponentialBackoff(initialInterval, BACKOFF_MULTIPLIER))
+ .retryOnResult(response -> response instanceof Response> && !((Response>) response).isSuccessful())
+ .failAfterMaxAttempts(true)
+ .build();
+ }
+
+ @Override
+ public Retrofit provideRetrofitBuilder() {
+ return new Retrofit.Builder()
+ .addCallAdapterFactory(RetryCallAdapter.of(Retry.of("chapa-retry", retryConfig)))
+ .baseUrl(this.baseUrl)
+ .addConverterFactory(GsonConverterFactory.create())
+ .client(httpClient)
+ .build();
+ }
+
+ public static class Builder {
+ private long timeoutMillis = DEFAULT_TIMEOUT;
+ private int maxRetries = DEFAULT_RETRY_COUNT;
+ private String baseUrl = "";
+
+ public Builder timeout(long timeoutMillis) {
+ this.timeoutMillis = timeoutMillis;
+ return this;
+ }
+
+ public Builder maxRetries(int maxRetries) {
+ this.maxRetries = maxRetries;
+ return this;
+ }
+
+ public Builder baseUrl(String baseUrl) {
+ this.baseUrl = baseUrl;
+ return this;
+ }
+
+ public RetrierRetrofitClientProvider build() {
+ return new RetrierRetrofitClientProvider(this);
+ }
+ }
+}
diff --git a/src/main/java/com/yaphet/chapa/client/provider/RetrofitClientProvider.java b/src/main/java/com/yaphet/chapa/client/provider/RetrofitClientProvider.java
new file mode 100644
index 0000000..61b993b
--- /dev/null
+++ b/src/main/java/com/yaphet/chapa/client/provider/RetrofitClientProvider.java
@@ -0,0 +1,13 @@
+package com.yaphet.chapa.client.provider;
+
+import okhttp3.OkHttpClient;
+import retrofit2.Retrofit;
+
+public interface RetrofitClientProvider {
+
+ Retrofit provideRetrofitBuilder();
+
+ RetrofitClientProvider setDebug(boolean debug);
+
+ RetrofitClientProvider setClient(OkHttpClient client);
+}
diff --git a/src/main/java/com/yaphet/chapa/model/Bank.java b/src/main/java/com/yaphet/chapa/model/Bank.java
index 079f0a7..3cfb298 100644
--- a/src/main/java/com/yaphet/chapa/model/Bank.java
+++ b/src/main/java/com/yaphet/chapa/model/Bank.java
@@ -1,17 +1,42 @@
package com.yaphet.chapa.model;
+import com.google.gson.annotations.JsonAdapter;
import com.google.gson.annotations.SerializedName;
+import com.yaphet.chapa.utility.LocalDateTimeDeserializer;
+
+import java.time.LocalDateTime;
public class Bank {
private String id;
+
private String name;
+
@SerializedName("country_id")
private int countryId;
+
+ private Integer active;
+
+ @SerializedName("acct_length")
+ private Integer accountLength;
+
+ @SerializedName("is_mobilemoney")
+ private Integer isMobileMoney;
+
+ @SerializedName("is_rtgs")
+ private Integer isRtgs;
+
+ private String swift;
+
+ private String currency;
+
@SerializedName("created_at")
- private String createdAt;
+ @JsonAdapter(LocalDateTimeDeserializer.class)
+ private LocalDateTime createdAt;
+
@SerializedName("updated_at")
- private String updatedAt;
+ @JsonAdapter(LocalDateTimeDeserializer.class)
+ private LocalDateTime updatedAt;
public String getId() {
return id;
@@ -40,21 +65,80 @@ public Bank setCountryId(int countryId) {
return this;
}
- public String getCreatedAt() {
+ public Integer getActive() {
+ return active;
+ }
+
+ public void setActive(Integer active) {
+ this.active = active;
+ }
+
+ public Integer getAccountLength() {
+ return accountLength;
+ }
+
+ public void setAccountLength(Integer accountLength) {
+ this.accountLength = accountLength;
+ }
+
+ public Integer getIsMobileMoney() {
+ return isMobileMoney;
+ }
+
+ public void setIsMobileMoney(Integer isMobileMoney) {
+ this.isMobileMoney = isMobileMoney;
+ }
+
+ public Integer getIsRtgs() {
+ return isRtgs;
+ }
+
+ public void setIsRtgs(Integer isRtgs) {
+ this.isRtgs = isRtgs;
+ }
+
+ public String getSwift() {
+ return swift;
+ }
+
+ public void setSwift(String swift) {
+ this.swift = swift;
+ }
+
+ public String getCurrency() {
+ return currency;
+ }
+
+ public void setCurrency(String currency) {
+ this.currency = currency;
+ }
+
+ public LocalDateTime getCreatedAt() {
return createdAt;
}
- public Bank setCreatedAt(String createdAt) {
+ public void setCreatedAt(LocalDateTime createdAt) {
this.createdAt = createdAt;
- return this;
}
- public String getUpdatedAt() {
+ public LocalDateTime getUpdatedAt() {
return updatedAt;
}
- public Bank setUpdatedAt(String updatedAt) {
+ public void setUpdatedAt(LocalDateTime updatedAt) {
this.updatedAt = updatedAt;
- return this;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder("Bank{");
+ sb.append("name='").append(name).append('\'');
+ sb.append(", countryId=").append(countryId);
+ sb.append(", active=").append(active);
+ sb.append(", accountLength=").append(accountLength);
+ sb.append(", swift='").append(swift).append('\'');
+ sb.append(", currency='").append(currency).append('\'');
+ sb.append('}');
+ return sb.toString();
}
}
diff --git a/src/main/java/com/yaphet/chapa/model/InitializeResponse.java b/src/main/java/com/yaphet/chapa/model/InitializeResponse.java
new file mode 100644
index 0000000..2891ea2
--- /dev/null
+++ b/src/main/java/com/yaphet/chapa/model/InitializeResponse.java
@@ -0,0 +1,76 @@
+package com.yaphet.chapa.model;
+
+import com.google.gson.annotations.SerializedName;
+
+public class InitializeResponse extends Response {
+
+ private Data data;
+
+ public InitializeResponse() {
+ }
+
+ public InitializeResponse(String rawJson, String message, String status, int statusCode, Data data) {
+ super(rawJson, message, status, statusCode);
+ this.data = data;
+ }
+
+ @Override
+ public InitializeResponse setMessage(String message) {
+ super.setMessage(message);
+ return this;
+ }
+
+ @Override
+ public InitializeResponse setStatus(String status) {
+ super.setStatus(status);
+ return this;
+ }
+
+ @Override
+ public InitializeResponse setStatusCode(int statusCode) {
+ super.setStatusCode(statusCode);
+ return this;
+ }
+
+ @Override
+ public InitializeResponse setRawJson(String rawJson) {
+ super.setRawJson(rawJson);
+ return this;
+ }
+
+ public InitializeResponse setData(Data data) {
+ this.data = data;
+ return this;
+ }
+
+ public Data getData() {
+ return data;
+ }
+
+ public static class Data {
+ @SerializedName("checkout_url")
+ private String checkOutUrl;
+
+ public String getCheckOutUrl() {
+ return checkOutUrl;
+ }
+
+ public void setCheckOutUrl(String checkOutUrl) {
+ this.checkOutUrl = checkOutUrl;
+ }
+
+ @Override
+ public String toString() {
+ return "Data {" + "checkOutUrl='" + checkOutUrl + "'}";
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "InitializeResponse{" + "status=" + this.getStatus() +
+ ", statusCode=" + this.getStatusCode() +
+ ", message=" + this.getMessage() +
+ ", data=" + data +
+ "}";
+ }
+}
diff --git a/src/main/java/com/yaphet/chapa/model/InitializeResponseData.java b/src/main/java/com/yaphet/chapa/model/InitializeResponseData.java
deleted file mode 100644
index d08409b..0000000
--- a/src/main/java/com/yaphet/chapa/model/InitializeResponseData.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package com.yaphet.chapa.model;
-
-import com.google.gson.annotations.SerializedName;
-
-public class InitializeResponseData extends ResponseData {
-
- private Data data;
-
- public InitializeResponseData() {
- }
-
- public InitializeResponseData(String rawJson, String message, String status, int statusCode, Data data) {
- super(rawJson, message, status, statusCode);
- this.data = data;
- }
-
- public InitializeResponseData setMessage(String message) {
- return (InitializeResponseData) super.setMessage(message);
- }
-
- public InitializeResponseData setStatus(String status) {
- return (InitializeResponseData) super.setStatus(status);
- }
-
- public InitializeResponseData setStatusCode(int statusCode) {
- return (InitializeResponseData) super.setStatusCode(statusCode);
- }
-
- public InitializeResponseData setRawJson(String rawJson) {
- return (InitializeResponseData) super.setRawJson(rawJson);
- }
-
- public InitializeResponseData setData(Data data) {
- this.data = data;
- return this;
- }
-
- public Data getData() {
- return data;
- }
-
- public static class Data {
- @SerializedName("checkout_url")
- private String checkOutUrl;
-
- public String getCheckOutUrl() {
- return checkOutUrl;
- }
-
- public InitializeResponseData.Data setCheckOutUrl(String checkOutUrl) {
- this.checkOutUrl = checkOutUrl;
- return this;
- }
- }
-}
diff --git a/src/main/java/com/yaphet/chapa/model/PostData.java b/src/main/java/com/yaphet/chapa/model/PostData.java
index fddacca..7999a35 100644
--- a/src/main/java/com/yaphet/chapa/model/PostData.java
+++ b/src/main/java/com/yaphet/chapa/model/PostData.java
@@ -1,8 +1,13 @@
package com.yaphet.chapa.model;
import com.google.gson.annotations.SerializedName;
+import com.yaphet.chapa.utility.Validate;
import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
+
+import static com.yaphet.chapa.utility.Util.putIfNotNull;
/**
* The PostData class is an object representation of JSON form data
@@ -10,7 +15,7 @@
*/
public class PostData {
- private BigDecimal amount;
+ private String amount;
private String currency;
private String email;
@SerializedName("first_name")
@@ -26,12 +31,18 @@ public class PostData {
@SerializedName("subaccounts[id]")
private String subAccountId;
private Customization customization;
+ @SerializedName("phone_number")
+ private String phoneNumber;
- public BigDecimal getAmount() {
+ public String getAmount() {
return amount;
}
- public PostData setAmount(BigDecimal amount) {
+ public BigDecimal getAmountAsBigDecimal() {
+ return new BigDecimal(amount);
+ }
+
+ public PostData setAmount(String amount) {
this.amount = amount;
return this;
}
@@ -50,6 +61,9 @@ public String getEmail() {
}
public PostData setEmail(String email) {
+ if (!Validate.isValidEmail(email)) {
+ throw new IllegalArgumentException("Invalid email");
+ }
this.email = email;
return this;
}
@@ -116,4 +130,28 @@ public PostData setCustomization(Customization customization) {
this.customization = customization;
return this;
}
+
+ public String getPhoneNumber() {
+ return phoneNumber;
+ }
+
+ public PostData setPhoneNumber(String phoneNumber) {
+ if (!Validate.isValidPhoneNumber(phoneNumber)) {
+ throw new IllegalArgumentException("Invalid isValidPhoneNumber number");
+ }
+ this.phoneNumber = phoneNumber;
+ return this;
+ }
+
+ public Map getAsMap() {
+ Map postData = new HashMap<>();
+ putIfNotNull(postData, "amount", amount);
+ putIfNotNull(postData, "currency", currency);
+ putIfNotNull(postData, "email", email);
+ putIfNotNull(postData, "first_name", firstName);
+ putIfNotNull(postData, "last_name", lastName);
+ putIfNotNull(postData, "tx_ref", txRef);
+ putIfNotNull(postData, "phone_number", phoneNumber);
+ return postData;
+ }
}
diff --git a/src/main/java/com/yaphet/chapa/model/ResponseData.java b/src/main/java/com/yaphet/chapa/model/Response.java
similarity index 70%
rename from src/main/java/com/yaphet/chapa/model/ResponseData.java
rename to src/main/java/com/yaphet/chapa/model/Response.java
index ab9cd9c..ed960f0 100644
--- a/src/main/java/com/yaphet/chapa/model/ResponseData.java
+++ b/src/main/java/com/yaphet/chapa/model/Response.java
@@ -1,20 +1,20 @@
package com.yaphet.chapa.model;
/**
- * The ResponseData
class is an abstract class that
+ * The Response
class is an abstract class that
* represents the response data from Chapa API.
*/
-public abstract class ResponseData {
+public abstract class Response {
private String message;
private String status;
private int statusCode;
private String rawJson;
- public ResponseData() {
+ protected Response() {
}
- public ResponseData(String rawJson, String message, String status, int statusCode) {
+ protected Response(String rawJson, String message, String status, int statusCode) {
this.message = message;
this.status = status;
this.statusCode = statusCode;
@@ -25,7 +25,7 @@ public String getMessage() {
return message;
}
- public ResponseData setMessage(String message) {
+ public Response setMessage(String message) {
this.message = message;
return this;
}
@@ -34,7 +34,7 @@ public String getStatus() {
return status;
}
- public ResponseData setStatus(String status) {
+ public Response setStatus(String status) {
this.status = status;
return this;
}
@@ -43,7 +43,7 @@ public int getStatusCode() {
return statusCode;
}
- public ResponseData setStatusCode(int statusCode) {
+ public Response setStatusCode(int statusCode) {
this.statusCode = statusCode;
return this;
}
@@ -60,7 +60,7 @@ public String asString() {
return rawJson;
}
- public ResponseData setRawJson(String rawJson) {
+ public Response setRawJson(String rawJson) {
this.rawJson = rawJson;
return this;
}
diff --git a/src/main/java/com/yaphet/chapa/model/ResponseBanks.java b/src/main/java/com/yaphet/chapa/model/ResponseBanks.java
new file mode 100644
index 0000000..daa1d00
--- /dev/null
+++ b/src/main/java/com/yaphet/chapa/model/ResponseBanks.java
@@ -0,0 +1,54 @@
+package com.yaphet.chapa.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ResponseBanks extends Response {
+
+ private List data;
+
+ public List getData() {
+ if(data == null) {
+ return new ArrayList<>();
+ }
+ return data;
+ }
+
+ @Override
+ public ResponseBanks setMessage(String message) {
+ super.setMessage(message);
+ return this;
+ }
+
+ @Override
+ public ResponseBanks setStatus(String status) {
+ super.setStatus(status);
+ return this;
+ }
+
+ @Override
+ public ResponseBanks setStatusCode(int statusCode) {
+ super.setStatusCode(statusCode);
+ return this;
+ }
+
+ @Override
+ public ResponseBanks setRawJson(String rawJson) {
+ super.setRawJson(rawJson);
+ return this;
+ }
+
+ public ResponseBanks setData(List data) {
+ this.data = data;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return "ResponseBanks{" + "status=" + this.getStatus() +
+ ", statusCode=" + this.getStatusCode() +
+ ", message=" + this.getMessage() +
+ ", data=" + data +
+ '}';
+ }
+}
diff --git a/src/main/java/com/yaphet/chapa/model/SplitTypeEnum.java b/src/main/java/com/yaphet/chapa/model/SplitTypeEnum.java
new file mode 100644
index 0000000..86f4735
--- /dev/null
+++ b/src/main/java/com/yaphet/chapa/model/SplitTypeEnum.java
@@ -0,0 +1,6 @@
+package com.yaphet.chapa.model;
+
+public enum SplitTypeEnum {
+ PERCENTAGE,
+ FLAT
+}
diff --git a/src/main/java/com/yaphet/chapa/model/SubAccountDto.java b/src/main/java/com/yaphet/chapa/model/SubAccountDto.java
new file mode 100644
index 0000000..b5d61e3
--- /dev/null
+++ b/src/main/java/com/yaphet/chapa/model/SubAccountDto.java
@@ -0,0 +1,89 @@
+package com.yaphet.chapa.model;
+
+import com.google.gson.annotations.SerializedName;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static com.yaphet.chapa.utility.Util.putIfNotNull;
+
+public class SubAccountDto {
+
+ @SerializedName("business_name")
+ private String businessName;
+ @SerializedName("bank_code")
+ private String bankCode;
+ @SerializedName("account_name")
+ private String accountName;
+ @SerializedName("account_number")
+ private String accountNumber;
+ @SerializedName("split_type")
+ private SplitTypeEnum splitType;
+ @SerializedName("split_value")
+ private Double splitValue;
+
+ public String getBusinessName() {
+ return businessName;
+ }
+
+ public SubAccountDto setBusinessName(String businessName) {
+ this.businessName = businessName;
+ return this;
+ }
+
+ public String getBankCode() {
+ return bankCode;
+ }
+
+ public SubAccountDto setBankCode(String bankCode) {
+ this.bankCode = bankCode;
+ return this;
+ }
+
+ public String getAccountName() {
+ return accountName;
+ }
+
+ public SubAccountDto setAccountName(String accountName) {
+ this.accountName = accountName;
+ return this;
+ }
+
+ public String getAccountNumber() {
+ return accountNumber;
+ }
+
+ public SubAccountDto setAccountNumber(String accountNumber) {
+ this.accountNumber = accountNumber;
+ return this;
+ }
+
+ public SplitTypeEnum getSplitType() {
+ return splitType;
+ }
+
+ public SubAccountDto setSplitType(SplitTypeEnum splitType) {
+ this.splitType = splitType;
+ return this;
+ }
+
+ public Double getSplitValue() {
+ return splitValue;
+ }
+
+ public SubAccountDto setSplitValue(Double splitValue) {
+ this.splitValue = splitValue;
+ return this;
+ }
+
+ public Map getAsMap() {
+ Map account = new HashMap<>();
+ putIfNotNull(account, "business_name", businessName);
+ putIfNotNull(account, "account_name", accountName);
+ putIfNotNull(account, "account_number", accountNumber);
+ putIfNotNull(account, "bank_code", bankCode);
+ putIfNotNull(account, "split_type", splitType.name().toLowerCase());
+ putIfNotNull(account, "split_value", splitValue != null ? splitValue.toString() : null);
+ return account;
+ }
+}
diff --git a/src/main/java/com/yaphet/chapa/model/SubAccountResponse.java b/src/main/java/com/yaphet/chapa/model/SubAccountResponse.java
new file mode 100644
index 0000000..0bfa337
--- /dev/null
+++ b/src/main/java/com/yaphet/chapa/model/SubAccountResponse.java
@@ -0,0 +1,72 @@
+package com.yaphet.chapa.model;
+
+import com.google.gson.annotations.SerializedName;
+
+public class SubAccountResponse extends Response {
+
+ private Data data;
+
+ public SubAccountResponse() {
+ }
+
+ public SubAccountResponse(String rawJson, String message, String status, int statusCode, Data data) {
+ super(rawJson, message, status, statusCode);
+ this.data = data;
+ }
+
+ public SubAccountResponse setData(Data data) {
+ this.data = data;
+ return this;
+ }
+
+ @Override
+ public SubAccountResponse setMessage(String message) {
+ super.setMessage(message);
+ return this;
+ }
+
+ @Override
+ public SubAccountResponse setStatus(String status) {
+ super.setStatus(status);
+ return this;
+ }
+
+ @Override
+ public SubAccountResponse setStatusCode(int statusCode) {
+ super.setStatusCode(statusCode);
+ return this;
+ }
+
+ @Override
+ public SubAccountResponse setRawJson(String rawJson) {
+ super.setRawJson(rawJson);
+ return this;
+ }
+
+ public Data getData() {
+ return data;
+ }
+
+ public static class Data {
+ @SerializedName("subaccounts[id]")
+ private String subAccountId;
+
+ public String getSubAccountId() {
+ return subAccountId;
+ }
+
+ public Data setSubAccountId(String subAccountId) {
+ this.subAccountId = subAccountId;
+ return this;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "SubAccountResponse{" + "status=" + this.getStatus() +
+ ", statusCode=" + this.getStatusCode() +
+ ", message=" + this.getMessage() +
+ ", data=" + data +
+ '}';
+ }
+}
diff --git a/src/main/java/com/yaphet/chapa/model/SubAccountResponseData.java b/src/main/java/com/yaphet/chapa/model/SubAccountResponseData.java
deleted file mode 100644
index 0b6b9d4..0000000
--- a/src/main/java/com/yaphet/chapa/model/SubAccountResponseData.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package com.yaphet.chapa.model;
-
-import com.google.gson.annotations.SerializedName;
-
-public class SubAccountResponseData extends ResponseData {
-
- private Data data;
-
- public SubAccountResponseData() {
- }
-
- public SubAccountResponseData(String rawJson, String message, String status, int statusCode, Data data) {
- super(rawJson, message, status, statusCode);
- this.data = data;
- }
-
- public SubAccountResponseData setMessage(String message) {
- return (SubAccountResponseData) super.setMessage(message);
- }
-
- public SubAccountResponseData setStatus(String status) {
- return (SubAccountResponseData) super.setStatus(status);
- }
-
- public SubAccountResponseData setStatusCode(int statusCode) {
- return (SubAccountResponseData) super.setStatusCode(statusCode);
- }
-
- public SubAccountResponseData setRawJson(String rawJson) {
- return (SubAccountResponseData) super.setRawJson(rawJson);
- }
-
- public SubAccountResponseData setData(Data data) {
- this.data = data;
- return this;
- }
-
- public Data getData() {
- return data;
- }
-
- public static class Data {
- @SerializedName("subaccounts[id]")
- private String subAccountId;
-
- public String getSubAccountId() {
- return subAccountId;
- }
-
- public Data setSubAccountId(String subAccountId) {
- this.subAccountId = subAccountId;
- return this;
- }
- }
-}
diff --git a/src/main/java/com/yaphet/chapa/model/VerifyResponse.java b/src/main/java/com/yaphet/chapa/model/VerifyResponse.java
new file mode 100644
index 0000000..889db93
--- /dev/null
+++ b/src/main/java/com/yaphet/chapa/model/VerifyResponse.java
@@ -0,0 +1,249 @@
+package com.yaphet.chapa.model;
+
+import com.google.gson.annotations.JsonAdapter;
+import com.google.gson.annotations.SerializedName;
+import com.yaphet.chapa.utility.LocalDateTimeDeserializer;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+public class VerifyResponse extends Response {
+
+ private Data data;
+
+ public VerifyResponse() {
+ }
+
+ public VerifyResponse(String rawJson, String message, String status, int statusCode, Data data) {
+ super(rawJson, message, status, statusCode);
+ this.data = data;
+ }
+
+ @Override
+ public VerifyResponse setMessage(String message) {
+ super.setMessage(message);
+ return this;
+ }
+
+ @Override
+ public VerifyResponse setStatus(String status) {
+ super.setStatus(status);
+ return this;
+ }
+
+ @Override
+ public VerifyResponse setStatusCode(int statusCode) {
+ super.setStatusCode(statusCode);
+ return this;
+ }
+
+ @Override
+ public VerifyResponse setRawJson(String rawJson) {
+ super.setRawJson(rawJson);
+ return this;
+ }
+
+ public VerifyResponse setData(Data data) {
+ this.data = data;
+ return this;
+ }
+
+ public Data getData() {
+ return data;
+ }
+
+ public static class Data {
+ @SerializedName("first_name")
+ private String firstName;
+ @SerializedName("last_name")
+ private String lastName;
+ private String email;
+ private String currency;
+ private BigDecimal amount;
+ private BigDecimal charge;
+ private String mode;
+ private String method;
+ private String type;
+ private String status;
+ private String reference;
+ @SerializedName("tx_ref")
+ private String txRef;
+ private Customization customization;
+ private String meta;
+ @SerializedName("created_at")
+ @JsonAdapter(LocalDateTimeDeserializer.class)
+ private LocalDateTime createdAt;
+ @SerializedName("updated_at")
+ @JsonAdapter(LocalDateTimeDeserializer.class)
+ private LocalDateTime updatedAt;
+
+ @SerializedName("first_name")
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public Data setFirstName(String firstName) {
+ this.firstName = firstName;
+ return this;
+ }
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ public Data setLastName(String lastName) {
+ this.lastName = lastName;
+ return this;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public Data setEmail(String email) {
+ this.email = email;
+ return this;
+ }
+
+ public String getCurrency() {
+ return currency;
+ }
+
+ public Data setCurrency(String currency) {
+ this.currency = currency;
+ return this;
+ }
+
+ public BigDecimal getAmount() {
+ return amount;
+ }
+
+ public Data setAmount(BigDecimal amount) {
+ this.amount = amount;
+ return this;
+ }
+
+ public BigDecimal getCharge() {
+ return charge;
+ }
+
+ public Data setCharge(BigDecimal charge) {
+ this.charge = charge;
+ return this;
+ }
+
+ public String getMode() {
+ return mode;
+ }
+
+ public Data setMode(String mode) {
+ this.mode = mode;
+ return this;
+ }
+
+ public String getMethod() {
+ return method;
+ }
+
+ public Data setMethod(String method) {
+ this.method = method;
+ return this;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public Data setType(String type) {
+ this.type = type;
+ return this;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public Data setStatus(String status) {
+ this.status = status;
+ return this;
+ }
+
+ public String getReference() {
+ return reference;
+ }
+
+ public Data setReference(String reference) {
+ this.reference = reference;
+ return this;
+ }
+
+ public String getTxRef() {
+ return txRef;
+ }
+
+ public Data setTxRef(String txRef) {
+ this.txRef = txRef;
+ return this;
+ }
+
+ public Customization getCustomization() {
+ return customization;
+ }
+
+ public Data setCustomization(Customization customization) {
+ this.customization = customization;
+ return this;
+ }
+
+ public String getMeta() {
+ return meta;
+ }
+
+ public Data setMeta(String meta) {
+ this.meta = meta;
+ return this;
+ }
+
+ public LocalDateTime getCreatedAt() {
+ return createdAt;
+ }
+
+ public Data setCreatedAt(LocalDateTime createdAt) {
+ this.createdAt = createdAt;
+ return this;
+ }
+
+ public LocalDateTime getUpdatedAt() {
+ return updatedAt;
+ }
+
+ public Data setUpdatedAt(LocalDateTime updatedAt) {
+ this.updatedAt = updatedAt;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return "Data{" + "firstName='" + firstName + '\'' +
+ ", currency='" + currency + '\'' +
+ ", amount=" + amount +
+ ", charge=" + charge +
+ ", mode='" + mode + '\'' +
+ ", method='" + method + '\'' +
+ ", type='" + type + '\'' +
+ ", status='" + status + '\'' +
+ ", reference='" + reference + '\'' +
+ ", txRef='" + txRef + '\'' +
+ '}';
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "VerifyResponse{" + "status=" + this.getStatus() +
+ ", statusCode=" + this.getStatusCode() +
+ ", message=" + this.getMessage() +
+ ", data=" + data +
+ '}';
+ }
+}
diff --git a/src/main/java/com/yaphet/chapa/model/VerifyResponseData.java b/src/main/java/com/yaphet/chapa/model/VerifyResponseData.java
deleted file mode 100644
index c9bcb0d..0000000
--- a/src/main/java/com/yaphet/chapa/model/VerifyResponseData.java
+++ /dev/null
@@ -1,218 +0,0 @@
-package com.yaphet.chapa.model;
-
-import com.google.gson.annotations.JsonAdapter;
-import com.google.gson.annotations.SerializedName;
-import com.yaphet.chapa.utility.LocalDateTimeDeserializer;
-
-import java.math.BigDecimal;
-import java.time.LocalDateTime;
-
-public class VerifyResponseData extends ResponseData {
-
- private Data data;
-
- public VerifyResponseData() {
- }
-
- public VerifyResponseData(String rawJson, String message, String status, int statusCode, Data data) {
- super(rawJson, message, status, statusCode);
- this.data = data;
- }
-
- public VerifyResponseData setMessage(String message) {
- return (VerifyResponseData) super.setMessage(message);
- }
-
- public VerifyResponseData setStatus(String status) {
- return (VerifyResponseData) super.setStatus(status);
- }
-
- public VerifyResponseData setStatusCode(int statusCode) {
- return (VerifyResponseData) super.setStatusCode(statusCode);
- }
-
- public VerifyResponseData setRawJson(String rawJson) {
- return (VerifyResponseData) super.setRawJson(rawJson);
- }
-
- public VerifyResponseData setData(Data data) {
- this.data = data;
- return this;
- }
-
- public Data getData() {
- return data;
- }
-
- public static class Data {
-
- @SerializedName("first_name")
- private String firstName;
- @SerializedName("last_name")
- private String lastName;
- private String email;
- private String currency;
- private BigDecimal amount;
- private BigDecimal charge;
- private String mode;
- private String method;
- private String type;
- private String status;
- private String reference;
- @SerializedName("tx_ref")
- private String txRef;
- private Customization customization;
- private String meta;
- @SerializedName("created_at")
- @JsonAdapter(LocalDateTimeDeserializer.class)
- private LocalDateTime createdAt;
- @SerializedName("updated_at")
- @JsonAdapter(LocalDateTimeDeserializer.class)
- private LocalDateTime updatedAt;
-
- @SerializedName("first_name")
- public String getFirstName() {
- return firstName;
- }
-
- public VerifyResponseData.Data setFirstName(String firstName) {
- this.firstName = firstName;
- return this;
- }
-
- public String getLastName() {
- return lastName;
- }
-
- public VerifyResponseData.Data setLastName(String lastName) {
- this.lastName = lastName;
- return this;
- }
-
- public String getEmail() {
- return email;
- }
-
- public VerifyResponseData.Data setEmail(String email) {
- this.email = email;
- return this;
- }
-
- public String getCurrency() {
- return currency;
- }
-
- public VerifyResponseData.Data setCurrency(String currency) {
- this.currency = currency;
- return this;
- }
-
- public BigDecimal getAmount() {
- return amount;
- }
-
- public VerifyResponseData.Data setAmount(BigDecimal amount) {
- this.amount = amount;
- return this;
- }
-
- public BigDecimal getCharge() {
- return charge;
- }
-
- public VerifyResponseData.Data setCharge(BigDecimal charge) {
- this.charge = charge;
- return this;
- }
-
- public String getMode() {
- return mode;
- }
-
- public VerifyResponseData.Data setMode(String mode) {
- this.mode = mode;
- return this;
- }
-
- public String getMethod() {
- return method;
- }
-
- public VerifyResponseData.Data setMethod(String method) {
- this.method = method;
- return this;
- }
-
- public String getType() {
- return type;
- }
-
- public VerifyResponseData.Data setType(String type) {
- this.type = type;
- return this;
- }
-
- public String getStatus() {
- return status;
- }
-
- public VerifyResponseData.Data setStatus(String status) {
- this.status = status;
- return this;
- }
-
- public String getReference() {
- return reference;
- }
-
- public VerifyResponseData.Data setReference(String reference) {
- this.reference = reference;
- return this;
- }
-
- public String getTxRef() {
- return txRef;
- }
-
- public VerifyResponseData.Data setTxRef(String txRef) {
- this.txRef = txRef;
- return this;
- }
-
- public Customization getCustomization() {
- return customization;
- }
-
- public VerifyResponseData.Data setCustomization(Customization customization) {
- this.customization = customization;
- return this;
- }
-
- public String getMeta() {
- return meta;
- }
-
- public VerifyResponseData.Data setMeta(String meta) {
- this.meta = meta;
- return this;
- }
-
- public LocalDateTime getCreatedAt() {
- return createdAt;
- }
-
- public VerifyResponseData.Data setCreatedAt(LocalDateTime createdAt) {
- this.createdAt = createdAt;
- return this;
- }
-
- public LocalDateTime getUpdatedAt() {
- return updatedAt;
- }
-
- public VerifyResponseData.Data setUpdatedAt(LocalDateTime updatedAt) {
- this.updatedAt = updatedAt;
- return this;
- }
- }
-}
diff --git a/src/main/java/com/yaphet/chapa/utility/LocalDateTimeDeserializer.java b/src/main/java/com/yaphet/chapa/utility/LocalDateTimeDeserializer.java
index 67c0f07..8dae897 100644
--- a/src/main/java/com/yaphet/chapa/utility/LocalDateTimeDeserializer.java
+++ b/src/main/java/com/yaphet/chapa/utility/LocalDateTimeDeserializer.java
@@ -9,16 +9,10 @@
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
-/**
- * Custom deserializer for LocalDateTime objects.
- */
public class LocalDateTimeDeserializer implements JsonDeserializer {
@Override
public LocalDateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
- String dateTimeString = json.getAsString();
- DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'");
- LocalDateTime dateTime = LocalDateTime.parse(dateTimeString, formatter);
- return dateTime;
+ return LocalDateTime.parse(json.getAsString(), DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'"));
}
}
diff --git a/src/main/java/com/yaphet/chapa/utility/StringUtils.java b/src/main/java/com/yaphet/chapa/utility/StringUtils.java
new file mode 100644
index 0000000..2b12629
--- /dev/null
+++ b/src/main/java/com/yaphet/chapa/utility/StringUtils.java
@@ -0,0 +1,40 @@
+package com.yaphet.chapa.utility;
+
+public final class StringUtils {
+ public static final String EMPTY = "";
+
+ public static boolean isEmpty(String str) {
+ return str == null || str.isEmpty();
+ }
+
+ public static boolean isBlank(String str) {
+ return str == null || str.trim().isEmpty();
+ }
+
+ public static boolean isNotBlank(String str) {
+ return !isBlank(str);
+ }
+
+ public static String nullToEmpty(String str) {
+ return str == null ? "" : str;
+ }
+
+ public static String defaultIfEmpty(String str, String defaultStr) {
+ return isEmpty(str) ? defaultStr : str;
+ }
+
+ public static String reverse(String str) {
+ return isEmpty(str) ? str : new StringBuilder(str).reverse().toString();
+ }
+
+ public static String capitalize(String str) {
+ if (isEmpty(str)) {
+ return str;
+ }
+ return Character.toUpperCase(str.charAt(0)) + (str.length() > 1 ? str.substring(1) : "");
+ }
+
+ private StringUtils() {
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/yaphet/chapa/utility/Util.java b/src/main/java/com/yaphet/chapa/utility/Util.java
index c972235..b70c9ae 100644
--- a/src/main/java/com/yaphet/chapa/utility/Util.java
+++ b/src/main/java/com/yaphet/chapa/utility/Util.java
@@ -1,131 +1,43 @@
package com.yaphet.chapa.utility;
-import java.lang.reflect.Type;
-import java.math.BigDecimal;
-import java.time.Clock;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.yaphet.chapa.Chapa;
+
import java.time.LocalDateTime;
-import java.time.format.DateTimeFormatter;
-import java.util.List;
import java.util.Map;
-import java.util.UUID;
-import com.google.gson.Gson;
-import com.google.gson.JsonObject;
-import com.google.gson.reflect.TypeToken;
-import com.yaphet.chapa.model.*;
+import static com.yaphet.chapa.utility.StringUtils.isBlank;
/**
- * The Util
class serves as a helper class for the main {@link com.yaphet.chapa.Chapa} class.
+ * The Util
class serves as a helper class for the main {@link Chapa} class.
*/
public class Util {
- private static final Clock CLOCK = Clock.systemDefaultZone();
- private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("dd-MM-yy-HH-mm-ss");
- private final static Gson JSON_MAPPER = new Gson();
-
- /**
- * @param jsonData A json string to be mapped to a {@link PostData} object.
- * @return A {@link PostData} object which contains post fields of the
- * provided JSON data.
- */
- public static PostData jsonToPostData(String jsonData) {
- if (!notNullAndEmpty(jsonData)) {
- throw new IllegalArgumentException("Can't map null or empty json to PostData object");
- }
-
- Map newMap = jsonToMap(jsonData);
- JsonObject jsonObject = JSON_MAPPER.fromJson(jsonData, JsonObject.class);
- Type bankListType = new TypeToken