Skip to content

Commit

Permalink
Update Product.type to be a string value or enum
Browse files Browse the repository at this point in the history
  • Loading branch information
armando-rodriguez-cko committed Jan 16, 2025
1 parent bd5401c commit 56238b2
Show file tree
Hide file tree
Showing 4 changed files with 191 additions and 1 deletion.
26 changes: 26 additions & 0 deletions src/main/java/com/checkout/GsonSerializer.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import com.checkout.issuing.controls.responses.create.MccCardControlResponse;
import com.checkout.issuing.controls.responses.create.VelocityCardControlResponse;
import com.checkout.payments.PaymentDestinationType;
import com.checkout.payments.Product;
import com.checkout.payments.ProductType;
import com.checkout.payments.previous.PaymentAction;
import com.checkout.payments.sender.Sender;
import com.checkout.payments.sender.SenderType;
Expand Down Expand Up @@ -149,6 +151,7 @@ public class GsonSerializer implements Serializer {
.registerTypeAdapter(WEBHOOKS_TYPE, webhooksResponseDeserializer())
.registerTypeAdapter(PREVIOUS_PAYMENT_ACTIONS_TYPE, paymentActionsResponsePreviousDeserializer())
.registerTypeAdapter(PAYMENT_ACTIONS_TYPE, paymentActionsResponseDeserializer())
.registerTypeAdapter(Product.class, getProductDeserializer())
.create();

private final Gson gson;
Expand Down Expand Up @@ -320,4 +323,27 @@ private static JsonDeserializer<Instant> getInstantJsonDeserializer() {
}
};
}

