diff --git a/pom.xml b/pom.xml
index c7ad738..55a6f5c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
ai.pluggy
pluggy-java
- 1.10.0
+ 1.11.0
jar
@@ -86,6 +86,24 @@
+
+
+
+ src/main/resources
+ true
+
+ pluggy.properties
+
+
+
+ src/main/resources
+ false
+
+ pluggy.properties
+
+
+
diff --git a/src/main/java/ai/pluggy/client/PluggyClient.java b/src/main/java/ai/pluggy/client/PluggyClient.java
index eda479c..f46227e 100644
--- a/src/main/java/ai/pluggy/client/PluggyClient.java
+++ b/src/main/java/ai/pluggy/client/PluggyClient.java
@@ -9,6 +9,7 @@
import ai.pluggy.client.response.ErrorResponse;
import ai.pluggy.exception.PluggyException;
import ai.pluggy.utils.Utils;
+import ai.pluggy.utils.Version;
import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
@@ -292,7 +293,7 @@ public String authenticate() throws IOException, PluggyException {
.post(body)
.addHeader("content-type", "application/json")
.addHeader("cache-control", "no-cache")
- .addHeader("User-Agent", "PluggyJava/0.16.2")
+ .addHeader("User-Agent", Version.userAgent())
.build();
String apiKey;
diff --git a/src/main/java/ai/pluggy/client/auth/ApiKeyAuthInterceptor.java b/src/main/java/ai/pluggy/client/auth/ApiKeyAuthInterceptor.java
index fff3926..fe2af9b 100644
--- a/src/main/java/ai/pluggy/client/auth/ApiKeyAuthInterceptor.java
+++ b/src/main/java/ai/pluggy/client/auth/ApiKeyAuthInterceptor.java
@@ -2,6 +2,7 @@
import static ai.pluggy.utils.Asserts.assertNotNull;
+import ai.pluggy.utils.Version;
import com.google.gson.Gson;
import java.io.IOException;
@@ -114,8 +115,7 @@ private Request requestWithAuth(Request originalRequest, String apiKey) {
// override the apiKey of the original request with the new one
return originalRequest.newBuilder()
.header(X_API_KEY_HEADER, apiKey)
- // TOOD: add dynamic version
- .header("User-Agent", "PluggyJava/0.16.2")
+ .header("User-Agent", Version.userAgent())
.build();
}
diff --git a/src/main/java/ai/pluggy/client/response/CreditCardAccountFeeType.java b/src/main/java/ai/pluggy/client/response/CreditCardAccountFeeType.java
new file mode 100644
index 0000000..4d449a2
--- /dev/null
+++ b/src/main/java/ai/pluggy/client/response/CreditCardAccountFeeType.java
@@ -0,0 +1,28 @@
+package ai.pluggy.client.response;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@AllArgsConstructor
+public enum CreditCardAccountFeeType {
+ @SerializedName("ANNUAL_FEE")
+ ANNUAL_FEE("ANNUAL_FEE"),
+ @SerializedName("ATM_WITHDRAWAL_DOMESTIC")
+ ATM_WITHDRAWAL_DOMESTIC("ATM_WITHDRAWAL_DOMESTIC"),
+ @SerializedName("ATM_WITHDRAWAL_INTERNATIONAL")
+ ATM_WITHDRAWAL_INTERNATIONAL("ATM_WITHDRAWAL_INTERNATIONAL"),
+ @SerializedName("EMERGENCY_CREDIT_EVALUATION")
+ EMERGENCY_CREDIT_EVALUATION("EMERGENCY_CREDIT_EVALUATION"),
+ @SerializedName("CARD_REISSUE")
+ CARD_REISSUE("CARD_REISSUE"),
+ @SerializedName("BILL_PAYMENT_FEE")
+ BILL_PAYMENT_FEE("BILL_PAYMENT_FEE"),
+ @SerializedName("SMS")
+ SMS("SMS"),
+ @SerializedName("OTHER")
+ OTHER("OTHER");
+
+ @Getter
+ private String value;
+}
diff --git a/src/main/java/ai/pluggy/client/response/CreditCardAccountOtherCreditType.java b/src/main/java/ai/pluggy/client/response/CreditCardAccountOtherCreditType.java
new file mode 100644
index 0000000..7ff49b1
--- /dev/null
+++ b/src/main/java/ai/pluggy/client/response/CreditCardAccountOtherCreditType.java
@@ -0,0 +1,20 @@
+package ai.pluggy.client.response;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@AllArgsConstructor
+public enum CreditCardAccountOtherCreditType {
+ @SerializedName("REVOLVING_CREDIT")
+ REVOLVING_CREDIT("REVOLVING_CREDIT"),
+ @SerializedName("BILL_INSTALLMENT")
+ BILL_INSTALLMENT("BILL_INSTALLMENT"),
+ @SerializedName("LOAN")
+ LOAN("LOAN"),
+ @SerializedName("OTHER")
+ OTHER("OTHER");
+
+ @Getter
+ private String value;
+}
diff --git a/src/main/java/ai/pluggy/client/response/CreditCardLimitLineName.java b/src/main/java/ai/pluggy/client/response/CreditCardLimitLineName.java
new file mode 100644
index 0000000..2dd7c97
--- /dev/null
+++ b/src/main/java/ai/pluggy/client/response/CreditCardLimitLineName.java
@@ -0,0 +1,24 @@
+package ai.pluggy.client.response;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@AllArgsConstructor
+public enum CreditCardLimitLineName {
+ @SerializedName("CREDITO_A_VISTA")
+ CREDITO_A_VISTA("CREDITO_A_VISTA"),
+ @SerializedName("CREDITO_PARCELADO")
+ CREDITO_PARCELADO("CREDITO_PARCELADO"),
+ @SerializedName("SAQUE_CREDITO_BRASIL")
+ SAQUE_CREDITO_BRASIL("SAQUE_CREDITO_BRASIL"),
+ @SerializedName("SAQUE_CREDITO_EXTERIOR")
+ SAQUE_CREDITO_EXTERIOR("SAQUE_CREDITO_EXTERIOR"),
+ @SerializedName("EMPRESTIMO_CARTAO_CONSIGNADO")
+ EMPRESTIMO_CARTAO_CONSIGNADO("EMPRESTIMO_CARTAO_CONSIGNADO"),
+ @SerializedName("OUTROS")
+ OUTROS("OUTROS");
+
+ @Getter
+ private String value;
+}
diff --git a/src/main/java/ai/pluggy/client/response/CreditData.java b/src/main/java/ai/pluggy/client/response/CreditData.java
index cd33570..4168fa9 100644
--- a/src/main/java/ai/pluggy/client/response/CreditData.java
+++ b/src/main/java/ai/pluggy/client/response/CreditData.java
@@ -3,12 +3,15 @@
import lombok.Builder;
import lombok.Data;
+import java.util.List;
+
@Data
@Builder
public class CreditData {
String level;
String brand;
+ String brandAdditionalInfo;
String balanceCloseDate;
String balanceDueDate;
Double availableCreditLimit;
@@ -17,4 +20,5 @@ public class CreditData {
Double creditLimit;
HolderType holderType;
CreditCardStatus status;
+ List disaggregatedCreditLimits;
}
diff --git a/src/main/java/ai/pluggy/client/response/DisaggregatedCreditLimit.java b/src/main/java/ai/pluggy/client/response/DisaggregatedCreditLimit.java
new file mode 100644
index 0000000..5c0cb41
--- /dev/null
+++ b/src/main/java/ai/pluggy/client/response/DisaggregatedCreditLimit.java
@@ -0,0 +1,14 @@
+package ai.pluggy.client.response;
+
+import lombok.Builder;
+import lombok.Data;
+
+@Data
+@Builder
+public class DisaggregatedCreditLimit {
+
+ CreditCardLimitLineName lineName;
+ String limitAmountReason;
+ Double customizedLimitAmount;
+ String customizedLimitAmountCurrencyCode;
+}
diff --git a/src/main/java/ai/pluggy/client/response/TransactionCreditCardMetadata.java b/src/main/java/ai/pluggy/client/response/TransactionCreditCardMetadata.java
index d5abeea..580ea0a 100644
--- a/src/main/java/ai/pluggy/client/response/TransactionCreditCardMetadata.java
+++ b/src/main/java/ai/pluggy/client/response/TransactionCreditCardMetadata.java
@@ -13,4 +13,8 @@ public class TransactionCreditCardMetadata {
Date purchaseDate;
String cardNumber;
String billId;
+ CreditCardAccountFeeType feeType;
+ String feeTypeAdditionalInfo;
+ CreditCardAccountOtherCreditType otherCreditsType;
+ String otherCreditsAdditionalInfo;
}
diff --git a/src/main/java/ai/pluggy/utils/Version.java b/src/main/java/ai/pluggy/utils/Version.java
new file mode 100644
index 0000000..fb0f35e
--- /dev/null
+++ b/src/main/java/ai/pluggy/utils/Version.java
@@ -0,0 +1,46 @@
+package ai.pluggy.utils;
+
+import java.io.InputStream;
+import java.util.Properties;
+
+/**
+ * Exposes the SDK version, derived from the Maven {@code project.version} at build time via
+ * resource filtering of {@code pluggy.properties}. Used to build the {@code User-Agent} header so it
+ * stays in sync with {@code pom.xml} automatically.
+ */
+public final class Version {
+
+ private static final String UNKNOWN = "unknown";
+ private static final String VERSION = load();
+
+ private Version() {
+ }
+
+ /** SDK version (e.g. {@code "1.11.0"}), or {@code "unknown"} if it can't be resolved. */
+ public static String get() {
+ return VERSION;
+ }
+
+ /** {@code User-Agent} header value, e.g. {@code "PluggyJava/1.11.0"}. */
+ public static String userAgent() {
+ return "PluggyJava/" + VERSION;
+ }
+
+ private static String load() {
+ try (InputStream in = Version.class.getResourceAsStream("/pluggy.properties")) {
+ if (in == null) {
+ return UNKNOWN;
+ }
+ Properties props = new Properties();
+ props.load(in);
+ String version = props.getProperty("version");
+ // Guard against an unfiltered placeholder (e.g. if resource filtering didn't run).
+ if (version == null || version.isEmpty() || version.startsWith("${")) {
+ return UNKNOWN;
+ }
+ return version;
+ } catch (Exception e) {
+ return UNKNOWN;
+ }
+ }
+}
diff --git a/src/main/resources/pluggy.properties b/src/main/resources/pluggy.properties
new file mode 100644
index 0000000..defbd48
--- /dev/null
+++ b/src/main/resources/pluggy.properties
@@ -0,0 +1 @@
+version=${project.version}
diff --git a/src/test/java/ai/pluggy/utils/VersionTest.java b/src/test/java/ai/pluggy/utils/VersionTest.java
new file mode 100644
index 0000000..ee63c63
--- /dev/null
+++ b/src/test/java/ai/pluggy/utils/VersionTest.java
@@ -0,0 +1,24 @@
+package ai.pluggy.utils;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+
+public class VersionTest {
+
+ @Test
+ public void version_isResolvedFromFilteredProperties() {
+ // Resource filtering replaces ${project.version} at build time. If the filtering config
+ // is removed, Version falls back to "unknown" and these assertions fail.
+ String version = Version.get();
+ assertFalse(version.isEmpty(), "version should not be empty");
+ assertFalse("unknown".equals(version), "version should resolve from pluggy.properties");
+ assertFalse(version.startsWith("${"), "version placeholder should be filtered");
+ }
+
+ @Test
+ public void userAgent_hasExpectedPrefix() {
+ assertTrue(Version.userAgent().startsWith("PluggyJava/"));
+ }
+}