Skip to content

Commit

Permalink
Improve deserialization
Browse files Browse the repository at this point in the history
  • Loading branch information
armando-rodriguez-cko committed Nov 21, 2024
1 parent e111be3 commit bb686eb
Show file tree
Hide file tree
Showing 5 changed files with 610 additions and 41 deletions.
29 changes: 25 additions & 4 deletions src/main/java/com/checkout/GsonSerializer.java
Original file line number Diff line number Diff line change
Expand Up @@ -273,27 +273,48 @@ private static JsonDeserializer<GetScheduleResponse> getScheduleResponseDeserial

private static JsonDeserializer<Instant> getInstantJsonDeserializer() {
return (json, typeOfT, context) -> {
final String dateString = json.getAsString();
String dateString;

// Check if the JSON is a number or a string
if (json.isJsonPrimitive() && json.getAsJsonPrimitive().isNumber()) {
dateString = String.valueOf(json.getAsLong()); // Convert numeric value to string
} else {
dateString = json.getAsString(); // Use the string value directly
}

try {
// Try parsing the string as an ISO-8601 Instant
return Instant.parse(dateString);
} catch (final DateTimeParseException ex) {
if (dateString.length() == 8) {
if (dateString.matches("\\d{8}")) { // Handle numeric format yyyyMMdd
try {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
LocalDateTime dateTime = LocalDate.parse(dateString, formatter).atStartOfDay();
return dateTime.toInstant(ZoneOffset.UTC);
} catch (final DateTimeParseException e) {
throw new JsonParseException("Failed to parse date in format yyyyMMdd: " + dateString, e);
throw new JsonParseException("Failed to parse numeric date in format yyyyMMdd: " + dateString, e);
}
}
// Explicitly handle the yyyy-MM-dd format
if (dateString.length() == 10) { // Handle format yyyy-MM-dd
try {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDate date = LocalDate.parse(dateString, formatter);
return date.atStartOfDay().toInstant(ZoneOffset.UTC);
} catch (final DateTimeParseException e) {
throw new JsonParseException("Failed to parse date in format yyyy-MM-dd: " + dateString, e);
}
}
// Attempt parsing with the DEFAULT_FORMATTERS
for (final DateTimeFormatter formatter : DEFAULT_FORMATTERS) {
try {
final LocalDateTime dateTime = LocalDateTime.parse(dateString, formatter);
return dateTime.toInstant(ZoneOffset.UTC);
} catch (final DateTimeParseException ignored) {
// continue to next formatter
// Continue with the next formatter
}
}
// Rethrow the original exception if no format matches
throw ex;
}
};
Expand Down
32 changes: 32 additions & 0 deletions src/test/java/com/checkout/GsonSerializerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.checkout.payments.previous.response.PaymentResponse;
import com.checkout.payments.previous.response.destination.PaymentResponseAlternativeDestination;
import com.checkout.payments.previous.response.destination.PaymentResponseCardDestination;
import com.checkout.payments.response.source.contexts.PaymentContextsKlarnaResponseSource;
import com.checkout.payments.response.source.contexts.PaymentContextsPayPalResponseSource;
import com.checkout.payments.sender.PaymentCorporateSender;
import com.checkout.payments.sender.ResponseAlternativeSender;
Expand Down Expand Up @@ -121,6 +122,15 @@ void shouldGetFinancial() {
assertNotNull(actionsQueryResponse.getData().get(0).getRequestedOn());
}

@Test
void shouldSerializePaymentKlarnaDetailsResponseFromJson() {

final com.checkout.payments.response.GetPaymentResponse paymentKlarnaResponseSource = serializer.fromJson(getMock("/mocks/payments/response/get_payment_klarna_response.json"), com.checkout.payments.response.GetPaymentResponse.class);

assertNotNull(paymentKlarnaResponseSource);
assertEquals(PaymentSourceType.KLARNA, paymentKlarnaResponseSource.getSource().getType());
}

@Test
void shouldSerializePaymentContextsPayPalDetailsResponseFromJson() {

Expand All @@ -131,6 +141,16 @@ void shouldSerializePaymentContextsPayPalDetailsResponseFromJson() {
assertEquals(PaymentSourceType.PAYPAL, paymentContextsPayPalResponseSource.getPaymentRequest().getSource().getType());
}

@Test
void shouldSerializePaymentContextsKlarnaDetailsResponseFromJson() {

final PaymentContextDetailsResponse paymentKlarnaResponseSource = serializer.fromJson(getMock("/mocks/payments/response/contexts/payment_context_klarna_details_response.json"), PaymentContextDetailsResponse.class);

assertNotNull(paymentKlarnaResponseSource);
assertTrue(paymentKlarnaResponseSource.getPaymentRequest().getSource() instanceof PaymentContextsKlarnaResponseSource);
assertEquals(PaymentSourceType.KLARNA, paymentKlarnaResponseSource.getPaymentRequest().getSource().getType());
}

@Test
void shouldSerializePaymentContextsResponseFromJson() {

Expand Down Expand Up @@ -160,6 +180,18 @@ void shouldDeserializeMultipleDateFormats() {
assertNotNull(paymentResponse.getProcessedOn());
assertEquals(instant, paymentResponse.getProcessedOn());

// Test format yyyyMMdd number
paymentResponse = serializer.fromJson("{\"processed_on\":20210608}", PaymentResponse.class);
assertNotNull(paymentResponse);
assertNotNull(paymentResponse.getProcessedOn());
assertEquals(instant, paymentResponse.getProcessedOn());

// Test format yyyy-MM-dd
paymentResponse = serializer.fromJson("{\"processed_on\":\"2021-06-08\"}", PaymentResponse.class);
assertNotNull(paymentResponse);
assertNotNull(paymentResponse.getProcessedOn());
assertEquals(instant, paymentResponse.getProcessedOn());

// Test other valid formats
paymentResponse = serializer.fromJson("{\"processed_on\":\"2021-06-08T12:25:01.000Z\"}", PaymentResponse.class);
assertNotNull(paymentResponse);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
{
"status": "Approved",
"payment_request": {
"source": {
"type": "klarna"
},
"amount": 6540,
"currency": "USD",
"payment_type": "Recurring",
"capture": true,
"customer": {
"email": "[email protected]",
"name": "John Smith"
},
"shipping": {
"first_name": "John",
"last_name": "Smith",
"email": "[email protected]",
"address": {
"address_line1": "123 High St.",
"address_line2": "Flat 456",
"city": "London",
"state": "str",
"zip": "SW1A 1AA",
"country": "GB"
},
"phone": {
"country_code": "+1",
"number": "415 555 2671"
},
"from_address_zip": "123456",
"timeframe": "SameDay",
"method": "BillingAddress",
"delay": 5
},
"processing": {
"plan": {
"type": "MERCHANT_INITIATED_BILLING",
"skip_shipping_address": true,
"immutable_shipping_address": true
},
"discount_amount": 5,
"shipping_amount": 300,
"tax_amount": 3000,
"invoice_id": "string",
"brand_name": "Acme Corporation",
"locale": "en-US",
"shipping_preference": "set_provided_address",
"user_action": "pay_now",
"partner_customer_risk_data": {
"key": "string",
"value": "string"
},
"custom_payment_method_ids": [
"string"
],
"airline_data": [
{
"ticket": {
"number": "045-21351455613",
"issue_date": "2023-05-20",
"issuing_carrier_code": "AI",
"travel_package_indicator": "B",
"travel_agency_name": "World Tours",
"travel_agency_code": "01"
},
"passenger": [
{
"first_name": "John",
"last_name": "White",
"date_of_birth": "1990-05-26",
"address": {
"country": null
}
}
],
"flight_leg_details": [
{
"flight_number": "101",
"carrier_code": "BA",
"class_of_travelling": "J",
"departure_airport": "LHR",
"departure_date": "2023-06-19",
"departure_time": "15:30",
"arrival_airport": "LAX",
"stop_over_code": "x",
"fare_basis_code": "SPRSVR"
}
]
}
],
"accommodation_data": [
{
"name": "The Sea View Hotel",
"booking_reference": "HOTEL123",
"check_in_date": "2023-06-20",
"check_out_date": "2023-06-23",
"address": {
"address_line1": "123 Beach Road",
"zip": 10001
},
"state": "FL",
"country": "USA",
"city": "Los Angeles",
"number_of_rooms": 2,
"guests": [
{
"first_name": "Jane",
"last_name": "Doe",
"date_of_birth": "1985-07-14"
}
],
"room": [
{
"rate": "70",
"number_of_nights_at_room_rate": "3"
}
]
}
]
},
"processing_channel_id": "pc_q4dbxom5jbgudnjzjpz7j2z6uq",
"reference": "ORD-5023-4E89",
"description": "Set of 3 masks",
"success_url": "https://example.com/payments/success",
"failure_url": "https://example.com/payments/fail",
"items": [
{
"type": "string",
"name": "Test item",
"quantity": 2,
"unit_price": 50,
"reference": "858818ac",
"total_amount": 29000,
"tax_rate": 2000,
"tax_amount": 1000,
"discount_amount": 1000,
"url": "string",
"image_url": "string"
}
]
},
"partner_metadata": {
"order_id": "test_order_123",
"customer_id": "cus_123",
"session_id": "feb0096d-8486-400d-89fa-2fa716b4521f",
"client_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjgyMzA1ZWJjLWI4MTEtMzYzNy1hYTRjLTY2ZWNhMTg3NGYzZCJ9.eyJzZXNzaW9uX2lkIjoiY2RiNDI0MGQtMTdkYy01MjJkLWJlYjEtYjAyYjRlMzllYTdhIiwiYmFzZV91cmwiOiJodHRwczovL2pzLnBsYXlncm91bmQua2xhcm5hLmNvbS9ldS9rcCIsImRlc2lnbiI6ImtsYXJuYSIsImxhbmd1YWdlIjoiZW4iLCJwdXJjaGFzZV9jb3VudHJ5IjoiREUiLCJlbnZpcm9ubWVudCI6InBsYXlncm91bmQiLCJtZXJjaGFudF9uYW1lIjoiQ2hlY2tvdXQuY29tIiwic2Vzc2lvbl90eXBlIjoiUEFZTUVOVFMiLCJjbGllbnRfZXZlbnRfYmFzZV91cmwiOiJodHRwczovL2V1LnBsYXlncm91bmQua2xhcm5hZXZ0LmNvbSIsInNjaGVtZSI6dHJ1ZSwiZXhwZXJpbWVudHMiOlt7Im5hbWUiOiJrcC1jbGllbnQtb25lLXB1cmNoYXNlLWZsb3ciLCJ2YXJpYXRlIjoidmFyaWF0ZS0xIn0seyJuYW1lIjoia3AtY2xpZW50LXV0b3BpYS1mbG93IiwidmFyaWF0ZSI6InZhcmlhdGUtMSJ9LHsibmFtZSI6ImtwYy0xay1zZXJ2aWNlIiwidmFyaWF0ZSI6InZhcmlhdGUtMSJ9LHsibmFtZSI6ImtwLWNsaWVudC11dG9waWEtc3RhdGljLXdpZGdldCIsInZhcmlhdGUiOiJpbmRleCIsInBhcmFtZXRlcnMiOnsiZHluYW1pYyI6InRydWUifX0seyJuYW1lIjoiaW4tYXBwLXNkay1uZXctaW50ZXJuYWwtYnJvd3NlciIsInBhcmFtZXRlcnMiOnsidmFyaWF0ZV9pZCI6Im5ldy1pbnRlcm5hbC1icm93c2VyLWVuYWJsZSJ9fSx7Im5hbWUiOiJrcC1jbGllbnQtdXRvcGlhLXNkay1mbG93IiwidmFyaWF0ZSI6InZhcmlhdGUtMSJ9LHsibmFtZSI6ImtwLWNsaWVudC11dG9waWEtd2Vidmlldy1mbG93IiwidmFyaWF0ZSI6InZhcmlhdGUtMSJ9LHsibmFtZSI6ImluLWFwcC1zZGstY2FyZC1zY2FubmluZyIsInBhcmFtZXRlcnMiOnsidmFyaWF0ZV9pZCI6ImNhcmQtc2Nhbm5pbmctZW5hYmxlIn19XSwicmVnaW9uIjoiZXUiLCJvcmRlcl9hbW91bnQiOjIwMDAsIm9mZmVyaW5nX29wdHMiOjAsIm9vIjoiY3ciLCJ2ZXJzaW9uIjoidjEuMTAuMC0xNTkwLWczZWJjMzkwNyJ9.ZxThQVo5e0Fck1vwOQ-WWAr7Zw-dsiEhjd3CW-E5p8atUhnBhrzIs6WCBeOOv3ci2VvpykVnDw2qycCTA-7TpTq1wn_kPxxixDQnYJYJzrZMoUhPLZo5pfy2a1S_t2owEQks0THRzu2wRlZwCN4ewDnVqsut60X4r3B92cJENIDtEC4Fs55CjFEmYUtsLXSspNLKvpZe2zg4O_M5yjH7XsBs5YJalZLexf4545G5vJrmVHgiA322mbgWC7BH0IU1A-ql5sFvs190_cjGaLsAvrkh9CVczUPy3X-jr3A5z1YRVfywPpvwKFWL8GZtgrdUZmgiU5_8ZZLkEPzrSucHrQ"
}
}
Loading

0 comments on commit bb686eb

Please sign in to comment.