diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 2c5f5a59f..9b0e4d636 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -* @AlexandrosMor @wboereboom @Morerice +* @AlexandrosMor @wboereboom @Morerice @michaelpaul diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 72fd96035..0ac25aa72 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -13,7 +13,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: # We must fetch at least the immediate parents so that if this is # a pull request then we can checkout the head. @@ -26,7 +26,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v1 + uses: github/codeql-action/init@v2 # Override language selection by uncommenting this and choosing your languages # with: # languages: go, javascript, csharp, python, cpp, java @@ -34,7 +34,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v1 + uses: github/codeql-action/autobuild@v2 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -48,4 +48,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/coveralls.yml b/.github/workflows/coveralls.yml index 50676aaaa..ee5ff5d35 100644 --- a/.github/workflows/coveralls.yml +++ b/.github/workflows/coveralls.yml @@ -1,6 +1,6 @@ name: Coveralls -on: [push] +on: [pull_request] jobs: @@ -8,9 +8,9 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up JDK 11 - uses: actions/setup-java@v2 + uses: actions/setup-java@v3 with: java-version: '11' distribution: 'adopt' diff --git a/.github/workflows/javaci.yml b/.github/workflows/javaci.yml new file mode 100644 index 000000000..ffa01e3ea --- /dev/null +++ b/.github/workflows/javaci.yml @@ -0,0 +1,19 @@ +name: Java CI + +on: [push] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Set up JDK 11 + uses: actions/setup-java@v3 + + with: + java-version: '11' + distribution: 'adopt' + + - name: Run the tests with Maven + run: mvn test diff --git a/README.md b/README.md index c29740e94..a2598c66a 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ You can use Maven and add this dependency to your project's POM: com.adyen adyen-java-api-library - 17.3.0 + 17.4.0 ``` diff --git a/pom.xml b/pom.xml index 39322493e..20e4c0060 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.adyen adyen-java-api-library jar - 17.3.0 + 17.4.0 Adyen Java API Library Adyen API Client Library for Java https://github.com/adyen/adyen-java-api-library @@ -25,7 +25,6 @@ UTF-8 UTF-8 - 2.13.1 scm:git:git@github.com:Adyen/adyen-java-api-library.git @@ -37,13 +36,16 @@ org.apache.maven.plugins maven-compiler-plugin + 3.1 1.8 1.8 + org.apache.maven.plugins maven-jar-plugin + 2.4 ${project.build.outputDirectory}/META-INF/MANIFEST.MF @@ -65,7 +67,7 @@ org.jacoco jacoco-maven-plugin - 0.8.7 + 0.8.8 default-prepare-agent @@ -91,7 +93,10 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.3.1 + + 8 + + 3.4.0 attach-javadocs @@ -118,7 +123,7 @@ org.sonatype.plugins nexus-staging-maven-plugin - 1.6.8 + 1.6.13 true ossrh @@ -149,7 +154,7 @@ org.apache.felix maven-bundle-plugin - 5.1.3 + 5.1.4 bundle-manifest @@ -176,22 +181,22 @@ com.google.code.gson gson - 2.8.9 + 2.9.0 com.fasterxml.jackson.core jackson-annotations - ${jackson.version} + 2.13.2 com.fasterxml.jackson.core jackson-databind - ${jackson.version} + 2.13.2.2 org.apache.httpcomponents.client5 httpclient5 - 5.1.2 + 5.1.3 junit @@ -202,13 +207,13 @@ org.mockito mockito-core - 4.2.0 + 4.5.1 test com.fasterxml.jackson.datatype jackson-datatype-jdk8 - ${jackson.version} + 2.13.2 test @@ -219,12 +224,12 @@ io.swagger.core.v3 swagger-models - 2.1.12 + 2.2.0 io.swagger.core.v3 swagger-annotations - 2.1.12 + 2.2.0 diff --git a/src/main/java/com/adyen/Client.java b/src/main/java/com/adyen/Client.java index 8637f56d6..102a5ce15 100644 --- a/src/main/java/com/adyen/Client.java +++ b/src/main/java/com/adyen/Client.java @@ -47,7 +47,7 @@ public class Client { public static final String MARKETPAY_NOTIFICATION_API_VERSION = "v6"; public static final String MARKETPAY_HOP_API_VERSION = "v6"; public static final String LIB_NAME = "adyen-java-api-library"; - public static final String LIB_VERSION = "17.3.0"; + public static final String LIB_VERSION = "17.4.0"; public static final String CHECKOUT_ENDPOINT_TEST = "https://checkout-test.adyen.com/checkout"; public static final String CHECKOUT_ENDPOINT_LIVE_SUFFIX = "-checkout-live.adyenpayments.com/checkout"; public static final String CHECKOUT_ENDPOINT_CERT_LIVE = "https://checkoutcert-live-%s.adyen.com/checkout"; diff --git a/src/main/java/com/adyen/deserializer/PaymentMethodDetailsDeserializerJackson.java b/src/main/java/com/adyen/deserializer/PaymentMethodDetailsDeserializerJackson.java index 563b1e5e6..573f3d38f 100644 --- a/src/main/java/com/adyen/deserializer/PaymentMethodDetailsDeserializerJackson.java +++ b/src/main/java/com/adyen/deserializer/PaymentMethodDetailsDeserializerJackson.java @@ -20,6 +20,7 @@ */ package com.adyen.deserializer; +import java.io.IOException; import com.adyen.model.checkout.DefaultPaymentMethodDetails; import com.adyen.model.checkout.PaymentMethodDetails; import com.adyen.model.checkout.details.AchDetails; @@ -47,10 +48,13 @@ import com.adyen.model.checkout.details.MolPayDetails; import com.adyen.model.checkout.details.PayPalDetails; import com.adyen.model.checkout.details.PayUUpiDetails; +import com.adyen.model.checkout.details.PayWithGoogleDetails; import com.adyen.model.checkout.details.QiwiWalletDetails; import com.adyen.model.checkout.details.SamsungPayDetails; import com.adyen.model.checkout.details.SepaDirectDebitDetails; +import com.adyen.model.checkout.details.UpiCollectDetails; import com.adyen.model.checkout.details.UpiDetails; +import com.adyen.model.checkout.details.UpiIntentDetails; import com.adyen.model.checkout.details.VippsDetails; import com.adyen.model.checkout.details.VisaCheckoutDetails; import com.adyen.model.checkout.details.WeChatPayDetails; @@ -61,8 +65,6 @@ import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonNode; -import java.io.IOException; - public class PaymentMethodDetailsDeserializerJackson extends JsonDeserializer { @Override @@ -118,6 +120,8 @@ public PaymentMethodDetails deserialize(JsonParser jsonParser, DeserializationCo return codec.treeToValue(node, GiropayDetails.class); case GooglePayDetails.GOOGLEPAY: return codec.treeToValue(node, GooglePayDetails.class); + case PayWithGoogleDetails.PAYWITHGOOGLE: + return codec.treeToValue(node, PayWithGoogleDetails.class); case IdealDetails.IDEAL: return codec.treeToValue(node, IdealDetails.class); case KlarnaDetails.KLARNA: @@ -157,6 +161,10 @@ public PaymentMethodDetails deserialize(JsonParser jsonParser, DeserializationCo return codec.treeToValue(node, SepaDirectDebitDetails.class); case UpiDetails.UPI: return codec.treeToValue(node, UpiDetails.class); + case UpiCollectDetails.UPI_COLLECT: + return codec.treeToValue(node, UpiCollectDetails.class); + case UpiIntentDetails.UPI_INTENT: + return codec.treeToValue(node, UpiIntentDetails.class); case VippsDetails.VIPPS: return codec.treeToValue(node, VippsDetails.class); case VisaCheckoutDetails.VISA_CHECKOUT: diff --git a/src/main/java/com/adyen/deserializer/PaymentMethodDetailsTypeAdapter.java b/src/main/java/com/adyen/deserializer/PaymentMethodDetailsTypeAdapter.java index 6c03c367e..96dbba370 100644 --- a/src/main/java/com/adyen/deserializer/PaymentMethodDetailsTypeAdapter.java +++ b/src/main/java/com/adyen/deserializer/PaymentMethodDetailsTypeAdapter.java @@ -47,10 +47,13 @@ import com.adyen.model.checkout.details.MolPayDetails; import com.adyen.model.checkout.details.PayPalDetails; import com.adyen.model.checkout.details.PayUUpiDetails; +import com.adyen.model.checkout.details.PayWithGoogleDetails; import com.adyen.model.checkout.details.QiwiWalletDetails; import com.adyen.model.checkout.details.SamsungPayDetails; import com.adyen.model.checkout.details.SepaDirectDebitDetails; +import com.adyen.model.checkout.details.UpiCollectDetails; import com.adyen.model.checkout.details.UpiDetails; +import com.adyen.model.checkout.details.UpiIntentDetails; import com.adyen.model.checkout.details.VippsDetails; import com.adyen.model.checkout.details.VisaCheckoutDetails; import com.adyen.model.checkout.details.WeChatPayDetails; @@ -135,6 +138,8 @@ public PaymentMethodDetails read(JsonReader in) { return gson.getAdapter(GiropayDetails.class).fromJsonTree(jsonElement); case GooglePayDetails.GOOGLEPAY: return gson.getAdapter(GooglePayDetails.class).fromJsonTree(jsonElement); + case PayWithGoogleDetails.PAYWITHGOOGLE: + return gson.getAdapter(PayWithGoogleDetails.class).fromJsonTree(jsonElement); case IdealDetails.IDEAL: return gson.getAdapter(IdealDetails.class).fromJsonTree(jsonElement); case KlarnaDetails.KLARNA: @@ -172,6 +177,10 @@ public PaymentMethodDetails read(JsonReader in) { return gson.getAdapter(SamsungPayDetails.class).fromJsonTree(jsonElement); case SepaDirectDebitDetails.SEPA_DIRECT_DEBIT: return gson.getAdapter(SepaDirectDebitDetails.class).fromJsonTree(jsonElement); + case UpiIntentDetails.UPI_INTENT: + return gson.getAdapter(UpiIntentDetails.class).fromJsonTree(jsonElement); + case UpiCollectDetails.UPI_COLLECT: + return gson.getAdapter(UpiCollectDetails.class).fromJsonTree(jsonElement); case UpiDetails.UPI: return gson.getAdapter(UpiDetails.class).fromJsonTree(jsonElement); case VippsDetails.VIPPS: diff --git a/src/main/java/com/adyen/model/ThreeDS2RequestData.java b/src/main/java/com/adyen/model/ThreeDS2RequestData.java index 9ff57cd69..89be2b7f4 100644 --- a/src/main/java/com/adyen/model/ThreeDS2RequestData.java +++ b/src/main/java/com/adyen/model/ThreeDS2RequestData.java @@ -124,6 +124,9 @@ public ChallengeIndicatorEnum read(final JsonReader jsonReader) throws IOExcepti @SerializedName("sdkTransID") private String sdkTransID = null; + @SerializedName("sdkVersion") + private String sdkVersion = null; + @SerializedName("threeDSCompInd") private String threeDSCompInd = null; @@ -361,12 +364,24 @@ public void setSdkTransID(String sdkTransID) { this.sdkTransID = sdkTransID; } + public ThreeDS2RequestData sdkVersion(String sdkVersion) { + this.sdkVersion = sdkVersion; + return this; + } + + public String getSdkVersion() { + return sdkVersion; + } + + public void setSdkVersion(String sdkVersion) { + this.sdkVersion = sdkVersion; + } + public ThreeDS2RequestData threeDSCompInd(String threeDSCompInd) { this.threeDSCompInd = threeDSCompInd; return this; } - public String getThreeDSCompInd() { return threeDSCompInd; } @@ -612,6 +627,7 @@ public boolean equals(java.lang.Object o) { Objects.equals(this.sdkMaxTimeout, threeDS2RequestData.sdkMaxTimeout) && Objects.equals(this.sdkReferenceNumber, threeDS2RequestData.sdkReferenceNumber) && Objects.equals(this.sdkTransID, threeDS2RequestData.sdkTransID) && + Objects.equals(this.sdkVersion, threeDS2RequestData.sdkVersion) && Objects.equals(this.threeDSCompInd, threeDS2RequestData.threeDSCompInd) && Objects.equals(this.threeDSRequestorID, threeDS2RequestData.threeDSRequestorID) && Objects.equals(this.threeDSRequestorName, threeDS2RequestData.threeDSRequestorName) && @@ -622,7 +638,7 @@ public boolean equals(java.lang.Object o) { @Override public int hashCode() { - return Objects.hash(acquirerBIN, acquirerMerchantID, authenticationOnly, challengeIndicator, deviceChannel, deviceRenderOptions, mcc, merchantName, messageVersion, notificationURL, sdkAppID, sdkEncData, sdkEphemPubKey, sdkMaxTimeout, sdkReferenceNumber, sdkTransID, threeDSCompInd, threeDSRequestorID, threeDSRequestorName, threeDSRequestorURL, transactionType, whiteListStatus); + return Objects.hash(acquirerBIN, acquirerMerchantID, authenticationOnly, challengeIndicator, deviceChannel, deviceRenderOptions, mcc, merchantName, messageVersion, notificationURL, sdkAppID, sdkEncData, sdkEphemPubKey, sdkMaxTimeout, sdkReferenceNumber, sdkTransID, sdkVersion, threeDSCompInd, threeDSRequestorID, threeDSRequestorName, threeDSRequestorURL, transactionType, whiteListStatus); } @@ -647,6 +663,7 @@ public String toString() { sb.append(" sdkMaxTimeout: ").append(toIndentedString(sdkMaxTimeout)).append("\n"); sb.append(" sdkReferenceNumber: ").append(toIndentedString(sdkReferenceNumber)).append("\n"); sb.append(" sdkTransID: ").append(toIndentedString(sdkTransID)).append("\n"); + sb.append(" sdkVersion: ").append(toIndentedString(sdkVersion)).append("\n"); sb.append(" threeDSCompInd: ").append(toIndentedString(threeDSCompInd)).append("\n"); sb.append(" threeDSRequestorID: ").append(toIndentedString(threeDSRequestorID)).append("\n"); sb.append(" threeDSRequestorName: ").append(toIndentedString(threeDSRequestorName)).append("\n"); diff --git a/src/main/java/com/adyen/model/checkout/details/GooglePayDetails.java b/src/main/java/com/adyen/model/checkout/details/GooglePayDetails.java index 6c75f4c28..9f436f3de 100755 --- a/src/main/java/com/adyen/model/checkout/details/GooglePayDetails.java +++ b/src/main/java/com/adyen/model/checkout/details/GooglePayDetails.java @@ -44,7 +44,7 @@ public class GooglePayDetails implements PaymentMethodDetails { /** * Possible types */ - public static final String GOOGLEPAY = "paywithgoogle"; + public static final String GOOGLEPAY = "googlepay"; /** * Gets or Sets fundingSource diff --git a/src/main/java/com/adyen/model/checkout/details/PayWithGoogleDetails.java b/src/main/java/com/adyen/model/checkout/details/PayWithGoogleDetails.java new file mode 100755 index 000000000..c442026df --- /dev/null +++ b/src/main/java/com/adyen/model/checkout/details/PayWithGoogleDetails.java @@ -0,0 +1,233 @@ +/* + * ###### + * ###### + * ############ ####( ###### #####. ###### ############ ############ + * ############# #####( ###### #####. ###### ############# ############# + * ###### #####( ###### #####. ###### ##### ###### ##### ###### + * ###### ###### #####( ###### #####. ###### ##### ##### ##### ###### + * ###### ###### #####( ###### #####. ###### ##### ##### ###### + * ############# ############# ############# ############# ##### ###### + * ############ ############ ############# ############ ##### ###### + * ###### + * ############# + * ############ + * + * Adyen Java API Library + * + * Copyright (c) 2022 Adyen N.V. + * This file is open source and available under the MIT license. + * See the LICENSE file for more info. + */ + +package com.adyen.model.checkout.details; + +import java.util.Arrays; +import java.util.Objects; + +import com.adyen.model.checkout.PaymentMethodDetails; +import com.fasterxml.jackson.annotation.JsonValue; +import com.google.gson.TypeAdapter; +import com.google.gson.annotations.JsonAdapter; +import com.google.gson.annotations.SerializedName; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; + +/** + * PayWithGoogleDetails + */ +public class PayWithGoogleDetails implements PaymentMethodDetails { + /** + * Possible types + */ + public static final String PAYWITHGOOGLE = "paywithgoogle"; + + /** + * The funding source that should be used when multiple sources are available. For Brazilian combo cards, by default the funding source is credit. To use debit, set this value to **debit**. + */ + @JsonAdapter(FundingSourceEnum.Adapter.class) + public enum FundingSourceEnum { + DEBIT("debit"); + + @JsonValue + private String value; + + FundingSourceEnum(String value) { + this.value = value; + } + public String getValue() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + + public static FundingSourceEnum fromValue(String text) { + return Arrays.stream(values()). + filter(s -> s.value.equals(text)). + findFirst().orElse(null); + } + + public static class Adapter extends TypeAdapter { + @Override + public void write(final JsonWriter jsonWriter, final FundingSourceEnum enumeration) throws IOException { + jsonWriter.value(String.valueOf(enumeration.getValue())); + } + + @Override + public FundingSourceEnum read(final JsonReader jsonReader) throws IOException { + String value = jsonReader.nextString(); + return FundingSourceEnum.fromValue(String.valueOf(value)); + } + } + } + @SerializedName("fundingSource") + private FundingSourceEnum fundingSource = null; + + @SerializedName("googlePayToken") + private String googlePayToken = null; + + @SerializedName("recurringDetailReference") + private String recurringDetailReference = null; + + @SerializedName("storedPaymentMethodId") + private String storedPaymentMethodId = null; + + @SerializedName("type") + private String type = PAYWITHGOOGLE; + + public PayWithGoogleDetails fundingSource(FundingSourceEnum fundingSource) { + this.fundingSource = fundingSource; + return this; + } + + /** + * The funding source that should be used when multiple sources are available. For Brazilian combo cards, by default the funding source is credit. To use debit, set this value to **debit**. + * @return fundingSource + **/ + public FundingSourceEnum getFundingSource() { + return fundingSource; + } + + public void setFundingSource(FundingSourceEnum fundingSource) { + this.fundingSource = fundingSource; + } + + public PayWithGoogleDetails googlePayToken(String googlePayToken) { + this.googlePayToken = googlePayToken; + return this; + } + + /** + * The `token` that you obtained from the [Google Pay API](https://developers.google.com/pay/api/web/reference/response-objects#PaymentData) `PaymentData` response. + * @return googlePayToken + **/ + public String getGooglePayToken() { + return googlePayToken; + } + + public void setGooglePayToken(String googlePayToken) { + this.googlePayToken = googlePayToken; + } + + public PayWithGoogleDetails recurringDetailReference(String recurringDetailReference) { + this.recurringDetailReference = recurringDetailReference; + return this; + } + + /** + * This is the `recurringDetailReference` returned in the response when you created the token. + * @return recurringDetailReference + **/ + public String getRecurringDetailReference() { + return recurringDetailReference; + } + + public void setRecurringDetailReference(String recurringDetailReference) { + this.recurringDetailReference = recurringDetailReference; + } + + public PayWithGoogleDetails storedPaymentMethodId(String storedPaymentMethodId) { + this.storedPaymentMethodId = storedPaymentMethodId; + return this; + } + + /** + * This is the `recurringDetailReference` returned in the response when you created the token. + * @return storedPaymentMethodId + **/ + public String getStoredPaymentMethodId() { + return storedPaymentMethodId; + } + + public void setStoredPaymentMethodId(String storedPaymentMethodId) { + this.storedPaymentMethodId = storedPaymentMethodId; + } + + public PayWithGoogleDetails type(String type) { + this.type = type; + return this; + } + + /** + * **paywithgoogle** + * @return type + **/ + @Override + public String getType() { + return type; + } + + @Override + public void setType(String type) { + this.type = type; + } + + @Override + public boolean equals(java.lang.Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + PayWithGoogleDetails payWithGoogleDetails = (PayWithGoogleDetails) o; + return Objects.equals(this.fundingSource, payWithGoogleDetails.fundingSource) && + Objects.equals(this.googlePayToken, payWithGoogleDetails.googlePayToken) && + Objects.equals(this.recurringDetailReference, payWithGoogleDetails.recurringDetailReference) && + Objects.equals(this.storedPaymentMethodId, payWithGoogleDetails.storedPaymentMethodId) && + Objects.equals(this.type, payWithGoogleDetails.type); + } + + @Override + public int hashCode() { + return Objects.hash(fundingSource, googlePayToken, recurringDetailReference, storedPaymentMethodId, type); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class PayWithGoogleDetails {\n"); + + sb.append(" fundingSource: ").append(toIndentedString(fundingSource)).append("\n"); + sb.append(" googlePayToken: ").append(toIndentedString(googlePayToken)).append("\n"); + sb.append(" recurringDetailReference: ").append(toIndentedString(recurringDetailReference)).append("\n"); + sb.append(" storedPaymentMethodId: ").append(toIndentedString(storedPaymentMethodId)).append("\n"); + sb.append(" type: ").append(toIndentedString(type)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(java.lang.Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} diff --git a/src/main/java/com/adyen/model/checkout/details/UpiCollectDetails.java b/src/main/java/com/adyen/model/checkout/details/UpiCollectDetails.java new file mode 100644 index 000000000..630074d99 --- /dev/null +++ b/src/main/java/com/adyen/model/checkout/details/UpiCollectDetails.java @@ -0,0 +1,199 @@ +/* + * ###### + * ###### + * ############ ####( ###### #####. ###### ############ ############ + * ############# #####( ###### #####. ###### ############# ############# + * ###### #####( ###### #####. ###### ##### ###### ##### ###### + * ###### ###### #####( ###### #####. ###### ##### ##### ##### ###### + * ###### ###### #####( ###### #####. ###### ##### ##### ###### + * ############# ############# ############# ############# ##### ###### + * ############ ############ ############# ############ ##### ###### + * ###### + * ############# + * ############ + * + * Adyen Java API Library + * + * Copyright (c) 2022 Adyen N.V. + * This file is open source and available under the MIT license. + * See the LICENSE file for more info. + */ +package com.adyen.model.checkout.details; + +import java.util.Objects; +import com.adyen.model.checkout.PaymentMethodDetails; +import com.google.gson.annotations.SerializedName; + +/** + * UpiCollectDetails + */ +public class UpiCollectDetails implements PaymentMethodDetails { + + public static final String UPI_COLLECT = "upi_collect"; + + @SerializedName("billingSequenceNumber") + private String billingSequenceNumber = null; + + @SerializedName("recurringDetailReference") + private String recurringDetailReference = null; + + @SerializedName("shopperNotificationReference") + private String shopperNotificationReference = null; + + @SerializedName("storedPaymentMethodId") + private String storedPaymentMethodId = null; + + @SerializedName("virtualPaymentAddress") + private String virtualPaymentAddress = null; + + @SerializedName("type") + private String type = UPI_COLLECT; + + /** + * **upi_collect** + * + * @return type + **/ + @Override + public String getType() { + return type; + } + + @Override + public void setType(String type) { + this.type = type; + } + + public UpiCollectDetails type(String type) { + this.type = type; + return this; + } + + /** + * The sequence number for the debit. For example, send **2** if this is the second debit for the subscription. The sequence number is included in the notification sent to the shopper. + * + * @return billingSequenceNumber + **/ + public String getBillingSequenceNumber() { + return billingSequenceNumber; + } + + public void setBillingSequenceNumber(String billingSequenceNumber) { + this.billingSequenceNumber = billingSequenceNumber; + } + + public UpiCollectDetails billingSequenceNumber(String billingSequenceNumber) { + this.billingSequenceNumber = billingSequenceNumber; + return this; + } + + /** + * This is the `recurringDetailReference` returned in the response when you created the token. + * + * @return recurringDetailReference + **/ + public String getRecurringDetailReference() { + return recurringDetailReference; + } + + public void setRecurringDetailReference(String recurringDetailReference) { + this.recurringDetailReference = recurringDetailReference; + } + + public UpiCollectDetails recurringDetailReference(String recurringDetailReference) { + this.recurringDetailReference = recurringDetailReference; + return this; + } + + /** + * The `shopperNotificationReference` returned in the response when you requested to notify the shopper. Used for recurring payment only. + * + * @return shopperNotificationReference + **/ + public String getShopperNotificationReference() { + return shopperNotificationReference; + } + + public void setShopperNotificationReference(String shopperNotificationReference) { + this.shopperNotificationReference = shopperNotificationReference; + } + + + public UpiCollectDetails shopperNotificationReference(String shopperNotificationReference) { + this.shopperNotificationReference = shopperNotificationReference; + return this; + } + + /** + * This is the `recurringDetailReference` returned in the response when you created the token. + * + * @return storedPaymentMethodId + **/ + public String getStoredPaymentMethodId() { + return storedPaymentMethodId; + } + + public void setStoredPaymentMethodId(String storedPaymentMethodId) { + this.storedPaymentMethodId = storedPaymentMethodId; + } + + public UpiCollectDetails storedPaymentMethodId(String storedPaymentMethodId) { + this.storedPaymentMethodId = storedPaymentMethodId; + return this; + } + + /** + * The virtual payment address for UPI. + * + * @return virtualPaymentAddress + **/ + public String getVirtualPaymentAddress() { + return virtualPaymentAddress; + } + + public void setVirtualPaymentAddress(String virtualPaymentAddress) { + this.virtualPaymentAddress = virtualPaymentAddress; + } + + public UpiCollectDetails virtualPaymentAddress(String virtualPaymentAddress) { + this.virtualPaymentAddress = virtualPaymentAddress; + return this; + } + + @Override + public boolean equals(java.lang.Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + UpiCollectDetails upiCollectDetails = (UpiCollectDetails) o; + return Objects.equals(this.billingSequenceNumber, upiCollectDetails.billingSequenceNumber) + && Objects.equals(this.recurringDetailReference, upiCollectDetails.recurringDetailReference) + && Objects.equals(this.shopperNotificationReference, upiCollectDetails.shopperNotificationReference) + && Objects.equals(this.storedPaymentMethodId, upiCollectDetails.storedPaymentMethodId) + && Objects.equals(this.type, upiCollectDetails.type) + && Objects.equals(this.virtualPaymentAddress, upiCollectDetails.virtualPaymentAddress); + } + + @Override + public int hashCode() { + return Objects.hash(billingSequenceNumber, recurringDetailReference, shopperNotificationReference, storedPaymentMethodId, type, virtualPaymentAddress); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class UpiCollectDetails {\n"); + + sb.append(" billingSequenceNumber: ").append(billingSequenceNumber).append("\n"); + sb.append(" recurringDetailReference: ").append(recurringDetailReference).append("\n"); + sb.append(" shopperNotificationReference: ").append(shopperNotificationReference).append("\n"); + sb.append(" storedPaymentMethodId: ").append(storedPaymentMethodId).append("\n"); + sb.append(" type: ").append(type).append("\n"); + sb.append(" virtualPaymentAddress: ").append(virtualPaymentAddress).append("\n"); + sb.append("}"); + return sb.toString(); + } +} diff --git a/src/main/java/com/adyen/model/checkout/details/UpiIntentDetails.java b/src/main/java/com/adyen/model/checkout/details/UpiIntentDetails.java new file mode 100644 index 000000000..d14860c1d --- /dev/null +++ b/src/main/java/com/adyen/model/checkout/details/UpiIntentDetails.java @@ -0,0 +1,80 @@ +/* + * ###### + * ###### + * ############ ####( ###### #####. ###### ############ ############ + * ############# #####( ###### #####. ###### ############# ############# + * ###### #####( ###### #####. ###### ##### ###### ##### ###### + * ###### ###### #####( ###### #####. ###### ##### ##### ##### ###### + * ###### ###### #####( ###### #####. ###### ##### ##### ###### + * ############# ############# ############# ############# ##### ###### + * ############ ############ ############# ############ ##### ###### + * ###### + * ############# + * ############ + * + * Adyen Java API Library + * + * Copyright (c) 2022 Adyen N.V. + * This file is open source and available under the MIT license. + * See the LICENSE file for more info. + */ +package com.adyen.model.checkout.details; + +import java.util.Objects; +import com.adyen.model.checkout.PaymentMethodDetails; +import com.google.gson.annotations.SerializedName; + +/** + * UpiIntentDetails + */ +public class UpiIntentDetails implements PaymentMethodDetails { + + public static final String UPI_INTENT = "upi_intent"; + + @SerializedName("type") + private String type = UPI_INTENT; + + /** + * **upi** + * + * @return type + **/ + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public UpiIntentDetails type(String type) { + this.type = type; + return this; + } + + @Override + public int hashCode() { + return Objects.hash(type); + } + + @Override + public boolean equals(java.lang.Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + UpiIntentDetails upiIntentDetails = (UpiIntentDetails) o; + return Objects.equals(this.type, upiIntentDetails.type); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class UpiIntentDetails {\n"); + sb.append(" type: ").append(type).append("\n"); + sb.append("}"); + return sb.toString(); + } +} diff --git a/src/main/java/com/adyen/model/marketpay/notification/PaymentFailureNotificationContent.java b/src/main/java/com/adyen/model/marketpay/notification/PaymentFailureNotificationContent.java index 3b667eb65..29cdd27d2 100644 --- a/src/main/java/com/adyen/model/marketpay/notification/PaymentFailureNotificationContent.java +++ b/src/main/java/com/adyen/model/marketpay/notification/PaymentFailureNotificationContent.java @@ -38,6 +38,15 @@ public class PaymentFailureNotificationContent { @SerializedName("errorMessage") public Message errorMessage; + @SerializedName("modificationMerchantReference") + public String modificationMerchantReference; + @SerializedName("modificationPspReference") + public String modificationPspReference; + @SerializedName("paymentMerchantReference") + public String paymentMerchantReference; + @SerializedName("paymentPspReference") + public String paymentPspReference; + public List getErrorFieldList() { List errorFieldTypeList = new ArrayList<>(); @@ -66,8 +75,40 @@ public void setErrorMessage(Message errorMessage) { this.errorMessage = errorMessage; } + public String getModificationMerchantReference() { + return modificationMerchantReference; + } + + public void setModificationMerchantReference(String modificationMerchantReference) { + this.modificationMerchantReference = modificationMerchantReference; + } + + public String getModificationPspReference() { + return modificationPspReference; + } + + public void setModificationPspReference(String modificationPspReference) { + this.modificationPspReference = modificationPspReference; + } + + public String getPaymentMerchantReference() { + return paymentMerchantReference; + } + + public void setPaymentMerchantReference(String paymentMerchantReference) { + this.paymentMerchantReference = paymentMerchantReference; + } + + public String getPaymentPspReference() { + return paymentPspReference; + } + + public void setPaymentPspReference(String paymentPspReference) { + this.paymentPspReference = paymentPspReference; + } + @Override public String toString() { - return "PaymentFailureContent{" + "errorFieldTypeContainers=" + errorFieldTypeContainers + ", errorMessage=" + errorMessage + '}'; + return "PaymentFailureContent{" + "errorFieldTypeContainers=" + errorFieldTypeContainers + ", errorMessage=" + errorMessage + ", modificationMerchantReference=" + modificationMerchantReference + ", modificationPspReference=" + modificationPspReference + ", paymentMerchantReference=" + paymentMerchantReference + ", paymentPspReference=" + paymentPspReference + '}'; } } diff --git a/src/main/java/com/adyen/model/nexo/Input.java b/src/main/java/com/adyen/model/nexo/Input.java index 9d3686f6d..622ca63e8 100644 --- a/src/main/java/com/adyen/model/nexo/Input.java +++ b/src/main/java/com/adyen/model/nexo/Input.java @@ -180,7 +180,7 @@ public void setPassword(ContentInformation value) { /** * Gets the value of the menuEntryNumber property. * - * @return possible object is {@link Integer[] } + * @return possible object is Array of {@link Integer } */ public Integer[] getMenuEntryNumber() { return menuEntryNumber; @@ -189,7 +189,7 @@ public Integer[] getMenuEntryNumber() { /** * Sets the value of the menuEntryNumber property. * - * @param value allowed object is {@link Integer[] } + * @param value allowed object is Array of {@link Integer } */ public void setMenuEntryNumber(Integer[] value) { this.menuEntryNumber = value; diff --git a/src/main/java/com/adyen/util/HMACValidator.java b/src/main/java/com/adyen/util/HMACValidator.java index 34d4169a4..54ace3b39 100644 --- a/src/main/java/com/adyen/util/HMACValidator.java +++ b/src/main/java/com/adyen/util/HMACValidator.java @@ -79,7 +79,9 @@ public boolean validateHMAC(NotificationRequestItem notificationRequestItem, Str throw new IllegalArgumentException("Missing NotificationRequestItem."); } - if (notificationRequestItem.getAdditionalData() == null || notificationRequestItem.getAdditionalData().get(HMAC_SIGNATURE).isEmpty()) { + if (notificationRequestItem.getAdditionalData() == null + || notificationRequestItem.getAdditionalData().get(HMAC_SIGNATURE) == null + || notificationRequestItem.getAdditionalData().get(HMAC_SIGNATURE).isEmpty()) { throw new IllegalArgumentException("Missing " + HMAC_SIGNATURE); } final byte[] merchantSign = (notificationRequestItem.getAdditionalData().get(HMAC_SIGNATURE)).getBytes(StandardCharsets.UTF_8); diff --git a/src/test/java/com/adyen/CheckoutTest.java b/src/test/java/com/adyen/CheckoutTest.java index 43a2ed412..bd290e1a7 100644 --- a/src/test/java/com/adyen/CheckoutTest.java +++ b/src/test/java/com/adyen/CheckoutTest.java @@ -88,9 +88,12 @@ import com.adyen.model.checkout.details.MolPayDetails; import com.adyen.model.checkout.details.PayPalDetails; import com.adyen.model.checkout.details.PayUUpiDetails; +import com.adyen.model.checkout.details.PayWithGoogleDetails; import com.adyen.model.checkout.details.QiwiWalletDetails; import com.adyen.model.checkout.details.SamsungPayDetails; import com.adyen.model.checkout.details.SepaDirectDebitDetails; +import com.adyen.model.checkout.details.UpiCollectDetails; +import com.adyen.model.checkout.details.UpiIntentDetails; import com.adyen.model.checkout.details.VippsDetails; import com.adyen.model.checkout.details.VisaCheckoutDetails; import com.adyen.model.checkout.details.WeChatPayDetails; @@ -102,6 +105,7 @@ import com.fasterxml.jackson.databind.module.SimpleModule; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import com.google.gson.JsonParser; import com.google.gson.annotations.SerializedName; import org.junit.Assert; import org.junit.Test; @@ -397,7 +401,7 @@ public void TestPaymentMethodDetails() { PaymentsRequest paymentsRequest = createPaymentsCheckoutRequest(); String jsonRequest = PRETTY_PRINT_GSON.toJson(paymentsRequest); - assertEquals("{\n" + assertJsonStringEquals("{\n" + " \"amount\": {\n" + " \"value\": 1000,\n" + " \"currency\": \"USD\"\n" @@ -427,7 +431,7 @@ public void TestPaymentMethodDetails() { paymentsRequest.setPaymentMethod(testPaymentMethodDetails); jsonRequest = PRETTY_PRINT_GSON.toJson(paymentsRequest); - assertEquals("{\n" + assertJsonStringEquals("{\n" + " \"amount\": {\n" + " \"value\": 1000,\n" + " \"currency\": \"USD\"\n" @@ -453,7 +457,7 @@ public void TestEncryptedPaymentMethodDetails() { PaymentsRequest paymentsRequest = createEncryptedPaymentsCheckoutRequest(); String jsonRequest = PRETTY_PRINT_GSON.toJson(paymentsRequest); - assertEquals("{\n" + assertJsonStringEquals("{\n" + " \"amount\": {\n" + " \"value\": 1000,\n" + " \"currency\": \"USD\"\n" @@ -483,7 +487,7 @@ public void TestEncryptedPaymentMethodDetails() { paymentsRequest.setPaymentMethod(testPaymentMethodDetails); jsonRequest = PRETTY_PRINT_GSON.toJson(paymentsRequest); - assertEquals("{\n" + assertJsonStringEquals("{\n" + " \"amount\": {\n" + " \"value\": 1000,\n" + " \"currency\": \"USD\"\n" @@ -533,7 +537,7 @@ public void TestSepaPaymentMethodDetails() { String jsonRequest = PRETTY_PRINT_GSON.toJson(paymentsRequest); - assertEquals("{\n" + assertJsonStringEquals("{\n" + " \"amount\": {\n" + " \"value\": 1000,\n" + " \"currency\": \"USD\"\n" @@ -566,10 +570,10 @@ public void TestSepaDirectDebitDetailsSerialization() throws JsonProcessingExcep paymentsRequest.setPaymentMethod(sepaDirectDebitDetails); String gson = GSON.toJson(paymentsRequest); - assertEquals(expectedJson, gson); + assertJsonStringEquals(expectedJson, gson); String jackson = OBJECT_MAPPER.writeValueAsString(paymentsRequest); - assertEquals(expectedJson, jackson); + assertJsonStringEquals(expectedJson, jackson); } @Test @@ -602,10 +606,10 @@ public void TestAchDetailsSerialization() throws JsonProcessingException { paymentsRequest.setPaymentMethod(achDetails); String gson = GSON.toJson(paymentsRequest); - assertEquals(expectedJson, gson); + assertJsonStringEquals(expectedJson, gson); String jackson = OBJECT_MAPPER.writeValueAsString(paymentsRequest); - assertEquals(expectedJson, jackson); + assertJsonStringEquals(expectedJson, jackson); } @Test @@ -641,10 +645,10 @@ public void TestEcontextVoucherDetailsSerialization() throws JsonProcessingExcep paymentsRequest.setPaymentMethod(econtextVoucherDetails); String gson = GSON.toJson(paymentsRequest); - assertEquals(expectedJson, gson); + assertJsonStringEquals(expectedJson, gson); String jackson = OBJECT_MAPPER.writeValueAsString(paymentsRequest); - assertEquals(expectedJson, jackson); + assertJsonStringEquals(expectedJson, jackson); } @Test @@ -677,10 +681,10 @@ public void TestIdealDetailsSerialization() throws JsonProcessingException { paymentsRequest.setPaymentMethod(idealDetails); String gson = GSON.toJson(paymentsRequest); - assertEquals(expectedJson, gson); + assertJsonStringEquals(expectedJson, gson); String jackson = OBJECT_MAPPER.writeValueAsString(paymentsRequest); - assertEquals(expectedJson, jackson); + assertJsonStringEquals(expectedJson, jackson); } @Test @@ -700,7 +704,7 @@ public void TestIdealDetailsDeserialization() throws JsonProcessingException { @Test public void TestGooglePayDetailsSerialization() throws JsonProcessingException { - String expectedJson = "{\"amount\":{\"value\":1000,\"currency\":\"USD\"},\"merchantAccount\":\"MagentoMerchantTest\",\"paymentMethod\":{\"fundingSource\":\"credit\",\"googlePayCardNetwork\":\"googlepaycardnetwork\",\"googlePayToken\":\"Payload as retrieved from Google Pay response\",\"type\":\"paywithgoogle\"},\"reference\":\"Your order number\",\"returnUrl\":\"https://your-company.com/...\",\"applicationInfo\":{\"adyenLibrary\":{\"name\":\"adyen-java-api-library\",\"version\":\"" + LIB_VERSION + "\"}}}"; + String expectedJson = "{\"amount\":{\"value\":1000,\"currency\":\"USD\"},\"merchantAccount\":\"MagentoMerchantTest\",\"paymentMethod\":{\"fundingSource\":\"credit\",\"googlePayCardNetwork\":\"googlepaycardnetwork\",\"googlePayToken\":\"Payload as retrieved from Google Pay response\",\"type\":\"googlepay\"},\"reference\":\"Your order number\",\"returnUrl\":\"https://your-company.com/...\",\"applicationInfo\":{\"adyenLibrary\":{\"name\":\"adyen-java-api-library\",\"version\":\"" + LIB_VERSION + "\"}}}"; GooglePayDetails googlePayDetails = new GooglePayDetails(); googlePayDetails.setGooglePayToken("Payload as retrieved from Google Pay response"); @@ -710,15 +714,15 @@ public void TestGooglePayDetailsSerialization() throws JsonProcessingException { paymentsRequest.setPaymentMethod(googlePayDetails); String gson = GSON.toJson(paymentsRequest); - assertEquals(expectedJson, gson); + assertJsonStringEquals(expectedJson, gson); String jackson = OBJECT_MAPPER.writeValueAsString(paymentsRequest); - assertEquals(expectedJson, jackson); + assertJsonStringEquals(expectedJson, jackson); } @Test public void TestGooglePayDetailsDeserialization() throws JsonProcessingException { - String json = "{\"amount\":{\"value\":1000,\"currency\":\"USD\"},\"merchantAccount\":\"MagentoMerchantTest\",\"paymentMethod\":{\"fundingSource\":\"credit\",\"googlePayCardNetwork\":\"googlepaycardnetwork\",\"googlePayToken\":\"Payload as retrieved from Google Pay response\",\"type\":\"paywithgoogle\"},\"reference\":\"Your order number\",\"returnUrl\":\"https://your-company.com/...\",\"applicationInfo\":{\"adyenLibrary\":{\"name\":\"adyen-java-api-library\",\"version\":\"" + LIB_VERSION + "\"}}}"; + String json = "{\"amount\":{\"value\":1000,\"currency\":\"USD\"},\"merchantAccount\":\"MagentoMerchantTest\",\"paymentMethod\":{\"fundingSource\":\"credit\",\"googlePayCardNetwork\":\"googlepaycardnetwork\",\"googlePayToken\":\"Payload as retrieved from Google Pay response\",\"type\":\"googlepay\"},\"reference\":\"Your order number\",\"returnUrl\":\"https://your-company.com/...\",\"applicationInfo\":{\"adyenLibrary\":{\"name\":\"adyen-java-api-library\",\"version\":\"" + LIB_VERSION + "\"}}}"; GooglePayDetails googlePayDetails = new GooglePayDetails(); googlePayDetails.setGooglePayToken("Payload as retrieved from Google Pay response"); googlePayDetails.setFundingSource(GooglePayDetails.FundingSourceEnum.CREDIT); @@ -733,6 +737,44 @@ public void TestGooglePayDetailsDeserialization() throws JsonProcessingException assertEquals(expectedPaymentRequest, jacksonObject); } + @Test + public void TestPayWithGoogleDetailsSerialization() throws JsonProcessingException { + String expectedJson = "{\"amount\":{\"value\":1000,\"currency\":\"USD\"},\"merchantAccount\":\"MagentoMerchantTest\",\"paymentMethod\":{\"fundingSource\":\"debit\",\"googlePayToken\":\"Payload as retrieved from Google Pay response\",\"recurringDetailReference\":\"serialize-reference\",\"storedPaymentMethodId\":\"shop\",\"type\":\"paywithgoogle\"},\"reference\":\"Your order number\",\"returnUrl\":\"https://your-company.com/...\",\"applicationInfo\":{\"adyenLibrary\":{\"name\":\"adyen-java-api-library\",\"version\":\"" + LIB_VERSION + "\"}}}"; + + PayWithGoogleDetails payWithGoogleDetails = new PayWithGoogleDetails(); + payWithGoogleDetails.setGooglePayToken("Payload as retrieved from Google Pay response"); + payWithGoogleDetails.setFundingSource(PayWithGoogleDetails.FundingSourceEnum.DEBIT); + payWithGoogleDetails.setRecurringDetailReference("serialize-reference"); + payWithGoogleDetails.setStoredPaymentMethodId("shop"); + PaymentsRequest paymentsRequest = createPaymentsCheckoutRequest(); + paymentsRequest.setPaymentMethod(payWithGoogleDetails); + + String gson = GSON.toJson(paymentsRequest); + assertJsonStringEquals(expectedJson, gson); + + String jackson = OBJECT_MAPPER.writeValueAsString(paymentsRequest); + assertJsonStringEquals(expectedJson, jackson); + } + + @Test + public void TestPayWithGoogleDetailsDeserialization() throws JsonProcessingException { + String json = "{\"amount\":{\"value\":1000,\"currency\":\"USD\"},\"merchantAccount\":\"MagentoMerchantTest\",\"paymentMethod\":{\"fundingSource\":\"debit\",\"googlePayToken\":\"Payload as retrieved from Google Pay response\",\"recurringDetailReference\":\"some-reference\",\"storedPaymentMethodId\":\"my-shop\",\"type\":\"paywithgoogle\"},\"reference\":\"Your order number\",\"returnUrl\":\"https://your-company.com/...\",\"applicationInfo\":{\"adyenLibrary\":{\"name\":\"adyen-java-api-library\",\"version\":\"" + LIB_VERSION + "\"}}}"; + + PayWithGoogleDetails payWithGoogleDetails = new PayWithGoogleDetails(); + payWithGoogleDetails.setGooglePayToken("Payload as retrieved from Google Pay response"); + payWithGoogleDetails.setFundingSource(PayWithGoogleDetails.FundingSourceEnum.DEBIT); + payWithGoogleDetails.setRecurringDetailReference("some-reference"); + payWithGoogleDetails.setStoredPaymentMethodId("my-shop"); + PaymentsRequest expectedPaymentRequest = createPaymentsCheckoutRequest(); + expectedPaymentRequest.setPaymentMethod(payWithGoogleDetails); + + PaymentsRequest gsonObject = GSON.fromJson(json, PaymentsRequest.class); + assertEquals(expectedPaymentRequest, gsonObject); + + PaymentsRequest jacksonObject = OBJECT_MAPPER.readValue(json, PaymentsRequest.class); + assertEquals(expectedPaymentRequest, jacksonObject); + } + @Test public void TestPayPalDetails() throws JsonProcessingException { String expectedJson = "{\"amount\":{\"value\":1000,\"currency\":\"USD\"},\"merchantAccount\":\"MagentoMerchantTest\",\"paymentMethod\":{\"orderID\":\"orderId\",\"payerID\":\"payerId\",\"type\":\"paypal\",\"storedPaymentMethodId\":\"12345678\",\"subtype\":\"sdk\"},\"reference\":\"Your order number\",\"returnUrl\":\"https://your-company.com/...\",\"applicationInfo\":{\"adyenLibrary\":{\"name\":\"adyen-java-api-library\",\"version\":\"" + LIB_VERSION + "\"}}}"; @@ -746,10 +788,10 @@ public void TestPayPalDetails() throws JsonProcessingException { paymentsRequest.setPaymentMethod(payPalDetails); String gson = GSON.toJson(paymentsRequest); - assertEquals(expectedJson, gson); + assertJsonStringEquals(expectedJson, gson); String jackson = OBJECT_MAPPER.writeValueAsString(paymentsRequest); - assertEquals(expectedJson, jackson); + assertJsonStringEquals(expectedJson, jackson); } @Test @@ -785,10 +827,10 @@ public void TestDokuDetailsSerialization() throws JsonProcessingException { paymentsRequest.setPaymentMethod(dokuDetails); String gson = GSON.toJson(paymentsRequest); - assertEquals(expectedJson, gson); + assertJsonStringEquals(expectedJson, gson); String jackson = OBJECT_MAPPER.writeValueAsString(paymentsRequest); - assertEquals(expectedJson, jackson); + assertJsonStringEquals(expectedJson, jackson); } @Test @@ -824,10 +866,10 @@ public void TestAmazonPayDetailsSerialization() throws JsonProcessingException { paymentsRequest.setPaymentMethod(amazonPayDetails); String gson = GSON.toJson(paymentsRequest); - assertEquals(expectedJson, gson); + assertJsonStringEquals(expectedJson, gson); String jackson = OBJECT_MAPPER.writeValueAsString(paymentsRequest); - assertEquals(expectedJson, jackson); + assertJsonStringEquals(expectedJson, jackson); } @Test @@ -859,10 +901,10 @@ public void TestApplePayDetailsSerialization() throws JsonProcessingException { paymentsRequest.setPaymentMethod(applePayDetails); String gson = GSON.toJson(paymentsRequest); - assertEquals(expectedJson, gson); + assertJsonStringEquals(expectedJson, gson); String jackson = OBJECT_MAPPER.writeValueAsString(paymentsRequest); - assertEquals(expectedJson, jackson); + assertJsonStringEquals(expectedJson, jackson); } @Test @@ -892,10 +934,10 @@ public void TestBillDeskOnlineDetailsSerialization() throws JsonProcessingExcept paymentsRequest.setPaymentMethod(billdeskOnlineDetails); String gsonRequest = GSON.toJson(paymentsRequest); - assertEquals(expectedJson, gsonRequest); + assertJsonStringEquals(expectedJson, gsonRequest); String jacksonRequest = OBJECT_MAPPER.writeValueAsString(paymentsRequest); - assertEquals(expectedJson, jacksonRequest); + assertJsonStringEquals(expectedJson, jacksonRequest); } @Test @@ -923,10 +965,10 @@ public void TestBacsDirectDebitDetailsSerialization() throws JsonProcessingExcep paymentsRequest.setPaymentMethod(bacsDirectDebitDetails); String gson = GSON.toJson(paymentsRequest); - assertEquals(expectedJson, gson); + assertJsonStringEquals(expectedJson, gson); String jackson = OBJECT_MAPPER.writeValueAsString(paymentsRequest); - assertEquals(expectedJson, jackson); + assertJsonStringEquals(expectedJson, jackson); } @Test @@ -954,10 +996,10 @@ public void TestBilldeskWalletDetailsSerialization() throws JsonProcessingExcept paymentsRequest.setPaymentMethod(billdeskWalletDetails); String gson = GSON.toJson(paymentsRequest); - assertEquals(expectedJson, gson); + assertJsonStringEquals(expectedJson, gson); String jackson = OBJECT_MAPPER.writeValueAsString(paymentsRequest); - assertEquals(expectedJson, jackson); + assertJsonStringEquals(expectedJson, jackson); } @Test @@ -985,10 +1027,10 @@ public void TestDotpayDetailsSerialization() throws JsonProcessingException { paymentsRequest.setPaymentMethod(dotpayDetails); String gson = GSON.toJson(paymentsRequest); - assertEquals(expectedJson, gson); + assertJsonStringEquals(expectedJson, gson); String jackson = OBJECT_MAPPER.writeValueAsString(paymentsRequest); - assertEquals(expectedJson, jackson); + assertJsonStringEquals(expectedJson, jackson); } @Test @@ -1016,10 +1058,10 @@ public void TestEntercashDetailsSerialization() throws JsonProcessingException { paymentsRequest.setPaymentMethod(entercashDetails); String gson = GSON.toJson(paymentsRequest); - assertEquals(expectedJson, gson); + assertJsonStringEquals(expectedJson, gson); String jackson = OBJECT_MAPPER.writeValueAsString(paymentsRequest); - assertEquals(expectedJson, jackson); + assertJsonStringEquals(expectedJson, jackson); } @Test @@ -1048,7 +1090,7 @@ public void TestGenericIssuerPaymentMethodDetails() { paymentsRequest.setPaymentMethod(genericIssuerPaymentMethodDetails); String jsonRequest = PRETTY_PRINT_GSON.toJson(paymentsRequest); - assertEquals("{\n" + assertJsonStringEquals("{\n" + " \"amount\": {\n" + " \"value\": 1000,\n" + " \"currency\": \"USD\"\n" @@ -1093,10 +1135,10 @@ public void TestGiropayDetailsSerialization() throws JsonProcessingException { paymentsRequest.setPaymentMethod(giropayDetails); String gson = GSON.toJson(paymentsRequest); - assertEquals(expectedJson, gson); + assertJsonStringEquals(expectedJson, gson); String jackson = OBJECT_MAPPER.writeValueAsString(paymentsRequest); - assertEquals(expectedJson, jackson); + assertJsonStringEquals(expectedJson, jackson); } @Test @@ -1109,10 +1151,10 @@ public void TestQiwiWalletDetailsSerialization() throws JsonProcessingException paymentsRequest.setPaymentMethod(qiwiWalletDetails); String gson = GSON.toJson(paymentsRequest); - assertEquals(expectedJson, gson); + assertJsonStringEquals(expectedJson, gson); String jackson = OBJECT_MAPPER.writeValueAsString(paymentsRequest); - assertEquals(expectedJson, jackson); + assertJsonStringEquals(expectedJson, jackson); } @Test @@ -1142,10 +1184,10 @@ public void TestSamsungPayDetailsSerialization() throws JsonProcessingException paymentsRequest.setPaymentMethod(samsungPayDetails); String gson = GSON.toJson(paymentsRequest); - assertEquals(expectedJson, gson); + assertJsonStringEquals(expectedJson, gson); String jackson = OBJECT_MAPPER.writeValueAsString(paymentsRequest); - assertEquals(expectedJson, jackson); + assertJsonStringEquals(expectedJson, jackson); } @Test @@ -1175,10 +1217,10 @@ public void TestVippsDetailsSerialization() throws JsonProcessingException { paymentsRequest.setPaymentMethod(vippsDetails); String gson = GSON.toJson(paymentsRequest); - assertEquals(expectedJson, gson); + assertJsonStringEquals(expectedJson, gson); String jackson = OBJECT_MAPPER.writeValueAsString(paymentsRequest); - assertEquals(expectedJson, jackson); + assertJsonStringEquals(expectedJson, jackson); } @Test @@ -1208,10 +1250,10 @@ public void TestVisaCheckoutDetailsSerialization() throws JsonProcessingExceptio paymentsRequest.setPaymentMethod(visaCheckoutDetails); String gson = GSON.toJson(paymentsRequest); - assertEquals(expectedJson, gson); + assertJsonStringEquals(expectedJson, gson); String jackson = OBJECT_MAPPER.writeValueAsString(paymentsRequest); - assertEquals(expectedJson, jackson); + assertJsonStringEquals(expectedJson, jackson); } @Test @@ -1241,7 +1283,7 @@ public void TestRecurringPaymentMethodDetails() { String jsonRequest = PRETTY_PRINT_GSON.toJson(paymentsRequest); - assertEquals("{\n" + assertJsonStringEquals("{\n" + " \"amount\": {\n" + " \"value\": 1000,\n" + " \"currency\": \"USD\"\n" @@ -1271,7 +1313,7 @@ public void TestShopperNotificationReferencePaymentMethodDetails() { String jsonRequest = PRETTY_PRINT_GSON.toJson(paymentsRequest); - assertEquals("{\n" + assertJsonStringEquals("{\n" + " \"amount\": {\n" + " \"value\": 1000,\n" + " \"currency\": \"USD\"\n" @@ -1301,10 +1343,10 @@ public void TestAndroidPayDetails() throws JsonProcessingException { paymentsRequest.setPaymentMethod(androidPayDetails); String gson = GSON.toJson(paymentsRequest); - assertEquals(expectedJson, gson); + assertJsonStringEquals(expectedJson, gson); String jackson = OBJECT_MAPPER.writeValueAsString(paymentsRequest); - assertEquals(expectedJson, jackson); + assertJsonStringEquals(expectedJson, jackson); } @Test @@ -1341,10 +1383,10 @@ public void TestKlarnaDetailsSerialization() throws JsonProcessingException { paymentsRequest.setPaymentMethod(klarnaDetails); String gson = GSON.toJson(paymentsRequest); - assertEquals(expectedJson, gson); + assertJsonStringEquals(expectedJson, gson); String jackson = OBJECT_MAPPER.writeValueAsString(paymentsRequest); - assertEquals(expectedJson, jackson); + assertJsonStringEquals(expectedJson, jackson); } @Test @@ -1383,10 +1425,10 @@ public void TestMasterPassDetailsSerialization() throws JsonProcessingException paymentsRequest.setPaymentMethod(masterpassDetails); String gson = GSON.toJson(paymentsRequest); - assertEquals(expectedJson, gson); + assertJsonStringEquals(expectedJson, gson); String jackson = OBJECT_MAPPER.writeValueAsString(paymentsRequest); - assertEquals(expectedJson, jackson); + assertJsonStringEquals(expectedJson, jackson); } @Test @@ -1415,10 +1457,10 @@ public void TestMobilePayDetailsSerialization() throws JsonProcessingException { paymentsRequest.setPaymentMethod(mobilePayDetails); String gson = GSON.toJson(paymentsRequest); - assertEquals(expectedJson, gson); + assertJsonStringEquals(expectedJson, gson); String jackson = OBJECT_MAPPER.writeValueAsString(paymentsRequest); - assertEquals(expectedJson, jackson); + assertJsonStringEquals(expectedJson, jackson); } @Test @@ -1445,10 +1487,10 @@ public void TestPayUUpiDetailsSerialization() throws JsonProcessingException { paymentsRequest.setPaymentMethod(payUUpiDetails); String gson = GSON.toJson(paymentsRequest); - assertEquals(expectedJson, gson); + assertJsonStringEquals(expectedJson, gson); String jackson = OBJECT_MAPPER.writeValueAsString(paymentsRequest); - assertEquals(expectedJson, jackson); + assertJsonStringEquals(expectedJson, jackson); } @Test @@ -1466,6 +1508,66 @@ public void TestPayUUpiDetailsDeserialization() throws JsonProcessingException { assertEquals(expectedRequest, jacksonObject); } + @Test + public void TestPayUpiIntentDetailsSerialization() throws JsonProcessingException { + String expectedJson = "{\"amount\":{\"value\":1000,\"currency\":\"USD\"},\"merchantAccount\":\"MagentoMerchantTest\",\"paymentMethod\":{\"type\":\"upi_intent\"},\"reference\":\"Your order number\",\"returnUrl\":\"https://your-company.com/...\",\"applicationInfo\":{\"adyenLibrary\":{\"name\":\"adyen-java-api-library\",\"version\":\"" + LIB_VERSION + "\"}}}"; + + UpiIntentDetails upiIntentDetails = new UpiIntentDetails(); + PaymentsRequest paymentsRequest = createPaymentsCheckoutRequest(); + paymentsRequest.setPaymentMethod(upiIntentDetails); + + String gson = GSON.toJson(paymentsRequest); + assertJsonStringEquals(expectedJson, gson); + + String jackson = OBJECT_MAPPER.writeValueAsString(paymentsRequest); + assertJsonStringEquals(expectedJson, jackson); + } + + @Test + public void TestPayUpiIntentDetailsDeserialization() throws JsonProcessingException { + String json = "{\"amount\":{\"value\":1000,\"currency\":\"USD\"},\"merchantAccount\":\"MagentoMerchantTest\",\"paymentMethod\":{\"type\":\"upi_intent\"},\"reference\":\"Your order number\",\"returnUrl\":\"https://your-company.com/...\",\"applicationInfo\":{\"adyenLibrary\":{\"name\":\"adyen-java-api-library\",\"version\":\"" + LIB_VERSION + "\"}}}"; + + UpiIntentDetails upiIntentDetails = new UpiIntentDetails(); + PaymentsRequest expectedRequest = createPaymentsCheckoutRequest(); + expectedRequest.setPaymentMethod(upiIntentDetails); + + PaymentsRequest gsonObject = GSON.fromJson(json, PaymentsRequest.class); + assertEquals(expectedRequest, gsonObject); + + PaymentsRequest jacksonObject = OBJECT_MAPPER.readValue(json, PaymentsRequest.class); + assertEquals(expectedRequest, jacksonObject); + } + + @Test + public void TestPayUpiCollectDetailsSerialization() throws JsonProcessingException { + String expectedJson = "{\"amount\":{\"value\":1000,\"currency\":\"USD\"},\"merchantAccount\":\"MagentoMerchantTest\",\"paymentMethod\":{\"type\":\"upi_collect\"},\"reference\":\"Your order number\",\"returnUrl\":\"https://your-company.com/...\",\"applicationInfo\":{\"adyenLibrary\":{\"name\":\"adyen-java-api-library\",\"version\":\"" + LIB_VERSION + "\"}}}"; + + UpiCollectDetails upiCollectDetails = new UpiCollectDetails(); + PaymentsRequest paymentsRequest = createPaymentsCheckoutRequest(); + paymentsRequest.setPaymentMethod(upiCollectDetails); + + String gson = GSON.toJson(paymentsRequest); + assertJsonStringEquals(expectedJson, gson); + + String jackson = OBJECT_MAPPER.writeValueAsString(paymentsRequest); + assertJsonStringEquals(expectedJson, jackson); + } + + @Test + public void TestPayUpiCollectDetailsDeserialization() throws JsonProcessingException { + String json = "{\"amount\":{\"value\":1000,\"currency\":\"USD\"},\"merchantAccount\":\"MagentoMerchantTest\",\"paymentMethod\":{\"type\":\"upi_collect\"},\"reference\":\"Your order number\",\"returnUrl\":\"https://your-company.com/...\",\"applicationInfo\":{\"adyenLibrary\":{\"name\":\"adyen-java-api-library\",\"version\":\"" + LIB_VERSION + "\"}}}"; + + UpiCollectDetails upiCollectDetails = new UpiCollectDetails(); + PaymentsRequest expectedRequest = createPaymentsCheckoutRequest(); + expectedRequest.setPaymentMethod(upiCollectDetails); + + PaymentsRequest gsonObject = GSON.fromJson(json, PaymentsRequest.class); + assertEquals(expectedRequest, gsonObject); + + PaymentsRequest jacksonObject = OBJECT_MAPPER.readValue(json, PaymentsRequest.class); + assertEquals(expectedRequest, jacksonObject); + } + @Test public void TestWeChatPayDetailsSerialization() throws JsonProcessingException { String expectedJson = "{\"amount\":{\"value\":1000,\"currency\":\"USD\"},\"merchantAccount\":\"MagentoMerchantTest\",\"paymentMethod\":{\"appId\":\"appId\",\"openid\":\"openId\",\"type\":\"wechatpay\"},\"reference\":\"Your order number\",\"returnUrl\":\"https://your-company.com/...\",\"applicationInfo\":{\"adyenLibrary\":{\"name\":\"adyen-java-api-library\",\"version\":\"" + LIB_VERSION + "\"}}}"; @@ -1477,10 +1579,10 @@ public void TestWeChatPayDetailsSerialization() throws JsonProcessingException { paymentsRequest.setPaymentMethod(weChatPayDetails); String gson = GSON.toJson(paymentsRequest); - assertEquals(expectedJson, gson); + assertJsonStringEquals(expectedJson, gson); String jackson = OBJECT_MAPPER.writeValueAsString(paymentsRequest); - assertEquals(expectedJson, jackson); + assertJsonStringEquals(expectedJson, jackson); } @Test @@ -1511,10 +1613,10 @@ public void TestWeChatPayMiniProgramDetailsSerialization() throws JsonProcessing paymentsRequest.setPaymentMethod(weChatPayMiniProgramDetails); String gson = GSON.toJson(paymentsRequest); - assertEquals(expectedJson, gson); + assertJsonStringEquals(expectedJson, gson); String jackson = OBJECT_MAPPER.writeValueAsString(paymentsRequest); - assertEquals(expectedJson, jackson); + assertJsonStringEquals(expectedJson, jackson); } @Test @@ -1544,10 +1646,10 @@ public void TestBlikDetailsSerialization() throws JsonProcessingException { paymentsRequest.setPaymentMethod(blikDetails); String gson = GSON.toJson(paymentsRequest); - assertEquals(expectedJson, gson); + assertJsonStringEquals(expectedJson, gson); String jackson = OBJECT_MAPPER.writeValueAsString(paymentsRequest); - assertEquals(expectedJson, jackson); + assertJsonStringEquals(expectedJson, jackson); } @Test @@ -1578,10 +1680,10 @@ public void TestDragonpayDetailsSerialization() throws JsonProcessingException { paymentsRequest.setPaymentMethod(dragonPayDetails); String gson = GSON.toJson(paymentsRequest); - assertEquals(expectedJson, gson); + assertJsonStringEquals(expectedJson, gson); String jackson = OBJECT_MAPPER.writeValueAsString(paymentsRequest); - assertEquals(expectedJson, jackson); + assertJsonStringEquals(expectedJson, jackson); } @Test @@ -1613,10 +1715,10 @@ public void TestLianLianPayDetailsSerialization() throws JsonProcessingException paymentsRequest.setPaymentMethod(lianLianPayDetails); String gson = GSON.toJson(paymentsRequest); - assertEquals(expectedJson, gson); + assertJsonStringEquals(expectedJson, gson); String jackson = OBJECT_MAPPER.writeValueAsString(paymentsRequest); - assertEquals(expectedJson, jackson); + assertJsonStringEquals(expectedJson, jackson); } @Test @@ -1648,10 +1750,10 @@ public void TestMbwayDetailsSerialization() throws JsonProcessingException { paymentsRequest.setPaymentMethod(mbwayDetails); String gson = GSON.toJson(paymentsRequest); - assertEquals(expectedJson, gson); + assertJsonStringEquals(expectedJson, gson); String jackson = OBJECT_MAPPER.writeValueAsString(paymentsRequest); - assertEquals(expectedJson, jackson); + assertJsonStringEquals(expectedJson, jackson); } @Test @@ -1683,10 +1785,10 @@ public void TestMolPayDetailsSerialization() throws JsonProcessingException { paymentsRequest.setPaymentMethod(molPayDetails); String gson = GSON.toJson(paymentsRequest); - assertEquals(expectedJson, gson); + assertJsonStringEquals(expectedJson, gson); String jackson = OBJECT_MAPPER.writeValueAsString(paymentsRequest); - assertEquals(expectedJson, jackson); + assertJsonStringEquals(expectedJson, jackson); } @Test @@ -1717,7 +1819,7 @@ public void TestDateSerializers() throws ParseException { paymentsRequest.setDateOfBirth(d); paymentsRequest.setDeliveryDate(d); String jsonRequest = PRETTY_PRINT_GSON.toJson(paymentsRequest); - assertEquals("{\n" + assertJsonStringEquals("{\n" + " \"dateOfBirth\": \"2018-10-31\",\n" + " \"deliveryDate\": \"2018-10-31T00:00:00.000Z\",\n" + " \"applicationInfo\": {\n" @@ -1735,15 +1837,15 @@ public void TestRecurringProcessingModels() { paymentsRequest.setRecurringProcessingModel(PaymentsRequest.RecurringProcessingModelEnum.CARD_ON_FILE); String jsonRequest = PRETTY_PRINT_GSON.toJson(paymentsRequest); - assertTrue(jsonRequest.contains("recurringProcessingModel\": \"CardOnFile\"\n")); + assertTrue(jsonRequest.contains("recurringProcessingModel\": \"CardOnFile\"\n") || jsonRequest.contains("recurringProcessingModel\": \"CardOnFile\",\n")); paymentsRequest.setRecurringProcessingModel(PaymentsRequest.RecurringProcessingModelEnum.SUBSCRIPTION); jsonRequest = PRETTY_PRINT_GSON.toJson(paymentsRequest); - assertTrue(jsonRequest.contains("recurringProcessingModel\": \"Subscription\"\n")); + assertTrue(jsonRequest.contains("recurringProcessingModel\": \"Subscription\"\n") || jsonRequest.contains("recurringProcessingModel\": \"Subscription\",\n")); paymentsRequest.setRecurringProcessingModel(PaymentsRequest.RecurringProcessingModelEnum.UNSCHEDULED_CARD_ON_FILE); jsonRequest = PRETTY_PRINT_GSON.toJson(paymentsRequest); - assertTrue(jsonRequest.contains("recurringProcessingModel\": \"UnscheduledCardOnFile\"\n")); + assertTrue(jsonRequest.contains("recurringProcessingModel\": \"UnscheduledCardOnFile\"\n") || jsonRequest.contains("recurringProcessingModel\": \"UnscheduledCardOnFile\",\n")); } @Test @@ -2396,6 +2498,11 @@ public void TestCheckoutSessionErrorMocked() throws Exception { CreateCheckoutSessionResponse sessionsResponse = checkout.sessions(sessionsRequest); assertNull(sessionsResponse.getSessionData()); } + + private void assertJsonStringEquals(String firstInput, String secondInput) { + JsonParser parser = new JsonParser(); + assertEquals(parser.parse(firstInput), parser.parse(secondInput)); + } } class TestPaymentMethodDetails implements PaymentMethodDetails { diff --git a/src/test/java/com/adyen/NotificationTest.java b/src/test/java/com/adyen/NotificationTest.java index 1659f0f07..ca7ba490a 100644 --- a/src/test/java/com/adyen/NotificationTest.java +++ b/src/test/java/com/adyen/NotificationTest.java @@ -25,6 +25,7 @@ import com.adyen.model.notification.NotificationRequestItem; import com.adyen.model.notification.NotificationRequestItemContainer; import com.adyen.notification.NotificationHandler; +import com.google.gson.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import org.junit.Before; import org.junit.Test; @@ -200,7 +201,12 @@ public void testGsonAndJacksonSerializeNotificationRequest() throws JsonProcessi String gson = GSON.toJson(notificationRequest); String jackson = OBJECT_MAPPER.writeValueAsString(notificationRequest); - assertEquals(jackson, gson); + assertJsonStringEquals(jackson, gson); + } + + private void assertJsonStringEquals(String firstInput, String secondInput) { + JsonParser parser = new JsonParser(); + assertEquals(parser.parse(firstInput), parser.parse(secondInput)); } private NotificationRequest readNotificationRequestFromFile(String resourcePath) { diff --git a/src/test/java/com/adyen/PaymentRequestBuilderTest.java b/src/test/java/com/adyen/PaymentRequestBuilderTest.java index ff4773472..19df50220 100644 --- a/src/test/java/com/adyen/PaymentRequestBuilderTest.java +++ b/src/test/java/com/adyen/PaymentRequestBuilderTest.java @@ -24,6 +24,7 @@ import com.adyen.model.PaymentRequest; import com.adyen.model.PaymentRequest3d; import com.adyen.model.applicationinfo.ExternalPlatform; +import com.google.gson.JsonParser; import org.junit.Test; import java.util.HashMap; @@ -89,7 +90,7 @@ public void TestCCPaymentRequest() { + " }\n" + "}"; - assertEquals(expected, paymentRequestJson); + assertJsonStringEquals(expected, paymentRequestJson); } @Test @@ -121,7 +122,7 @@ public void TestCSEPaymentRequest() { + " }\n" + "}"; - assertEquals(expected, paymentRequestJson); + assertJsonStringEquals(expected, paymentRequestJson); } @Test @@ -146,7 +147,7 @@ public void Test3DSecureRequest() { + " }\n" + "}"; - assertEquals(expected, paymentRequestJson); + assertJsonStringEquals(expected, paymentRequestJson); } @Test @@ -159,4 +160,9 @@ public void TestSecuredFieldsPaymentRequest() { assertEquals("encryptedExpiryYear", paymentRequest.getAdditionalData().get(ApiConstants.AdditionalData.ENCRYPTED_EXPIRY_YEAR)); assertEquals("encryptedSecurityCode", paymentRequest.getAdditionalData().get(ApiConstants.AdditionalData.ENCRYPTED_SECURITY_CODE)); } + + private void assertJsonStringEquals(String firstInput, String secondInput) { + JsonParser parser = new JsonParser(); + assertEquals(parser.parse(firstInput), parser.parse(secondInput)); + } } diff --git a/src/test/java/com/adyen/serializer/SaleToAcquirerDataSerializerTest.java b/src/test/java/com/adyen/serializer/SaleToAcquirerDataSerializerTest.java index 4da8d2557..a74dfb089 100644 --- a/src/test/java/com/adyen/serializer/SaleToAcquirerDataSerializerTest.java +++ b/src/test/java/com/adyen/serializer/SaleToAcquirerDataSerializerTest.java @@ -5,6 +5,7 @@ import com.adyen.model.applicationinfo.MerchantDevice; import com.adyen.model.terminal.SaleToAcquirerData; import com.google.gson.Gson; +import com.google.gson.JsonParser; import com.google.gson.GsonBuilder; import org.apache.commons.codec.binary.Base64; import org.junit.Test; @@ -100,10 +101,16 @@ public void testSerialize() { // test if json string matches String requestJson = PRETTY_PRINT_GSON.toJson(saleToAcquirerData); - assertEquals(requestJson, json); + assertJsonStringEquals(requestJson, json); // test if base64 works - String jsonBase64 = new String(Base64.encodeBase64(json.getBytes())); - assertEquals(jsonBase64, saleToAcquirerDataModelAdapter.serialize(saleToAcquirerData, null, null).getAsString()); + String serialized = saleToAcquirerDataModelAdapter.serialize(saleToAcquirerData, null, null).getAsString(); + SaleToAcquirerData saleToAcquirerDataDecoded = new Gson().fromJson(new String(Base64.decodeBase64(serialized)), SaleToAcquirerData.class); + assertEquals(saleToAcquirerData, saleToAcquirerDataDecoded); + } + + public static void assertJsonStringEquals(String firstInput, String secondInput) { + JsonParser parser = new JsonParser(); + assertEquals(parser.parse(firstInput), parser.parse(secondInput)); } } diff --git a/src/test/java/com/adyen/service/CheckoutTest.java b/src/test/java/com/adyen/service/CheckoutTest.java index e589d36e9..2d4361dc9 100644 --- a/src/test/java/com/adyen/service/CheckoutTest.java +++ b/src/test/java/com/adyen/service/CheckoutTest.java @@ -76,9 +76,10 @@ public void testPaymentsRequestWithXidAndCavv() throws Exception { assertNotNull(response); assertEquals("12345", response.getPspReference()); verify(clientInterface).request(anyString(), captor.capture(), any(Config.class), anyBoolean(), nullable(RequestOptions.class), any()); + String captorValue = captor.getValue(); //html escaped - assertFalse(captor.getValue().contains("\"mpiData\":{\"cavv\":\"AQIDBAUGBwgJCgsMDQ4PEBESExQ\\u003d\",\"xid\":\"AQIDBAUGBwgJCgsMDQ4PEBESExQ\\u003d\"}")); + assertFalse(captorValue.contains("\"mpiData\":{\"cavv\":\"AQIDBAUGBwgJCgsMDQ4PEBESExQ\\u003d\",\"xid\":\"AQIDBAUGBwgJCgsMDQ4PEBESExQ\\u003d\"}") || captorValue.contains("\"mpiData\":{\"xid\":\"AQIDBAUGBwgJCgsMDQ4PEBESExQ\\u003d\",\"cavv\":\"AQIDBAUGBwgJCgsMDQ4PEBESExQ\\u003d\"}")); //not html escaped - assertTrue(captor.getValue().contains("\"mpiData\":{\"cavv\":\"AQIDBAUGBwgJCgsMDQ4PEBESExQ=\",\"xid\":\"AQIDBAUGBwgJCgsMDQ4PEBESExQ=\"}")); + assertTrue(captorValue.contains("\"mpiData\":{\"cavv\":\"AQIDBAUGBwgJCgsMDQ4PEBESExQ=\",\"xid\":\"AQIDBAUGBwgJCgsMDQ4PEBESExQ=\"}") || captorValue.contains("\"mpiData\":{\"xid\":\"AQIDBAUGBwgJCgsMDQ4PEBESExQ=\",\"cavv\":\"AQIDBAUGBwgJCgsMDQ4PEBESExQ=\"}")); } } diff --git a/src/test/java/com/adyen/util/HMACValidatorTest.java b/src/test/java/com/adyen/util/HMACValidatorTest.java index 50fde0945..3c04882f9 100644 --- a/src/test/java/com/adyen/util/HMACValidatorTest.java +++ b/src/test/java/com/adyen/util/HMACValidatorTest.java @@ -21,12 +21,10 @@ package com.adyen.util; +import java.security.SignatureException; +import org.junit.Test; import com.adyen.model.notification.NotificationRequestItem; import com.google.gson.Gson; -import org.junit.Test; - -import java.security.SignatureException; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -59,6 +57,59 @@ public void testValidateHMAC() throws SignatureException { assertTrue(result); } + @Test + public void testValidateHMACNullHmacSignature() throws SignatureException { + String notificationJson = "{\n" + + " \"additionalData\": {\n" + + " },\n" + + " \"amount\": {\n" + + " \"currency\": \"EUR\",\n" + + " \"value\": \"0\"\n" + + " },\n" + + " \"eventCode\": \"REPORT_AVAILABLE\",\n" + + " \"eventDate\": \"2019-11-20T14:35:36+01:00\",\n" + + " \"merchantAccountCode\": \"Magento2Rik\",\n" + + " \"merchantReference\": \"testMerchantRef1\",\n" + + " \"pspReference\": \"test_REPORT_AVAILABLE\",\n" + + " \"reason\": \"will contain the url to the report\",\n" + + " \"success\": \"true\"\n" + + "}"; + try { + NotificationRequestItem notificationRequest = new Gson().fromJson(notificationJson, NotificationRequestItem.class); + boolean result = new HMACValidator().validateHMAC(notificationRequest, HMAC_KEY); + fail(); + } catch (IllegalArgumentException e) { + assertEquals("Missing hmacSignature", e.getMessage()); + } + } + + @Test + public void testValidateHMACEmptyHmacSignature() throws SignatureException { + String notificationJson = "{\n" + + " \"additionalData\": {\n" + + " \"hmacSignature\": \"\"\n" + + " },\n" + + " \"amount\": {\n" + + " \"currency\": \"EUR\",\n" + + " \"value\": \"0\"\n" + + " },\n" + + " \"eventCode\": \"REPORT_AVAILABLE\",\n" + + " \"eventDate\": \"2019-11-20T14:35:36+01:00\",\n" + + " \"merchantAccountCode\": \"Magento2Rik\",\n" + + " \"merchantReference\": \"testMerchantRef1\",\n" + + " \"pspReference\": \"test_REPORT_AVAILABLE\",\n" + + " \"reason\": \"will contain the url to the report\",\n" + + " \"success\": \"true\"\n" + + "}"; + try { + NotificationRequestItem notificationRequest = new Gson().fromJson(notificationJson, NotificationRequestItem.class); + boolean result = new HMACValidator().validateHMAC(notificationRequest, HMAC_KEY); + fail(); + } catch (IllegalArgumentException e) { + assertEquals("Missing hmacSignature", e.getMessage()); + } + } + @Test public void testValidateHMACMissingOptionalField() throws SignatureException { String notificationJson = "{\n" +