private static JsonDeserializer<Product> getProductDeserializer() {
return (json, typeOfT, context) -> {
JsonObject jsonObject = json.getAsJsonObject();

JsonElement typeElement = jsonObject.get("type");
Object typeValue = null;

if (typeElement != null && typeElement.isJsonPrimitive()) {
String typeAsString = typeElement.getAsString();
if (EnumUtils.isValidEnumIgnoreCase(ProductType.class, typeAsString)) {
typeValue = ProductType.valueOf(typeAsString.toUpperCase());
} else {
typeValue = typeAsString;
}
}

Product product = new Gson().fromJson(jsonObject, Product.class);
product.setType(typeValue);

return product;
};
}
}
10 changes: 9 additions & 1 deletion src/main/java/com/checkout/payments/Product.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
@AllArgsConstructor
public final class Product {

private ProductType type;
private Object type;

private String name;

Expand Down Expand Up @@ -54,4 +54,12 @@ public final class Product {
@SerializedName("service_ends_on")
private Instant serviceEndsOn;

public ProductType getTypeAsEnum() {
return type instanceof ProductType ? (ProductType) type : null;
}

public String getTypeAsString() {
return type instanceof String ? (String) type : null;
}

}
34 changes: 34 additions & 0 deletions src/test/java/com/checkout/GsonSerializerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import com.checkout.issuing.cardholders.CardholderCardsResponse;
import com.checkout.issuing.cards.responses.PhysicalCardDetailsResponse;
import com.checkout.issuing.cards.responses.VirtualCardDetailsResponse;
import com.checkout.payments.Product;
import com.checkout.payments.ProductType;
import com.checkout.payments.contexts.PaymentContextDetailsResponse;
import com.checkout.payments.previous.response.GetPaymentResponse;
import com.checkout.payments.previous.response.PaymentResponse;
Expand Down Expand Up @@ -171,6 +173,38 @@ void shouldSerializePaymentDetailsResponseFromJson() {
assertNotNull(paymentDetailsResponse.getPaymentPlan());
}

@Test
void shouldDeserializeProductWithEnumType() {
String json = "{ \"type\": \"DIGITAL\", \"name\": \"Product Name\" }";

Product product = serializer.fromJson(json, Product.class);

assertNotNull(product);
assertEquals(ProductType.DIGITAL, product.getTypeAsEnum());
assertNull(product.getTypeAsString());
}

@Test
void shouldDeserializeProductWithUnknownEnumValue() {
String json = "{ \"type\": \"UNKNOWN_VALUE\", \"name\": \"Product Name\", \"quantity\": 1, \"unit_price\": 1000 }";

Product product = serializer.fromJson(json, Product.class);

assertNotNull(product);
assertEquals("UNKNOWN_VALUE", product.getTypeAsString());
assertNull(product.getTypeAsEnum());
}

@Test
void shouldDeserializeProductWithNullType() {
String json = "{ \"type\": null, \"name\": \"Product Name\" }";

Product product = serializer.fromJson(json, Product.class);

assertNotNull(product);
assertNull(product.getType());
}

@Test
void shouldDeserializeMultipleDateFormats() {
Instant instant = Instant.parse("2021-06-08T00:00:00Z");
Expand Down
122 changes: 122 additions & 0 deletions src/test/java/com/checkout/payments/GetPaymentsTestIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import com.checkout.payments.sender.PaymentIndividualSender;
import org.junit.jupiter.api.Test;

import java.util.Arrays;
import java.util.Collections;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
Expand All @@ -21,6 +23,7 @@
import static com.checkout.CardSourceHelper.getRequestCardSource;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

Expand Down Expand Up @@ -48,6 +51,125 @@ void shouldGetCardPayment() {

}

@Test
void shouldGetPaymentWithItemsUsingEnumType() {

Product product = Product.builder()
.type(ProductType.DIGITAL)
.name("Test Product")
.quantity(1L)
.unitPrice(1000L)
.build();

PaymentRequest request = PaymentRequest.builder()
.source(getRequestCardSource())
.reference(UUID.randomUUID().toString())
.amount(1000L)
.currency(Currency.EUR)
.processingChannelId(System.getenv("CHECKOUT_PROCESSING_CHANNEL_ID"))
.items(Collections.singletonList(product))
.build();

PaymentResponse payment = blocking(() -> paymentsClient.requestPayment(request));

GetPaymentResponse paymentReturned = blocking(() -> paymentsClient.getPayment(payment.getId()));

assertNotNull(paymentReturned);
assertNotNull(paymentReturned.getItems());
assertEquals(1, paymentReturned.getItems().size());

Product returnedProduct = paymentReturned.getItems().get(0);
assertEquals(ProductType.DIGITAL, returnedProduct.getTypeAsEnum());
assertNull(returnedProduct.getTypeAsString());
assertEquals("Test Product", returnedProduct.getName());
assertEquals(1L, returnedProduct.getQuantity());
assertEquals(1000L, returnedProduct.getUnitPrice());
}

@Test
void shouldGetPaymentWithItemsUsingStringType() {

Product product = Product.builder()
.type("CustomType")
.name("Custom Product")
.quantity(2L)
.unitPrice(2000L)
.build();

PaymentRequest request = PaymentRequest.builder()
.source(getRequestCardSource())
.reference(UUID.randomUUID().toString())
.amount(2000L)
.currency(Currency.EUR)
.processingChannelId(System.getenv("CHECKOUT_PROCESSING_CHANNEL_ID"))
.items(Collections.singletonList(product))
.build();

PaymentResponse payment = blocking(() -> paymentsClient.requestPayment(request));

GetPaymentResponse paymentReturned = blocking(() -> paymentsClient.getPayment(payment.getId()));

assertNotNull(paymentReturned);
assertNotNull(paymentReturned.getItems());
assertEquals(1, paymentReturned.getItems().size());

Product returnedProduct = paymentReturned.getItems().get(0);
assertEquals("CustomType", returnedProduct.getTypeAsString());
assertNull(returnedProduct.getTypeAsEnum());
assertEquals("Custom Product", returnedProduct.getName());
assertEquals(2L, returnedProduct.getQuantity());
assertEquals(2000L, returnedProduct.getUnitPrice());
}

@Test
void shouldGetPaymentWithMultipleItems() {

Product enumProduct = Product.builder()
.type(ProductType.PHYSICAL)
.name("Physical Product")
.quantity(1L)
.unitPrice(1500L)
.build();

Product stringProduct = Product.builder()
.type("CustomType")
.name("Custom Product")
.quantity(2L)
.unitPrice(3000L)
.build();

PaymentRequest request = PaymentRequest.builder()
.source(getRequestCardSource())
.reference(UUID.randomUUID().toString())
.amount(4500L)
.currency(Currency.EUR)
.processingChannelId(System.getenv("CHECKOUT_PROCESSING_CHANNEL_ID"))
.items(Arrays.asList(enumProduct, stringProduct))
.build();

PaymentResponse payment = blocking(() -> paymentsClient.requestPayment(request));

GetPaymentResponse paymentReturned = blocking(() -> paymentsClient.getPayment(payment.getId()));

assertNotNull(paymentReturned);
assertNotNull(paymentReturned.getItems());
assertEquals(2, paymentReturned.getItems().size());

Product returnedEnumProduct = paymentReturned.getItems().get(0);
assertEquals(ProductType.PHYSICAL, returnedEnumProduct.getTypeAsEnum());
assertNull(returnedEnumProduct.getTypeAsString());
assertEquals("Physical Product", returnedEnumProduct.getName());
assertEquals(1L, returnedEnumProduct.getQuantity());
assertEquals(1500L, returnedEnumProduct.getUnitPrice());

Product returnedStringProduct = paymentReturned.getItems().get(1);
assertEquals("CustomType", returnedStringProduct.getTypeAsString());
assertNull(returnedStringProduct.getTypeAsEnum());
assertEquals("Custom Product", returnedStringProduct.getName());
assertEquals(2L, returnedStringProduct.getQuantity());
assertEquals(3000L, returnedStringProduct.getUnitPrice());
}

@Test
void shouldGetCardPaymentWithMetadata() {

Expand Down

0 comments on commit 56238b2

Please sign in to comment.