From ff48939e7b3982dc5705b1842b94eeeafc7dfe9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armando=20Rodr=C3=ADguez?= <127134616+armando-rodriguez-cko@users.noreply.github.com> Date: Mon, 2 Sep 2024 14:16:30 +0200 Subject: [PATCH] Update Klarna, Payment properties and enums --- .../java/com/checkout/GsonSerializer.java | 12 + .../com/checkout/common/CheckoutUtils.java | 2 +- .../checkout/payments/AmountVariability.java | 13 + .../checkout/payments/PaymentPlanType.java | 37 +++ .../com/checkout/payments/PaymentType.java | 20 +- .../checkout/payments/ProcessingSettings.java | 3 + .../com/checkout/payments/ProductType.java | 29 +- .../contexts/PaymentContextsItems.java | 12 + .../contexts/PaymentContextsProcessing.java | 4 + .../payments/request/PaymentRequest.java | 6 +- .../payments/response/GetPaymentResponse.java | 10 +- .../payments/response/PaymentResponse.java | 8 + .../java/com/checkout/GsonSerializerTest.java | 45 +++- .../payments/RequestApmPaymentsIT.java | 1 - .../payments/RequestPaymentsTestIT.java | 13 + .../sessions/UpdateSessionsTestIT.java | 2 +- .../plan/get_payment_context_response.json | 29 ++ .../plan/get_payment_details_response.json | 252 ++++++++++++++++++ 18 files changed, 473 insertions(+), 25 deletions(-) create mode 100644 src/main/java/com/checkout/payments/AmountVariability.java create mode 100644 src/main/java/com/checkout/payments/PaymentPlanType.java create mode 100644 src/test/resources/mocks/payments/response/plan/get_payment_context_response.json create mode 100644 src/test/resources/mocks/payments/response/plan/get_payment_details_response.json diff --git a/src/main/java/com/checkout/GsonSerializer.java b/src/main/java/com/checkout/GsonSerializer.java index 284a13ca..9ce88e2b 100644 --- a/src/main/java/com/checkout/GsonSerializer.java +++ b/src/main/java/com/checkout/GsonSerializer.java @@ -19,6 +19,7 @@ import com.checkout.issuing.controls.responses.create.VelocityCardControlResponse; import com.checkout.payments.PaymentDestinationType; import com.checkout.payments.previous.PaymentAction; +import com.checkout.payments.PaymentPlanType; import com.checkout.payments.sender.Sender; import com.checkout.payments.sender.SenderType; import com.checkout.webhooks.previous.WebhookResponse; @@ -32,6 +33,7 @@ import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; import com.google.gson.JsonPrimitive; import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; @@ -41,6 +43,7 @@ import java.lang.reflect.Type; import java.time.Instant; +import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; @@ -274,6 +277,15 @@ private static JsonDeserializer getInstantJsonDeserializer() { try { return Instant.parse(dateString); } catch (final DateTimeParseException ex) { + if (dateString.length() == 8) { + 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); + } + } for (final DateTimeFormatter formatter : DEFAULT_FORMATTERS) { try { final LocalDateTime dateTime = LocalDateTime.parse(dateString, formatter); diff --git a/src/main/java/com/checkout/common/CheckoutUtils.java b/src/main/java/com/checkout/common/CheckoutUtils.java index 20806ad6..4fb5e85a 100644 --- a/src/main/java/com/checkout/common/CheckoutUtils.java +++ b/src/main/java/com/checkout/common/CheckoutUtils.java @@ -14,8 +14,8 @@ public final class CheckoutUtils { public static final String WEEKLY = "Weekly"; public static final String MONTHLY = "Monthly"; public static final String ACCEPT_JSON = "application/json;charset=UTF-8"; - private static final String CKO_REQUEST_ID = "Cko-Request-Id"; public static final String CONTROL_TYPE = "control_type"; + private static final String CKO_REQUEST_ID = "Cko-Request-Id"; private CheckoutUtils() { } diff --git a/src/main/java/com/checkout/payments/AmountVariability.java b/src/main/java/com/checkout/payments/AmountVariability.java new file mode 100644 index 00000000..2d4e69fe --- /dev/null +++ b/src/main/java/com/checkout/payments/AmountVariability.java @@ -0,0 +1,13 @@ +package com.checkout.payments; + +import com.google.gson.annotations.SerializedName; + +public enum AmountVariability { + + @SerializedName("Fixed") + FIXED, + + @SerializedName("Variable") + VARIABLE + +} diff --git a/src/main/java/com/checkout/payments/PaymentPlanType.java b/src/main/java/com/checkout/payments/PaymentPlanType.java new file mode 100644 index 00000000..2fa44e1c --- /dev/null +++ b/src/main/java/com/checkout/payments/PaymentPlanType.java @@ -0,0 +1,37 @@ +package com.checkout.payments; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.Instant; + +@Data +@Builder +public final class PaymentPlanType { + + // Recurring + @SerializedName("amount_variability") + private AmountVariability amountVariability; + + // Installment + private Boolean financing; + + private String amount; + + // Common properties + @SerializedName("days_between_payments") + private Integer daysBetweenPayments; + + @SerializedName("total_number_of_payments") + private Integer totalNumberOfPayments; + + @SerializedName("current_payment_number") + private Integer currentPaymentNumber; + + @SerializedName("expiry") + private Instant expiry; + +} diff --git a/src/main/java/com/checkout/payments/PaymentType.java b/src/main/java/com/checkout/payments/PaymentType.java index d2f7886f..d03c53e1 100644 --- a/src/main/java/com/checkout/payments/PaymentType.java +++ b/src/main/java/com/checkout/payments/PaymentType.java @@ -4,14 +4,22 @@ public enum PaymentType { - @SerializedName("Regular") - REGULAR, - @SerializedName("Recurring") - RECURRING, - @SerializedName("Moto") - MOTO, @SerializedName("Installment") INSTALLMENT, + + @SerializedName("Moto") + MOTO, + + @SerializedName("PayLater") + PAYLATER, + + @SerializedName("Recurring") + RECURRING, + + @SerializedName("Regular") + REGULAR, + @SerializedName("Unscheduled") UNSCHEDULED + } \ No newline at end of file diff --git a/src/main/java/com/checkout/payments/ProcessingSettings.java b/src/main/java/com/checkout/payments/ProcessingSettings.java index bee74382..2858e34c 100644 --- a/src/main/java/com/checkout/payments/ProcessingSettings.java +++ b/src/main/java/com/checkout/payments/ProcessingSettings.java @@ -106,6 +106,9 @@ public final class ProcessingSettings { @SerializedName("shipping_info") private List shippingInfo; + @SerializedName("pan_preference") + private PanProcessedType panPreference; + //Previous private DLocalProcessingSettings dlocal; diff --git a/src/main/java/com/checkout/payments/ProductType.java b/src/main/java/com/checkout/payments/ProductType.java index 194b032a..db5413e2 100644 --- a/src/main/java/com/checkout/payments/ProductType.java +++ b/src/main/java/com/checkout/payments/ProductType.java @@ -6,11 +6,38 @@ public enum ProductType { @SerializedName("QR Code") QR_CODE, + @SerializedName("In-App") IN_APP, + @SerializedName("Official Account") OFFICIAL_ACCOUNT, + @SerializedName("Mini Program") - MINI_PROGRAM + MINI_PROGRAM, + + @SerializedName("pay_in_full") + PAY_IN_FULL, + + @SerializedName("pay_by_instalment") + PAY_BY_INSTALMENT, + + @SerializedName("pay_by_instalment_2") + PAY_BY_INSTALMENT_2, + + @SerializedName("pay_by_instalment_3") + PAY_BY_INSTALMENT_3, + + @SerializedName("pay_by_instalment_4") + PAY_BY_INSTALMENT_4, + + @SerializedName("pay_by_instalment_6") + PAY_BY_INSTALMENT_6, + + @SerializedName("invoice") + INVOICE, + + @SerializedName("pay_later") + PAY_LATER } \ No newline at end of file diff --git a/src/main/java/com/checkout/payments/contexts/PaymentContextsItems.java b/src/main/java/com/checkout/payments/contexts/PaymentContextsItems.java index 956bde54..c09ae3c5 100644 --- a/src/main/java/com/checkout/payments/contexts/PaymentContextsItems.java +++ b/src/main/java/com/checkout/payments/contexts/PaymentContextsItems.java @@ -12,6 +12,8 @@ @AllArgsConstructor public final class PaymentContextsItems { + private String type; + private String name; private Integer quantity; @@ -24,14 +26,24 @@ public final class PaymentContextsItems { @SerializedName("total_amount") private Integer totalAmount; + @SerializedName("tax_rate") + private Integer taxRate; + @SerializedName("tax_amount") private Integer taxAmount; @SerializedName("discount_amount") private Integer discountAmount; + @SerializedName("wxpay_goods_id") + private String wxpayGoodsId; + private String url; @SerializedName("image_url") private String imageUrl; + + @SerializedName("service_ends_on") + private String serviceEndsOn; + } diff --git a/src/main/java/com/checkout/payments/contexts/PaymentContextsProcessing.java b/src/main/java/com/checkout/payments/contexts/PaymentContextsProcessing.java index 3dabdbb2..20945436 100644 --- a/src/main/java/com/checkout/payments/contexts/PaymentContextsProcessing.java +++ b/src/main/java/com/checkout/payments/contexts/PaymentContextsProcessing.java @@ -19,6 +19,9 @@ public final class PaymentContextsProcessing { private BillingPlan plan; + @SerializedName("discount_amount") + private Integer discountAmount; + @SerializedName("shipping_amount") private Integer shippingAmount; @@ -41,4 +44,5 @@ public final class PaymentContextsProcessing { @SerializedName("airline_data") private List airlineData; + } diff --git a/src/main/java/com/checkout/payments/request/PaymentRequest.java b/src/main/java/com/checkout/payments/request/PaymentRequest.java index dba92412..6a1c2902 100644 --- a/src/main/java/com/checkout/payments/request/PaymentRequest.java +++ b/src/main/java/com/checkout/payments/request/PaymentRequest.java @@ -14,6 +14,7 @@ import com.checkout.payments.ShippingDetails; import com.checkout.payments.ThreeDSRequest; import com.checkout.payments.request.source.AbstractRequestSource; +import com.checkout.payments.PaymentPlanType; import com.checkout.payments.sender.PaymentSender; import com.google.gson.annotations.SerializedName; import lombok.Builder; @@ -38,7 +39,10 @@ public final class PaymentRequest { private Currency currency; @SerializedName("payment_type") - private PaymentType paymentType; + private PaymentType paymentType = PaymentType.REGULAR; + + @SerializedName("payment_plan") + private PaymentPlanType paymentPlan; @SerializedName("merchant_initiated") private Boolean merchantInitiated; diff --git a/src/main/java/com/checkout/payments/response/GetPaymentResponse.java b/src/main/java/com/checkout/payments/response/GetPaymentResponse.java index 8bfb5290..3a2f075e 100644 --- a/src/main/java/com/checkout/payments/response/GetPaymentResponse.java +++ b/src/main/java/com/checkout/payments/response/GetPaymentResponse.java @@ -17,6 +17,7 @@ import com.checkout.payments.ThreeDSData; import com.checkout.payments.request.PaymentInstruction; import com.checkout.payments.response.destination.PaymentResponseDestination; +import com.checkout.payments.PaymentPlanType; import com.checkout.payments.response.source.ResponseSource; import com.checkout.payments.sender.Sender; import com.google.gson.annotations.SerializedName; @@ -51,6 +52,9 @@ public final class GetPaymentResponse extends Resource { @SerializedName("payment_type") private PaymentType type; + @SerializedName("payment_plan") + private PaymentPlanType paymentPlan; + private String reference; private String description; @@ -103,12 +107,12 @@ public final class GetPaymentResponse extends Resource { private String schemeId; private List actions; - + private PaymentRetryResponse retry; - + @SerializedName("pan_type_processed") private PanProcessedType panTypeProcessed; - + @SerializedName("cko_network_token_available") private Boolean ckoNetworkTokenAvailable; diff --git a/src/main/java/com/checkout/payments/response/PaymentResponse.java b/src/main/java/com/checkout/payments/response/PaymentResponse.java index a2d94f9c..1631bb4c 100644 --- a/src/main/java/com/checkout/payments/response/PaymentResponse.java +++ b/src/main/java/com/checkout/payments/response/PaymentResponse.java @@ -6,9 +6,11 @@ import com.checkout.payments.PaymentProcessing; import com.checkout.payments.PaymentRecipient; import com.checkout.payments.PaymentStatus; +import com.checkout.payments.PaymentType; import com.checkout.payments.RiskAssessment; import com.checkout.payments.ShippingDetails; import com.checkout.payments.ThreeDSEnrollment; +import com.checkout.payments.PaymentPlanType; import com.checkout.payments.response.source.ResponseSource; import com.google.gson.annotations.SerializedName; import lombok.Data; @@ -29,6 +31,12 @@ public final class PaymentResponse extends Resource implements Serializable { private String id; + @SerializedName("payment_type") + private PaymentType paymentType; + + @SerializedName("payment_plan") + private PaymentPlanType paymentPlan; + @SerializedName("action_id") private String actionId; diff --git a/src/test/java/com/checkout/GsonSerializerTest.java b/src/test/java/com/checkout/GsonSerializerTest.java index eb7a183f..3cad9ad7 100644 --- a/src/test/java/com/checkout/GsonSerializerTest.java +++ b/src/test/java/com/checkout/GsonSerializerTest.java @@ -131,39 +131,62 @@ void shouldSerializePaymentContextsPayPalDetailsResponseFromJson() { assertEquals(PaymentSourceType.PAYPAL, paymentContextsPayPalResponseSource.getPaymentRequest().getSource().getType()); } + @Test + void shouldSerializePaymentContextsResponseFromJson() { + + final com.checkout.payments.response.PaymentResponse paymentContextsResponse = serializer.fromJson(getMock("/mocks/payments/response/plan/get_payment_context_response.json"), com.checkout.payments.response.PaymentResponse.class); + + assertNotNull(paymentContextsResponse); + assertNotNull(paymentContextsResponse.getPaymentPlan()); + } + + @Test + void shouldSerializePaymentDetailsResponseFromJson() { + + final com.checkout.payments.response.GetPaymentResponse paymentDetailsResponse = serializer.fromJson(getMock("/mocks/payments/response/plan/get_payment_details_response.json"), com.checkout.payments.response.GetPaymentResponse.class); + + assertNotNull(paymentDetailsResponse); + assertNotNull(paymentDetailsResponse.getPaymentPlan()); + } + @Test void shouldDeserializeMultipleDateFormats() { - Instant instant = Instant.parse("2021-06-08T12:25:01Z"); - PaymentResponse paymentResponse = serializer.fromJson("{\"processed_on\":\"2021-06-08T12:25:01.000Z\"}", PaymentResponse.class); + Instant instant = Instant.parse("2021-06-08T00:00:00Z"); + PaymentResponse paymentResponse; + + // Test format yyyyMMdd + paymentResponse = serializer.fromJson("{\"processed_on\":\"20210608\"}", PaymentResponse.class); assertNotNull(paymentResponse); assertNotNull(paymentResponse.getProcessedOn()); assertEquals(instant, paymentResponse.getProcessedOn()); - paymentResponse = serializer.fromJson("{\"processed_on\":\"2021-06-08T12:25:01Z\"}", PaymentResponse.class); + // Test other valid formats + paymentResponse = serializer.fromJson("{\"processed_on\":\"2021-06-08T12:25:01.000Z\"}", PaymentResponse.class); assertNotNull(paymentResponse); assertNotNull(paymentResponse.getProcessedOn()); - assertEquals(instant, paymentResponse.getProcessedOn()); + assertEquals(Instant.parse("2021-06-08T12:25:01Z"), paymentResponse.getProcessedOn()); - paymentResponse = serializer.fromJson("{\"processed_on\":\"2021-06-08T12:25:01+00:00\"}", PaymentResponse.class); + paymentResponse = serializer.fromJson("{\"processed_on\":\"2021-06-08T12:25:01Z\"}", PaymentResponse.class); assertNotNull(paymentResponse); assertNotNull(paymentResponse.getProcessedOn()); - assertEquals(instant, paymentResponse.getProcessedOn()); + assertEquals(Instant.parse("2021-06-08T12:25:01Z"), paymentResponse.getProcessedOn()); - paymentResponse = serializer.fromJson("{\"processed_on\":\"2021-06-08T12:25:01+0000\"}", PaymentResponse.class); + paymentResponse = serializer.fromJson("{\"processed_on\":\"2021-06-08T12:25:01+00:00\"}", PaymentResponse.class); assertNotNull(paymentResponse); assertNotNull(paymentResponse.getProcessedOn()); - assertEquals(instant, paymentResponse.getProcessedOn()); + assertEquals(Instant.parse("2021-06-08T12:25:01Z"), paymentResponse.getProcessedOn()); - paymentResponse = serializer.fromJson("{\"processed_on\":\"2021-06-08T12:25:01+00\"}", PaymentResponse.class); + paymentResponse = serializer.fromJson("{\"processed_on\":\"2021-06-08T12:25:01+0000\"}", PaymentResponse.class); assertNotNull(paymentResponse); assertNotNull(paymentResponse.getProcessedOn()); - assertEquals(instant, paymentResponse.getProcessedOn()); + assertEquals(Instant.parse("2021-06-08T12:25:01Z"), paymentResponse.getProcessedOn()); paymentResponse = serializer.fromJson("{\"processed_on\":\"2021-06-08T12:25:01\"}", PaymentResponse.class); assertNotNull(paymentResponse); assertNotNull(paymentResponse.getProcessedOn()); - assertEquals(instant, paymentResponse.getProcessedOn()); + assertEquals(Instant.parse("2021-06-08T12:25:01Z"), paymentResponse.getProcessedOn()); + // Additional cases for different milliseconds precision paymentResponse = serializer.fromJson("{\"processed_on\":\"2021-06-08T12:25:01.4698039\"}", PaymentResponse.class); assertNotNull(paymentResponse); assertNotNull(paymentResponse.getProcessedOn()); diff --git a/src/test/java/com/checkout/payments/RequestApmPaymentsIT.java b/src/test/java/com/checkout/payments/RequestApmPaymentsIT.java index 7c0673e3..93f2f03b 100644 --- a/src/test/java/com/checkout/payments/RequestApmPaymentsIT.java +++ b/src/test/java/com/checkout/payments/RequestApmPaymentsIT.java @@ -31,7 +31,6 @@ import com.checkout.payments.request.source.apm.RequestMbwaySource; import com.checkout.payments.request.source.apm.RequestMultiBancoSource; import com.checkout.payments.request.source.apm.RequestP24Source; -import com.checkout.payments.request.source.apm.RequestPayPalSource; import com.checkout.payments.request.source.apm.RequestPostFinanceSource; import com.checkout.payments.request.source.apm.RequestQPaySource; import com.checkout.payments.request.source.apm.RequestSepaSource; diff --git a/src/test/java/com/checkout/payments/RequestPaymentsTestIT.java b/src/test/java/com/checkout/payments/RequestPaymentsTestIT.java index 1708c609..862662ce 100644 --- a/src/test/java/com/checkout/payments/RequestPaymentsTestIT.java +++ b/src/test/java/com/checkout/payments/RequestPaymentsTestIT.java @@ -1,6 +1,7 @@ package com.checkout.payments; import com.checkout.CardSourceHelper; +import com.checkout.CheckoutArgumentException; import com.checkout.common.AccountHolderIdentification; import com.checkout.common.AccountHolderIdentificationType; import com.checkout.common.Address; @@ -26,7 +27,9 @@ import com.checkout.tokens.CardTokenResponse; import org.junit.jupiter.api.Test; +import java.time.Instant; import java.util.Collections; +import java.util.Date; import java.util.UUID; import static com.checkout.CardSourceHelper.getCorporateSender; @@ -61,8 +64,18 @@ void shouldMakeCardPayment() { .build()) .build(); + final PaymentPlanType recurringPlan = PaymentPlanType.builder() + .amountVariability(AmountVariability.FIXED) + .daysBetweenPayments(1) + .totalNumberOfPayments(1) + .currentPaymentNumber(1) + .expiry(Instant.parse("2025-12-31T00:00:00Z")) + .build(); + final PaymentRequest request = PaymentRequest.builder() .source(source) + .paymentType(PaymentType.RECURRING) + .paymentPlan(recurringPlan) .sender(sender) .capture(false) .reference(UUID.randomUUID().toString()) diff --git a/src/test/java/com/checkout/sessions/UpdateSessionsTestIT.java b/src/test/java/com/checkout/sessions/UpdateSessionsTestIT.java index 84b36cac..5c02fa89 100644 --- a/src/test/java/com/checkout/sessions/UpdateSessionsTestIT.java +++ b/src/test/java/com/checkout/sessions/UpdateSessionsTestIT.java @@ -114,7 +114,7 @@ void shouldUpdateCardSession() { assertNotNull(updated.getCard()); assertEquals(AuthenticationType.REGULAR, updated.getAuthenticationType()); assertEquals(Category.PAYMENT, updated.getAuthenticationCategory()); - assertEquals(SessionStatus.UNAVAILABLE, updated.getStatus()); + assertEquals(SessionStatus.PENDING, updated.getStatus()); assertNotNull(updated.getSelfLink()); assertNotNull(updated.getLink("success_url")); assertNotNull(updated.getLink("failure_url")); diff --git a/src/test/resources/mocks/payments/response/plan/get_payment_context_response.json b/src/test/resources/mocks/payments/response/plan/get_payment_context_response.json new file mode 100644 index 00000000..0a4e634b --- /dev/null +++ b/src/test/resources/mocks/payments/response/plan/get_payment_context_response.json @@ -0,0 +1,29 @@ +{ + "id": "pay_mbabizu24mvu3mela5njyhpit4", + "payment_type": "Installment", + "payment_plan": { + "financing": true, + "amount": 100000, + "days_between_payments": 28, + "total_number_of_payments": 5, + "current_payment_number": 3, + "expiry": 20251031 + }, + "processing": { + "partner_order_id": "5GK24544NA744002L" + }, + "customer": { + "id": "cus_y3oqhf46pyzuxjbcn2giaqnb44", + "email": "johnsmith@example.com", + "name": "John Smith", + "phone": { + "country_code": "+1", + "number": "415 555 2671" + } + }, + "_links": { + "self": { + "href": "https://api.checkout.com/payments/pay_y3oqhf46pezuxjbcn2giaqnb44" + } + } +} diff --git a/src/test/resources/mocks/payments/response/plan/get_payment_details_response.json b/src/test/resources/mocks/payments/response/plan/get_payment_details_response.json new file mode 100644 index 00000000..5c7017ce --- /dev/null +++ b/src/test/resources/mocks/payments/response/plan/get_payment_details_response.json @@ -0,0 +1,252 @@ +{ + "id": "pay_mbabizu24mvu3mela5njyhpit4", + "requested_on": "2019-08-24T14:15:22Z", + "source": { + "type": "card" + }, + "destination": { + "type": "card" + }, + "amount": 6540, + "amount_requested": 6540, + "currency": "USD", + "payment_type": "Recurring", + "payment_plan": { + "amount_variability": "Variable", + "days_between_payments": 28, + "total_number_of_payments": 5, + "current_payment_number": 3, + "expiry": 20251031 + }, + "reference": "ORD-5023-4E89", + "description": "Set of 3 masks", + "approved": true, + "expires_on": "2025-08-24T14:15:22Z", + "status": "Authorized", + "balances": { + "total_authorized": 6540, + "total_voided": 0, + "available_to_void": 6540, + "total_captured": 0, + "available_to_capture": 6540, + "total_refunded": 0, + "available_to_refund": 0 + }, + "3ds": { + "downgraded": false, + "enrolled": "Y", + "signature_valid": "Y", + "authentication_response": "Y", + "authentication_status_reason": "string", + "cryptogram": "hv8mUFzPzRZoCAAAAAEQBDMAAAA=", + "xid": "MDAwMDAwMDAwMDAwMDAwMzIyNzY=", + "version": "2.1.0", + "exemption": "low_value", + "exemption_applied": "string", + "challenged": true, + "upgrade_reason": "sca_retry", + "trusted_listing": { + "status": "Y", + "source": "01" + } + }, + "risk": { + "flagged": true, + "score": 22 + }, + "customer": { + "id": "cus_y3oqhf46pyzuxjbcn2giaqnb44", + "email": "brucewayne@gmail.com", + "name": "Bruce Wayne" + }, + "billing_descriptor": { + "name": "SUPERHEROES.COM", + "city": "GOTHAM", + "reference": "string", + "local_descriptors": [ + { + "name": "漢字", + "character_set": "kanji" + } + ] + }, + "shipping": { + "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" + } + }, + "payment_ip": "90.197.169.245", + "sender": { + "type": "instrument", + "reference": "8285282045818" + }, + "amount_allocations": [ + { + "id": "ent_w4jelhppmfiufdnatam37wrfc4", + "amount": 1000, + "reference": "ORD-5023-4E89", + "commission": { + "amount": 1000, + "percentage": 1.125 + } + } + ], + "recipient": { + "dob": "1985-05-15", + "account_number": "5555554444", + "address": { + "address_line1": "123 High St.", + "address_line2": "Flat 456", + "city": "London", + "state": "str", + "zip": "SW1A 1AA", + "country": "GB" + }, + "zip": "SW1A", + "first_name": "John", + "last_name": "Jones" + }, + "processing": { + "preferred_scheme": "cartes_bancaires", + "app_id": "com.iap.linker_portal", + "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": "US" + } + } + ], + "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", + "check_in_date": "2023-06-20", + "check_out_date": "2023-06-23", + "state": "US", + "country": "CA", + "city": "Los Angeles", + "room": [ + { + "rate": "70", + "number_of_nights_at_room_rate": "3" + } + ] + } + ], + "partner_customer_id": "2102209000001106125F8", + "partner_payment_id": "440644309099499894406", + "tax_amount": 1000, + "locale": "en-US", + "retrieval_reference_number": "909913440644", + "partner_order_id": "string", + "partner_status": "string", + "partner_transaction_id": "string", + "partner_error_codes": [ + "string" + ], + "partner_error_message": "string", + "partner_authorization_code": "string", + "partner_authorization_response_code": "string", + "partner_fraud_status": "string", + "custom_payment_method_ids": [ + "string" + ], + "aft": true, + "merchant_category_code": 5311, + "scheme_merchant_id": "string" + }, + "items": [ + { + "type": "string", + "name": "Kevlar batterang", + "quantity": 2, + "unit_price": 50, + "reference": "858818ac", + "commodity_code": "DEF123", + "unit_of_measure": "metres", + "total_amount": 29000, + "tax_rate": 2000, + "tax_amount": 1000, + "discount_amount": 1000, + "wxpay_goods_id": 1001, + "url": "string", + "image_url": "string", + "service_ends_on": "2025-01-01" + } + ], + "metadata": { + "coupon_code": "NY2018", + "partner_id": 123989 + }, + "eci": "06", + "scheme_id": "488341541494658", + "actions": [ + { + "id": "act_y3oqhf46pyzuxjbcn2giaqnb44", + "type": "Authorization", + "response_code": "10000", + "response_summary": "Approved" + } + ], + "retry": { + "attempts_made": 0, + "max_attempts": 6, + "ends_on": "2019-08-24T14:15:22Z", + "next_attempt_on": "2019-08-24T14:15:22Z" + }, + "pan_type_processed": "fpan", + "cko_network_token_available": false, + "instruction": { + "purpose": "financial_services" + }, + "_links": { + "self": { + "href": "https://api.checkout.com/payments/pay_y3oqhf46pyzuxjbcn2giaqnb44" + }, + "actions": { + "href": "https://api.checkout.com/payments/pay_y3oqhf46pyzuxjbcn2giaqnb44/actions" + }, + "authorize": { + "href": "https://api.checkout.com/payments/pay_y3oqhf46pyzuxjbcn2giaqnb44/authorizations" + }, + "refund": { + "href": "https://api.checkout.com/payments/pay_y3oqhf46pyzuxjbcn2giaqnb44/refund" + } + } +}