From 7f65fe3151029f496643265acf3cce4acf71540b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armando=20Rodr=C3=ADguez?= <127134616+armando-rodriguez-cko@users.noreply.github.com> Date: Tue, 25 Aug 2026 10:09:00 +0200 Subject: [PATCH] feat: add optional amount to VoidRequest for partial voids (INT-1689) --- .../com/checkout/payments/VoidRequest.java | 6 ++ .../payments/VoidRequestSchemaTest.java | 100 ++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 src/test/java/com/checkout/payments/VoidRequestSchemaTest.java diff --git a/src/main/java/com/checkout/payments/VoidRequest.java b/src/main/java/com/checkout/payments/VoidRequest.java index 244716bc..08233d92 100644 --- a/src/main/java/com/checkout/payments/VoidRequest.java +++ b/src/main/java/com/checkout/payments/VoidRequest.java @@ -14,6 +14,12 @@ @AllArgsConstructor public final class VoidRequest { + /** + * The amount to void. If not specified, the full payment amount is voided. + * Integer, min 0, max 9999999999. + */ + private Long amount; + private String reference; @Builder.Default diff --git a/src/test/java/com/checkout/payments/VoidRequestSchemaTest.java b/src/test/java/com/checkout/payments/VoidRequestSchemaTest.java new file mode 100644 index 00000000..882afc74 --- /dev/null +++ b/src/test/java/com/checkout/payments/VoidRequestSchemaTest.java @@ -0,0 +1,100 @@ +package com.checkout.payments; + +import com.checkout.GsonSerializer; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Schema validation tests for VoidRequest. + * Validates serialization and field completeness against swagger, in + * particular the optional amount field (partial voids, swagger 2026-08-13): + * when amount is not set it must be absent from the JSON body, because a + * null or zero amount leaking in would turn a full void into a zero-amount void. + */ +class VoidRequestSchemaTest { + + private final GsonSerializer serializer = new GsonSerializer(); + + @Test + void shouldSerializeWithAllFields() { + final Map metadata = new HashMap<>(); + metadata.put("coupon_code", "NY2018"); + + final VoidRequest request = VoidRequest.builder() + .amount(6540L) + .reference("ORD-5023-4E89") + .metadata(metadata) + .build(); + + assertDoesNotThrow(() -> { + final String json = serializer.toJson(request); + assertNotNull(json); + assertTrue(json.contains("\"amount\":6540")); + assertTrue(json.contains("\"reference\":\"ORD-5023-4E89\"")); + assertTrue(json.contains("\"coupon_code\":\"NY2018\"")); + }); + } + + @Test + void shouldOmitAmountWhenNotSet() { + final VoidRequest request = VoidRequest.builder() + .reference("ORD-5023-4E89") + .build(); + + final String json = serializer.toJson(request); + assertNotNull(json); + assertFalse(json.contains("amount")); + } + + @Test + void shouldDeserializeFromSwaggerExample() { + final String json = "{\"amount\":6540,\"reference\":\"ORD-5023-4E89\",\"metadata\":{\"coupon_code\":\"NY2018\"}}"; + + final VoidRequest request = serializer.fromJson(json, VoidRequest.class); + assertNotNull(request); + assertEquals(Long.valueOf(6540L), request.getAmount()); + assertEquals("ORD-5023-4E89", request.getReference()); + assertEquals("NY2018", request.getMetadata().get("coupon_code")); + } + + @Test + void shouldRoundTripSerialize() { + final Map metadata = new HashMap<>(); + metadata.put("partner_id", "123989"); + + final VoidRequest original = VoidRequest.builder() + .amount(1L) + .reference("REF-1") + .metadata(metadata) + .build(); + + final String json = serializer.toJson(original); + final VoidRequest deserialized = serializer.fromJson(json, VoidRequest.class); + + assertEquals(original.getAmount(), deserialized.getAmount()); + assertEquals(original.getReference(), deserialized.getReference()); + assertEquals(original.getMetadata(), deserialized.getMetadata()); + } + + @Test + void shouldRoundTripWithoutAmountAsFullVoid() { + final VoidRequest original = VoidRequest.builder() + .reference("REF-FULL-VOID") + .build(); + + final String json = serializer.toJson(original); + final VoidRequest deserialized = serializer.fromJson(json, VoidRequest.class); + + assertNull(deserialized.getAmount()); + assertEquals("REF-FULL-VOID", deserialized.getReference()); + } +}