From d74977440b72fbc7b95a340f4a7fea81f58b53ae Mon Sep 17 00:00:00 2001 From: leonardog Date: Mon, 23 Feb 2026 14:32:36 +0100 Subject: [PATCH 1/3] test(terminal): validate if boxed flags will be passed as nullable --- .../java/com/adyen/TerminalCloudAPITest.java | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/test/java/com/adyen/TerminalCloudAPITest.java b/src/test/java/com/adyen/TerminalCloudAPITest.java index 9eae0dd75..e5d190d04 100644 --- a/src/test/java/com/adyen/TerminalCloudAPITest.java +++ b/src/test/java/com/adyen/TerminalCloudAPITest.java @@ -38,11 +38,13 @@ import com.adyen.model.nexo.PaymentReceipt; import com.adyen.model.nexo.PaymentRequest; import com.adyen.model.nexo.PaymentResult; +import com.adyen.model.nexo.PaymentTransaction; import com.adyen.model.nexo.Response; import com.adyen.model.nexo.ResultType; import com.adyen.model.nexo.SaleData; import com.adyen.model.nexo.SaleToPOIRequest; import com.adyen.model.nexo.SaleToPOIResponse; +import com.adyen.model.nexo.TransactionConditions; import com.adyen.model.terminal.SaleToAcquirerData; import com.adyen.model.terminal.TerminalAPIRequest; import com.adyen.model.terminal.TerminalAPIResponse; @@ -299,6 +301,50 @@ public void syncInputRequestSuccess() throws Exception { assertFalse("Found null value", requestAsJson.contains(": null")); } + /** + * + *

When {@code setDebitPreferredFlag} is never called, the backing field stays {@code null} and + * Gson must omit it from the serialized JSON entirely. This allows the terminal to choose the + * payment type freely (DEBIT, CREDIT, or VOUCHER) rather than being forced to CREDIT by a + * spurious {@code "DebitPreferredFlag": false}. + */ + @Test + public void debitPreferredFlagOmittedFromJsonWhenNotSet() throws Exception { + Client client = createMockClientFromFile("mocks/terminal-api/payment-async-success"); + TerminalCloudAPI terminalCloudApi = new TerminalCloudAPI(client); + + TerminalAPIRequest terminalAPIRequest = createTerminalAPIPaymentRequest(); + + TransactionConditions transactionConditions = new TransactionConditions(); + // Deliberately do NOT call transactionConditions.setDebitPreferredFlag(...) + + PaymentTransaction paymentTransaction = new PaymentTransaction(); + paymentTransaction.setTransactionConditions(transactionConditions); + + terminalAPIRequest + .getSaleToPOIRequest() + .getPaymentRequest() + .setPaymentTransaction(paymentTransaction); + + terminalCloudApi.async(terminalAPIRequest); + + final ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + verify(client.getHttpClient()) + .request( + isNotNull(), + captor.capture(), + any(com.adyen.Config.class), + eq(true), + isNull(), + eq(ApiConstants.HttpMethod.POST), + isNull()); + + String requestAsJson = captor.getValue(); + assertFalse( + "DebitPreferredFlag must be absent from JSON when setter is never called", + requestAsJson.contains("DebitPreferredFlag")); + } + /** Mocked response for stored value type for POST /sync */ @Test public void syncPaymentRequestStoredValueSuccess() throws Exception { From 548eb094ad1c5cfb13e7c27c66b884c3af861084 Mon Sep 17 00:00:00 2001 From: leonardog Date: Mon, 23 Feb 2026 14:35:33 +0100 Subject: [PATCH 2/3] fix(test): swap assertFalse args to JUnit 5 signature (boolean, message) --- src/test/java/com/adyen/TerminalCloudAPITest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/adyen/TerminalCloudAPITest.java b/src/test/java/com/adyen/TerminalCloudAPITest.java index a1a643476..005a5e3d4 100644 --- a/src/test/java/com/adyen/TerminalCloudAPITest.java +++ b/src/test/java/com/adyen/TerminalCloudAPITest.java @@ -341,8 +341,8 @@ public void debitPreferredFlagOmittedFromJsonWhenNotSet() throws Exception { String requestAsJson = captor.getValue(); assertFalse( - "DebitPreferredFlag must be absent from JSON when setter is never called", - requestAsJson.contains("DebitPreferredFlag")); + requestAsJson.contains("DebitPreferredFlag"), + "DebitPreferredFlag must be absent from JSON when setter is never called"); } /** Mocked response for stored value type for POST /sync */ From 77afdde4b771393aa05e328c69c12fa4809fcf35 Mon Sep 17 00:00:00 2001 From: leonardog Date: Mon, 23 Feb 2026 14:56:50 +0100 Subject: [PATCH 3/3] test(terminal): validate DebitPreferredFlag omitted from JSON in local API serialization --- .../java/com/adyen/TerminalLocalAPITest.java | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/test/java/com/adyen/TerminalLocalAPITest.java b/src/test/java/com/adyen/TerminalLocalAPITest.java index f63a85032..a09e5e6fe 100644 --- a/src/test/java/com/adyen/TerminalLocalAPITest.java +++ b/src/test/java/com/adyen/TerminalLocalAPITest.java @@ -32,14 +32,18 @@ import com.adyen.model.nexo.PaymentInstrumentType; import com.adyen.model.nexo.PaymentReceipt; import com.adyen.model.nexo.PaymentResult; +import com.adyen.model.nexo.PaymentTransaction; import com.adyen.model.nexo.Response; import com.adyen.model.nexo.ResultType; import com.adyen.model.nexo.SaleData; import com.adyen.model.nexo.SaleToPOIResponse; +import com.adyen.model.nexo.TransactionConditions; import com.adyen.model.terminal.TerminalAPIRequest; import com.adyen.model.terminal.TerminalAPIResponse; import com.adyen.model.terminal.security.SecurityKey; import com.adyen.service.TerminalLocalAPI; +import com.adyen.terminal.serialization.TerminalAPIGsonBuilder; +import com.google.gson.Gson; import java.math.BigDecimal; import java.util.List; import org.junit.jupiter.api.Test; @@ -135,6 +139,38 @@ public void syncPaymentRequestSuccess() throws Exception { assertEquals(BigDecimal.ONE, paymentResult.getAmountsResp().getAuthorizedAmount()); } + /** + * Regression test for the DebitPreferredFlag workaround (Option A) on the local Terminal API. + * + *

{@link TerminalLocalAPI} serializes the request with {@link TerminalAPIGsonBuilder} before + * encrypting it. When {@code setDebitPreferredFlag} is never called, the backing field stays + * {@code null} and Gson must omit it from the JSON, allowing the terminal to choose the payment + * type freely (DEBIT, CREDIT, or VOUCHER). + */ + @Test + public void debitPreferredFlagOmittedFromJsonWhenNotSet() throws Exception { + Gson gson = TerminalAPIGsonBuilder.create(); + + TerminalAPIRequest terminalAPIRequest = createTerminalAPIPaymentRequest(); + + TransactionConditions transactionConditions = new TransactionConditions(); + // Deliberately do NOT call transactionConditions.setDebitPreferredFlag(...) + + PaymentTransaction paymentTransaction = new PaymentTransaction(); + paymentTransaction.setTransactionConditions(transactionConditions); + + terminalAPIRequest + .getSaleToPOIRequest() + .getPaymentRequest() + .setPaymentTransaction(paymentTransaction); + + String json = gson.toJson(terminalAPIRequest); + + assertFalse( + json.contains("DebitPreferredFlag"), + "DebitPreferredFlag must be absent from JSON when setter is never called"); + } + /** Test success flow for local request that includes unexpected attributes */ @Test public void syncPaymentRequestSuccessWithAdditionalAttributes() throws Exception {