From 393466ef991c5b735635a406abcf05abf12d193e Mon Sep 17 00:00:00 2001 From: Johan Lindkvist Date: Tue, 8 Jul 2025 14:22:32 +0200 Subject: [PATCH 1/4] Add lastorderstep and orderstatuses to cancel notification data Add ReturnToAppURL Deprecate urlSheme Add @Getter to method and uuid Update signer to take a JsonNode dataNode for verifying signature to handle null/not send values --- .../com/trustly/api/client/DefaultJsonRpcSigner.java | 4 ++-- .../java/com/trustly/api/client/JsonRpcSigner.java | 2 +- .../com/trustly/api/client/NotificationArgs.java | 3 +++ .../com/trustly/api/client/TrustlyApiClient.java | 9 ++++++++- .../domain/common/AbstractAccountDataAttributes.java | 12 ++++++++++++ .../domain/notifications/CancelNotificationData.java | 6 ++++++ src/test/java/com/trustly/api/NoOpJsonRpcSigner.java | 2 +- 7 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/trustly/api/client/DefaultJsonRpcSigner.java b/src/main/java/com/trustly/api/client/DefaultJsonRpcSigner.java index 61a34d6..d6f211d 100644 --- a/src/main/java/com/trustly/api/client/DefaultJsonRpcSigner.java +++ b/src/main/java/com/trustly/api/client/DefaultJsonRpcSigner.java @@ -95,13 +95,13 @@ private String createSignature(String method, String uuid, T d } @Override - public > void verify(IRequest

request) throws TrustlySignatureException { + public > void verify(IRequest

request, JsonNode dataNode) throws TrustlySignatureException { String uuid = (request.getParams() == null) ? null : request.getParams().getUuid(); String signature = (request.getParams() == null) ? null : request.getParams().getSignature(); D data = (request.getParams() == null) ? null : request.getParams().getData(); - this.verify(request.getMethod(), uuid, signature, data, null); + this.verify(request.getMethod(), uuid, signature, data, dataNode); } @Override diff --git a/src/main/java/com/trustly/api/client/JsonRpcSigner.java b/src/main/java/com/trustly/api/client/JsonRpcSigner.java index 8a07339..40e6fee 100644 --- a/src/main/java/com/trustly/api/client/JsonRpcSigner.java +++ b/src/main/java/com/trustly/api/client/JsonRpcSigner.java @@ -15,7 +15,7 @@ public interface JsonRpcSigner { JsonRpcResponse sign(JsonRpcResponse response); - > void verify(IRequest

request) throws TrustlySignatureException; + > void verify(IRequest

request, JsonNode dataNode) throws TrustlySignatureException; void verify(JsonRpcResponse response, JsonNode nodeResponse) throws TrustlySignatureException; } diff --git a/src/main/java/com/trustly/api/client/NotificationArgs.java b/src/main/java/com/trustly/api/client/NotificationArgs.java index 25e49e6..8eb7812 100644 --- a/src/main/java/com/trustly/api/client/NotificationArgs.java +++ b/src/main/java/com/trustly/api/client/NotificationArgs.java @@ -26,7 +26,10 @@ public interface NotificationFailHandler { @Valid private final D data; + @Getter private final String method; + + @Getter private final String uuid; private final NotificationOkHandler onOK; diff --git a/src/main/java/com/trustly/api/client/TrustlyApiClient.java b/src/main/java/com/trustly/api/client/TrustlyApiClient.java index f49a34c..0fe283c 100644 --- a/src/main/java/com/trustly/api/client/TrustlyApiClient.java +++ b/src/main/java/com/trustly/api/client/TrustlyApiClient.java @@ -720,12 +720,19 @@ private void handleNotification( NotificationFailHandler onFailed ) throws IOException, TrustlyValidationException, TrustlySignatureException { + // Get the JsonNode for the data field for verifying later + JsonNode jsonToken = this.objectMapper.readTree(jsonString); + JsonNode dataToken = null; + if (jsonToken.at("/params/data") != null) { + dataToken = jsonToken.at("/params/data"); + } + JavaType javaRequestType = this.objectMapper.getTypeFactory().constructParametricType(NotificationRequest.class, meta.getDataClass()); NotificationRequest rpcRequest = this.objectMapper.readValue(jsonString, javaRequestType); // Verify the notification (RpcRequest from Trustly) signature. try { - this.signer.verify(rpcRequest); + this.signer.verify(rpcRequest, dataToken); } catch (TrustlySignatureException ex) { throw new TrustlySignatureException( "Could not validate signature of notification from Trustly. Is the public key for Trustly the correct one, for test or production?", diff --git a/src/main/java/com/trustly/api/domain/common/AbstractAccountDataAttributes.java b/src/main/java/com/trustly/api/domain/common/AbstractAccountDataAttributes.java index 7524a3c..117f077 100644 --- a/src/main/java/com/trustly/api/domain/common/AbstractAccountDataAttributes.java +++ b/src/main/java/com/trustly/api/domain/common/AbstractAccountDataAttributes.java @@ -138,9 +138,21 @@ public class AbstractAccountDataAttributes extends AbstractRequestParamsDataAttr String unchangeableNationalIdentificationNumber; /** + * @deprecated (see ReturnToAppURL) * If you are using Trustly from within your native iOS app, this attribute should be sent so that we can redirect the users back to your * app in case an external app is used for authentication (for example Mobile Bank ID in Sweden). */ + @Deprecated @JsonProperty("URLScheme") String urlScheme; + + /** + * When rendering the Trustly Checkout in a native app you are required to pass your application’s url as an attribute to the order + * initiation request. By doing so, Trustly can redirect users back to your app after using external identification apps such as + * Mobile BankID: Please visit this link for more info. It must not be included for transactions that are not originating from an app. + * NOTE! This value is only used for redirecting users back to the native app within the flows. + * See also SuccessURL and FailURL descriptions. + */ + @JsonProperty("ReturnToAppURL") + String returnToAppURL; } diff --git a/src/main/java/com/trustly/api/domain/notifications/CancelNotificationData.java b/src/main/java/com/trustly/api/domain/notifications/CancelNotificationData.java index d0a1bf0..9e5fda5 100644 --- a/src/main/java/com/trustly/api/domain/notifications/CancelNotificationData.java +++ b/src/main/java/com/trustly/api/domain/notifications/CancelNotificationData.java @@ -30,4 +30,10 @@ public class CancelNotificationData extends AbstractFromTrustlyRequestData JsonRpcResponse sign(JsonRpcResponse> void verify(IRequest

request) { + public > void verify(IRequest

request, JsonNode dataNode) { } From c9b07f39e4a64ac52ef089eeb6e090d6f202abaf Mon Sep 17 00:00:00 2001 From: Johan Lindkvist Date: Wed, 9 Jul 2025 11:04:34 +0200 Subject: [PATCH 2/4] Add azura deposit models and api method Add azura field to deposit request model --- .../trustly/api/client/TrustlyApiClient.java | 9 ++ .../deposit/DepositRequestDataAttributes.java | 7 ++ .../deposit/DepositRequestDataAzura.java | 45 ++++++++++ .../azura/AzuraDepositRequestData.java | 36 ++++++++ .../AzuraDepositRequestDataAttributes.java | 90 +++++++++++++++++++ .../azura/AzuraDepositResponseData.java | 42 +++++++++ .../AzuraDepositResponseDataAccount.java | 39 ++++++++ .../azura/AzuraDepositResponseDataBank.java | 50 +++++++++++ .../AzuraDepositResponseDataCountry.java | 40 +++++++++ .../AzuraDepositResponseDataTrustlyInfo.java | 39 ++++++++ .../java/com/trustly/api/RequestsTest.java | 27 ++++++ 11 files changed, 424 insertions(+) create mode 100644 src/main/java/com/trustly/api/domain/methods/deposit/DepositRequestDataAzura.java create mode 100644 src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraDepositRequestData.java create mode 100644 src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraDepositRequestDataAttributes.java create mode 100644 src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraDepositResponseData.java create mode 100644 src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraDepositResponseDataAccount.java create mode 100644 src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraDepositResponseDataBank.java create mode 100644 src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraDepositResponseDataCountry.java create mode 100644 src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraDepositResponseDataTrustlyInfo.java diff --git a/src/main/java/com/trustly/api/client/TrustlyApiClient.java b/src/main/java/com/trustly/api/client/TrustlyApiClient.java index 0fe283c..d98db06 100644 --- a/src/main/java/com/trustly/api/client/TrustlyApiClient.java +++ b/src/main/java/com/trustly/api/client/TrustlyApiClient.java @@ -39,6 +39,8 @@ import com.trustly.api.domain.methods.denywithdrawal.DenyWithdrawalResponseData; import com.trustly.api.domain.methods.deposit.DepositRequestData; import com.trustly.api.domain.methods.deposit.DepositResponseData; +import com.trustly.api.domain.methods.deposit.azura.AzuraDepositRequestData; +import com.trustly.api.domain.methods.deposit.azura.AzuraDepositResponseData; import com.trustly.api.domain.methods.getwithdrawals.GetWithdrawalsRequestData; import com.trustly.api.domain.methods.getwithdrawals.GetWithdrawalsResponseData; import com.trustly.api.domain.methods.merchantsettlement.MerchantSettlementRequestData; @@ -441,6 +443,13 @@ public WithdrawResponseData withdraw(WithdrawRequestData request) throws Trustly return this.sendRequest(request, WithdrawResponseData.class, "Withdraw", null); } + /** + * TODO insert javadoc + */ + public AzuraDepositResponseData azuraDeposit(AzuraDepositRequestData request) throws TrustlyRequestException { + return this.sendRequest(request, AzuraDepositResponseData.class, "AzuraDeposit", null); + } + // Notifications /** diff --git a/src/main/java/com/trustly/api/domain/methods/deposit/DepositRequestDataAttributes.java b/src/main/java/com/trustly/api/domain/methods/deposit/DepositRequestDataAttributes.java index a162bb0..b10197a 100644 --- a/src/main/java/com/trustly/api/domain/methods/deposit/DepositRequestDataAttributes.java +++ b/src/main/java/com/trustly/api/domain/methods/deposit/DepositRequestDataAttributes.java @@ -181,4 +181,11 @@ public class DepositRequestDataAttributes extends AbstractAmountConstrainedAccou */ @JsonProperty(value = "RequestKYC") private String requestKyc; + + /** + * The Deposit request starts the deposit process at Trustly. It includes the same parameters as a standard deposit request, + * along with an additional Azura object containing attributes. + */ + @JsonProperty(value = "Azura") + private DepositRequestDataAzura azura; } diff --git a/src/main/java/com/trustly/api/domain/methods/deposit/DepositRequestDataAzura.java b/src/main/java/com/trustly/api/domain/methods/deposit/DepositRequestDataAzura.java new file mode 100644 index 0000000..1379f79 --- /dev/null +++ b/src/main/java/com/trustly/api/domain/methods/deposit/DepositRequestDataAzura.java @@ -0,0 +1,45 @@ +package com.trustly.api.domain.methods.deposit; + +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.NotBlank; +import lombok.Builder; +import lombok.RequiredArgsConstructor; +import lombok.Value; +import lombok.extern.jackson.Jacksonized; + +@Value +@Builder(toBuilder = true) +@Jacksonized +@RequiredArgsConstructor +public class DepositRequestDataAzura { + + /** + * Same value that was returned in the response to the initial call to AzuraDeposit. + */ + @JsonProperty(value = "AzuraSessionID", required = true) + @NotBlank + String azuraSessionId; + + /** + * SELECT_ACCOUNT: Deposit will have specified account preselected. + * SELECT_BANK: Deposit will have specified bank preselected. + * NO_SELECTION: Deposit will not have a preselected account or bank. + */ + @JsonProperty(value = "Action", required = true) + @NotBlank + String action; + + /** + * Id of the account that user wants to use. Should be the value from the field ‘accountid’ that is returned from the AzuraDeposit call. + * Note: Required if Action is SELECT_ACCOUNT + */ + @JsonProperty("AccountID") + String accountId; + + /** + * Id of the bank to use. Should be the value from the field ‘bankid’ that is returned from the AzuraDeposit call. + * Note: Required if Action is SELECT_BANK + */ + @JsonProperty("BankID") + String bankId; +} diff --git a/src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraDepositRequestData.java b/src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraDepositRequestData.java new file mode 100644 index 0000000..f164950 --- /dev/null +++ b/src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraDepositRequestData.java @@ -0,0 +1,36 @@ +package com.trustly.api.domain.methods.deposit.azura; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.trustly.api.domain.base.AbstractToTrustlyRequestData; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.RequiredArgsConstructor; +import lombok.experimental.SuperBuilder; +import lombok.extern.jackson.Jacksonized; + +@Data +@SuperBuilder(toBuilder = true) +@EqualsAndHashCode(callSuper = true) +@RequiredArgsConstructor +@AllArgsConstructor +@Jacksonized +@JsonInclude(Include.NON_NULL) +public class AzuraDepositRequestData extends AbstractToTrustlyRequestData { + + @JsonProperty(value = "MessageID", required = true) + @NotBlank + private String messageId; + + @JsonProperty(value = "Attributes", required = true) + @JsonInclude(Include.NON_NULL) + @Valid + @Override + public AzuraDepositRequestDataAttributes getAttributes() { + return super.getAttributes(); + } +} diff --git a/src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraDepositRequestDataAttributes.java b/src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraDepositRequestDataAttributes.java new file mode 100644 index 0000000..3284e3c --- /dev/null +++ b/src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraDepositRequestDataAttributes.java @@ -0,0 +1,90 @@ +package com.trustly.api.domain.methods.deposit.azura; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.trustly.api.domain.base.AbstractRequestParamsDataAttributes; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Pattern; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.RequiredArgsConstructor; +import lombok.experimental.SuperBuilder; + +@Data +@SuperBuilder(toBuilder = true) +@EqualsAndHashCode(callSuper = true) +@RequiredArgsConstructor +@AllArgsConstructor +@JsonInclude(Include.NON_NULL) +public class AzuraDepositRequestDataAttributes extends AbstractRequestParamsDataAttributes { + + /** + * The email of the consumer. + */ + @JsonProperty(value = "Email") + @Email + String email; + + /** + * The mobile phone number of the end-user in international format. + */ + @JsonProperty(value = "MobilePhone") + String mobilePhone; + + /** + * ID, username, hash or anything uniquely identifying the end-user requesting the deposit. + * Preferably the same ID/username as used in the merchant's own backoffice in order to simplify + * for the merchant's support department. + */ + @JsonProperty(value = "EndUserID") + String endUserID; + + /** + * The ISO 3166-1-alpha-2 code of the end-user's country. + */ + @JsonProperty(value = "Country", required = true) + @NotBlank + @Pattern(regexp = "[A-Z]{2}") + String country; + + /** + * The currency of the end-user's account in the merchant's system. + */ + @JsonProperty(value = "Currency", required = true) + @NotBlank + String currency; + + /** + * Only for Gaming + * If it's set to 1, it means requiring KYC. + */ + @JsonProperty(value = "RequestKYC") + Integer requestKYC; + + /** + * Only for Express Merchant Onboarding + * Human-readable identifier of the consumer-facing merchant (e.g. legal name or trade name). + */ + @JsonProperty(value = "PSPMerchant") + String pspMerchant; + + /** + * Only for Trustly Direct Debit. + * Request a direct debit mandate from the selected account. 1 or 0. + * See section "Direct Debit Mandates" below for details. + */ + @JsonProperty(value = "RequestDirectDebitMandate") + String requestDirectDebitMandate; + + /** + * Only for Trustly Direct Debit. + * In order to let the consumer choose to sign up for a recurring mandate, + * the attribute QuickDeposit with the value 1 shall be included in the call. + */ + @JsonProperty(value = "QuickDeposit") + Integer quickDeposit; + +} diff --git a/src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraDepositResponseData.java b/src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraDepositResponseData.java new file mode 100644 index 0000000..e9c72bc --- /dev/null +++ b/src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraDepositResponseData.java @@ -0,0 +1,42 @@ +package com.trustly.api.domain.methods.deposit.azura; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.trustly.api.domain.base.AbstractResponseResultData; +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Value; +import lombok.experimental.SuperBuilder; +import lombok.extern.jackson.Jacksonized; + +@Value +@SuperBuilder +@EqualsAndHashCode(callSuper = true) +@AllArgsConstructor +@Jacksonized +public class AzuraDepositResponseData extends AbstractResponseResultData { + + /** + * ID that you will send in the next call. + */ + @JsonProperty("azurasessionid") + String azuraSessionId; + + /** + * Array of objects containing information about the found accounts, sorted with the best match listed first. + */ + @JsonProperty("accounts") + List accounts; + + /** + * Trustly assets. + */ + @JsonProperty("trustlyinfo") + AzuraDepositResponseDataTrustlyInfo trustlyInfo; + + /** + * A list of countries and their banks, which can be utilized to display bank logos in the checkout. + */ + @JsonProperty("countries") + List countries; +} diff --git a/src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraDepositResponseDataAccount.java b/src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraDepositResponseDataAccount.java new file mode 100644 index 0000000..24f5332 --- /dev/null +++ b/src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraDepositResponseDataAccount.java @@ -0,0 +1,39 @@ +package com.trustly.api.domain.methods.deposit.azura; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Value; +import lombok.extern.jackson.Jacksonized; + +@Value +@Builder +@AllArgsConstructor +@Jacksonized +public class AzuraDepositResponseDataAccount { + + /** + * Identifies the suggested account. + * You will send this account id in the next call if the user chose to continue with this account. + */ + @JsonProperty("accountid") + String accountId; + + /** + * A masked representation of the account number. + */ + @JsonProperty("accountnumbermasked") + String accountNumberMasked; + + /** + * The last digits of the account number. + */ + @JsonProperty("accountnumberlastdigits") + String accountNumberLastDigits; + + /** + * An object with bank data. + */ + @JsonProperty("bank") + AzuraDepositResponseDataBank bank; +} diff --git a/src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraDepositResponseDataBank.java b/src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraDepositResponseDataBank.java new file mode 100644 index 0000000..fcdde4a --- /dev/null +++ b/src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraDepositResponseDataBank.java @@ -0,0 +1,50 @@ +package com.trustly.api.domain.methods.deposit.azura; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Value; +import lombok.extern.jackson.Jacksonized; + +@Value +@Builder +@AllArgsConstructor +@Jacksonized +public class AzuraDepositResponseDataBank { + + /** + * Country code for the suggested account. ISO 3166-1 alpha-2 + */ + @JsonProperty("bankcountry") + String bankCountry; + + /** + * Bank code for the suggested account. This is 4 uppercase chars. + */ + @JsonProperty("bankcode") + String bankCode; + + /** + * Name of the bank. + */ + @JsonProperty("bankname") + String bankName; + + /** + * The ID of the bank. This ID should be used when initiating the deposit using SELECT_BANK action. + */ + @JsonProperty("bankid") + String bankId; + + /** + * If the bank is out of order. If true it should not be possible to select the bank in the merchant´s checkout. + */ + @JsonProperty("outoforder") + Boolean outOfOrder; + + /** + * Link to bank logo of the bank. + */ + @JsonProperty("banklogoround") + String bankLogoRound; +} diff --git a/src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraDepositResponseDataCountry.java b/src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraDepositResponseDataCountry.java new file mode 100644 index 0000000..6a22ef8 --- /dev/null +++ b/src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraDepositResponseDataCountry.java @@ -0,0 +1,40 @@ +package com.trustly.api.domain.methods.deposit.azura; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; +import java.util.Map; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Value; +import lombok.extern.jackson.Jacksonized; + +@Value +@Builder +@AllArgsConstructor +@Jacksonized +public class AzuraDepositResponseDataCountry { + + /** + * Country code ISO 3166-1 alpha-2 + */ + @JsonProperty("countrycode") + String countryCode; + + /** + * An object with mappings from two-letter ISO 639 language code to a link to Trustly’s terms and conditions. + */ + @JsonProperty("termsandconditions") + Map termsAndConditions; + + /** + * An object with mappings from two-letter ISO 639 language code to a link to Trustly’s privacy policy. + */ + @JsonProperty("privacypolicy") + Map privacyPolicy; + + /** + * Available banks in this country. + */ + @JsonProperty("banks") + List banks; +} diff --git a/src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraDepositResponseDataTrustlyInfo.java b/src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraDepositResponseDataTrustlyInfo.java new file mode 100644 index 0000000..41e3776 --- /dev/null +++ b/src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraDepositResponseDataTrustlyInfo.java @@ -0,0 +1,39 @@ +package com.trustly.api.domain.methods.deposit.azura; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Value; +import lombok.extern.jackson.Jacksonized; + +@Value +@Builder +@AllArgsConstructor +@Jacksonized +public class AzuraDepositResponseDataTrustlyInfo { + + /** + * Trustly assets. + */ + @JsonProperty("trustlylogo1") + String trustlyLogo1; + + /** + * Trustly assets. + */ + @JsonProperty("trustlylogo2") + String trustlyLogo2; + + /** + * Trustly assets. + */ + @JsonProperty("trustlylogo3") + String trustlyLogo3; + + /** + * Trustly assets. + */ + @JsonProperty("trustlylogo4") + String trustlyLogo4; +} diff --git a/src/test/java/com/trustly/api/RequestsTest.java b/src/test/java/com/trustly/api/RequestsTest.java index 34a4dfb..2cb25ac 100644 --- a/src/test/java/com/trustly/api/RequestsTest.java +++ b/src/test/java/com/trustly/api/RequestsTest.java @@ -13,6 +13,9 @@ import com.trustly.api.domain.methods.deposit.DepositRequestData; import com.trustly.api.domain.methods.deposit.DepositRequestDataAttributes; import com.trustly.api.domain.methods.deposit.DepositResponseData; +import com.trustly.api.domain.methods.deposit.azura.AzuraDepositRequestData; +import com.trustly.api.domain.methods.deposit.azura.AzuraDepositRequestDataAttributes; +import com.trustly.api.domain.methods.deposit.azura.AzuraDepositResponseData; import com.trustly.api.domain.methods.merchantsettlement.MerchantSettlementRequestData; import com.trustly.api.domain.methods.merchantsettlement.MerchantSettlementResponseData; import com.trustly.api.domain.methods.refund.RefundRequestData; @@ -397,4 +400,28 @@ void testMerchantSettlement() { Assertions.fail("Unexpected error: " + ex, ex); } } + + @Test + void testAzuraDeposit() { + try (TrustlyApiClient client = new TrustlyApiClient(settings)) { + String uniqueMessageId = UUID.randomUUID().toString(); + + AzuraDepositRequestData request = AzuraDepositRequestData.builder() + .messageId(uniqueMessageId) + .attributes(AzuraDepositRequestDataAttributes.builder() + .email("test@trustly.com") + .mobilePhone("0701234567") + .endUserID("john.doe@trustly.com") + .country("SE") + .currency("SEK") + .build()) + .build(); + + AzuraDepositResponseData azuraDepositResponse = client.azuraDeposit(request); + + Assertions.assertNotNull(azuraDepositResponse); + } catch (TrustlyRequestException ex) { + Assertions.fail("Unexpected error: " + ex, ex); + } + } } From 3c1a7c257cd823ea11be542da47f75322313addc Mon Sep 17 00:00:00 2001 From: Johan Lindkvist Date: Wed, 9 Jul 2025 11:12:35 +0200 Subject: [PATCH 3/4] Add azura remove account --- .../trustly/api/client/TrustlyApiClient.java | 9 +++++ .../deposit/DepositRequestDataAzura.java | 3 ++ .../azura/AzuraRemoveAccountRequestData.java | 36 +++++++++++++++++++ ...uraRemoveAccountRequestDataAttributes.java | 33 +++++++++++++++++ .../azura/AzuraRemoveAccountResponseData.java | 31 ++++++++++++++++ 5 files changed, 112 insertions(+) create mode 100644 src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraRemoveAccountRequestData.java create mode 100644 src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraRemoveAccountRequestDataAttributes.java create mode 100644 src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraRemoveAccountResponseData.java diff --git a/src/main/java/com/trustly/api/client/TrustlyApiClient.java b/src/main/java/com/trustly/api/client/TrustlyApiClient.java index d98db06..a6897fb 100644 --- a/src/main/java/com/trustly/api/client/TrustlyApiClient.java +++ b/src/main/java/com/trustly/api/client/TrustlyApiClient.java @@ -41,6 +41,8 @@ import com.trustly.api.domain.methods.deposit.DepositResponseData; import com.trustly.api.domain.methods.deposit.azura.AzuraDepositRequestData; import com.trustly.api.domain.methods.deposit.azura.AzuraDepositResponseData; +import com.trustly.api.domain.methods.deposit.azura.AzuraRemoveAccountRequestData; +import com.trustly.api.domain.methods.deposit.azura.AzuraRemoveAccountResponseData; import com.trustly.api.domain.methods.getwithdrawals.GetWithdrawalsRequestData; import com.trustly.api.domain.methods.getwithdrawals.GetWithdrawalsResponseData; import com.trustly.api.domain.methods.merchantsettlement.MerchantSettlementRequestData; @@ -450,6 +452,13 @@ public AzuraDepositResponseData azuraDeposit(AzuraDepositRequestData request) th return this.sendRequest(request, AzuraDepositResponseData.class, "AzuraDeposit", null); } + /** + * TODO insert javadoc + */ + public AzuraRemoveAccountResponseData azuraRemoveAccount(AzuraRemoveAccountRequestData request) throws TrustlyRequestException { + return this.sendRequest(request, AzuraRemoveAccountResponseData.class, "RemoveAzuraAccount", null); + } + // Notifications /** diff --git a/src/main/java/com/trustly/api/domain/methods/deposit/DepositRequestDataAzura.java b/src/main/java/com/trustly/api/domain/methods/deposit/DepositRequestDataAzura.java index 1379f79..fe20e14 100644 --- a/src/main/java/com/trustly/api/domain/methods/deposit/DepositRequestDataAzura.java +++ b/src/main/java/com/trustly/api/domain/methods/deposit/DepositRequestDataAzura.java @@ -1,5 +1,7 @@ package com.trustly.api.domain.methods.deposit; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonProperty; import jakarta.validation.constraints.NotBlank; import lombok.Builder; @@ -11,6 +13,7 @@ @Builder(toBuilder = true) @Jacksonized @RequiredArgsConstructor +@JsonInclude(Include.NON_NULL) public class DepositRequestDataAzura { /** diff --git a/src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraRemoveAccountRequestData.java b/src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraRemoveAccountRequestData.java new file mode 100644 index 0000000..2a10ed3 --- /dev/null +++ b/src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraRemoveAccountRequestData.java @@ -0,0 +1,36 @@ +package com.trustly.api.domain.methods.deposit.azura; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.trustly.api.domain.base.AbstractToTrustlyRequestData; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.RequiredArgsConstructor; +import lombok.experimental.SuperBuilder; +import lombok.extern.jackson.Jacksonized; + +@Data +@SuperBuilder(toBuilder = true) +@EqualsAndHashCode(callSuper = true) +@RequiredArgsConstructor +@AllArgsConstructor +@Jacksonized +@JsonInclude(Include.NON_NULL) +public class AzuraRemoveAccountRequestData extends AbstractToTrustlyRequestData { + + @JsonProperty(value = "MessageID", required = true) + @NotBlank + private String messageId; + + @JsonProperty(value = "Attributes", required = true) + @JsonInclude(Include.NON_NULL) + @Valid + @Override + public AzuraRemoveAccountRequestDataAttributes getAttributes() { + return super.getAttributes(); + } +} diff --git a/src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraRemoveAccountRequestDataAttributes.java b/src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraRemoveAccountRequestDataAttributes.java new file mode 100644 index 0000000..b9460c7 --- /dev/null +++ b/src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraRemoveAccountRequestDataAttributes.java @@ -0,0 +1,33 @@ +package com.trustly.api.domain.methods.deposit.azura; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.trustly.api.domain.base.AbstractRequestParamsDataAttributes; +import jakarta.validation.constraints.Email; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.RequiredArgsConstructor; +import lombok.experimental.SuperBuilder; + +@Data +@SuperBuilder(toBuilder = true) +@EqualsAndHashCode(callSuper = true) +@RequiredArgsConstructor +@AllArgsConstructor +@JsonInclude(Include.NON_NULL) +public class AzuraRemoveAccountRequestDataAttributes extends AbstractRequestParamsDataAttributes { + + /** + * Same value that was returned in the response to the initial call to AzuraDeposit. + */ + @JsonProperty(value = "AzuraSessionID") + String azuraSessionId; + + /** + * ID of the account to be removed. This should be the same value as returned in the response to the initial AzuraDeposit call. + */ + @JsonProperty(value = "accountID") + String accountId; +} diff --git a/src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraRemoveAccountResponseData.java b/src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraRemoveAccountResponseData.java new file mode 100644 index 0000000..80de37f --- /dev/null +++ b/src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraRemoveAccountResponseData.java @@ -0,0 +1,31 @@ +package com.trustly.api.domain.methods.deposit.azura; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.trustly.api.domain.base.AbstractResponseResultData; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Value; +import lombok.experimental.SuperBuilder; +import lombok.extern.jackson.Jacksonized; + +@Value +@SuperBuilder +@EqualsAndHashCode(callSuper = true) +@AllArgsConstructor +@Jacksonized +public class AzuraRemoveAccountResponseData extends AbstractResponseResultData { + + /** + * 1 if the account was removed. 0 if it was not. If not removed there will be an additional error code in the rejected field. + */ + @JsonProperty("result") + String result; + + /** + * If the account was not removed there will be an error code here. Any of: + * ERROR_ACCOUNT_NOT_FOUND - No account exists with this id. + * ERROR_AZURA_SESSION_NOT_FOUND - If the session could not be found. + */ + @JsonProperty("rejected") + String rejected; +} From 19d4da3f060778cedf0f49e1dcd1061732d0c946 Mon Sep 17 00:00:00 2001 From: Johan Lindkvist Date: Wed, 30 Jul 2025 12:56:47 +0200 Subject: [PATCH 4/4] Fix accountId json name --- .../deposit/azura/AzuraRemoveAccountRequestDataAttributes.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraRemoveAccountRequestDataAttributes.java b/src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraRemoveAccountRequestDataAttributes.java index b9460c7..ee53673 100644 --- a/src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraRemoveAccountRequestDataAttributes.java +++ b/src/main/java/com/trustly/api/domain/methods/deposit/azura/AzuraRemoveAccountRequestDataAttributes.java @@ -28,6 +28,6 @@ public class AzuraRemoveAccountRequestDataAttributes extends AbstractRequestPara /** * ID of the account to be removed. This should be the same value as returned in the response to the initial AzuraDeposit call. */ - @JsonProperty(value = "accountID") + @JsonProperty(value = "AccountID") String accountId; }