From 86e05501cbea53fd85e2bc67a1c2be4cba47d0ff Mon Sep 17 00:00:00 2001 From: Narayan Bhat <48803246+Narayanbhat166@users.noreply.github.com> Date: Fri, 10 May 2024 15:05:25 +0530 Subject: [PATCH] refactor(payment_method_data): send optional billing details in response (#4569) --- crates/api_models/src/payments.rs | 104 +++++++++++++++--- .../stripe/payment_intents/types.rs | 4 +- .../router/src/core/payments/transformers.rs | 19 ++-- 3 files changed, 100 insertions(+), 27 deletions(-) diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index 2dc578ef75..b6e39c3568 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -2626,24 +2626,30 @@ where S: Serializer, { if let Some(payment_method_data_response) = payment_method_data_response { - match payment_method_data_response.payment_method_data { - PaymentMethodDataResponse::Reward {} => serializer.serialize_str("reward"), - PaymentMethodDataResponse::BankDebit {} - | PaymentMethodDataResponse::BankRedirect {} - | PaymentMethodDataResponse::Card(_) - | PaymentMethodDataResponse::CardRedirect {} - | PaymentMethodDataResponse::CardToken {} - | PaymentMethodDataResponse::Crypto {} - | PaymentMethodDataResponse::MandatePayment {} - | PaymentMethodDataResponse::GiftCard {} - | PaymentMethodDataResponse::PayLater {} - | PaymentMethodDataResponse::Paypal {} - | PaymentMethodDataResponse::Upi {} - | PaymentMethodDataResponse::Wallet {} - | PaymentMethodDataResponse::BankTransfer {} - | PaymentMethodDataResponse::Voucher {} => { - payment_method_data_response.serialize(serializer) + if let Some(payment_method_data) = payment_method_data_response.payment_method_data.as_ref() + { + match payment_method_data { + PaymentMethodDataResponse::Reward {} => serializer.serialize_str("reward"), + PaymentMethodDataResponse::BankDebit {} + | PaymentMethodDataResponse::BankRedirect {} + | PaymentMethodDataResponse::Card(_) + | PaymentMethodDataResponse::CardRedirect {} + | PaymentMethodDataResponse::CardToken {} + | PaymentMethodDataResponse::Crypto {} + | PaymentMethodDataResponse::MandatePayment {} + | PaymentMethodDataResponse::GiftCard {} + | PaymentMethodDataResponse::PayLater {} + | PaymentMethodDataResponse::Paypal {} + | PaymentMethodDataResponse::Upi {} + | PaymentMethodDataResponse::Wallet {} + | PaymentMethodDataResponse::BankTransfer {} + | PaymentMethodDataResponse::Voucher {} => { + payment_method_data_response.serialize(serializer) + } } + } else { + // Can serialize directly because there is no `payment_method_data` + payment_method_data_response.serialize(serializer) } } else { serializer.serialize_none() @@ -2675,7 +2681,7 @@ pub enum PaymentMethodDataResponse { pub struct PaymentMethodDataResponseWithBilling { // The struct is flattened in order to provide backwards compatibility #[serde(flatten)] - pub payment_method_data: PaymentMethodDataResponse, + pub payment_method_data: Option, pub billing: Option
, } @@ -4808,6 +4814,68 @@ mod payments_request_api_contract { Some(PaymentMethodData::Reward) ); } + + #[test] + fn test_payment_method_data_with_payment_method_billing() { + let payments_request = r#" + { + "amount": 6540, + "currency": "USD", + "payment_method_data": { + "billing": { + "address": { + "line1": "1467", + "line2": "Harrison Street", + "city": "San Fransico", + "state": "California", + "zip": "94122", + "country": "US", + "first_name": "Narayan", + "last_name": "Bhat" + } + } + } + } + "#; + + let payments_request = serde_json::from_str::(payments_request); + assert!(payments_request.is_ok()); + assert!(payments_request + .unwrap() + .payment_method_data + .unwrap() + .billing + .is_some()); + } +} + +#[cfg(test)] +mod payments_response_api_contract { + #![allow(clippy::unwrap_used)] + use super::*; + + #[derive(Debug, serde::Serialize)] + struct TestPaymentsResponse { + #[serde(serialize_with = "serialize_payment_method_data_response")] + payment_method_data: Option, + } + + #[test] + fn test_reward_payment_response() { + let payment_method_response_with_billing = PaymentMethodDataResponseWithBilling { + payment_method_data: Some(PaymentMethodDataResponse::Reward {}), + billing: None, + }; + + let payments_response = TestPaymentsResponse { + payment_method_data: Some(payment_method_response_with_billing), + }; + + let expected_response = r#"{"payment_method_data":"reward"}"#; + + let stringified_payments_response = payments_response.encode_to_string_of_json(); + assert_eq!(stringified_payments_response.unwrap(), expected_response); + } } /// Set of tests to extract billing details from payment method data diff --git a/crates/router/src/compatibility/stripe/payment_intents/types.rs b/crates/router/src/compatibility/stripe/payment_intents/types.rs index 3d5264ddbe..04bb99ef75 100644 --- a/crates/router/src/compatibility/stripe/payment_intents/types.rs +++ b/crates/router/src/compatibility/stripe/payment_intents/types.rs @@ -527,7 +527,9 @@ impl From for StripePaymentIntentResponse { capture_on: resp.capture_on, capture_method: resp.capture_method, payment_method: resp.payment_method, - payment_method_data: resp.payment_method_data.map(|pmd| pmd.payment_method_data), + payment_method_data: resp + .payment_method_data + .and_then(|pmd| pmd.payment_method_data), payment_token: resp.payment_token, shipping: resp.shipping, billing: resp.billing, diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index 2b7ba070d2..41ce77a4de 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -463,14 +463,17 @@ where let payment_method_data = additional_payment_method_data.map(api::PaymentMethodDataResponse::from); - let payment_method_data_response = payment_method_data.map(|payment_method_data| { - api_models::payments::PaymentMethodDataResponseWithBilling { - payment_method_data, - billing: payment_data - .address - .get_request_payment_method_billing() - .cloned(), - } + let payment_method_data_response = (payment_method_data.is_some() + || payment_data + .address + .get_request_payment_method_billing() + .is_some()) + .then_some(api_models::payments::PaymentMethodDataResponseWithBilling { + payment_method_data, + billing: payment_data + .address + .get_request_payment_method_billing() + .cloned(), }); let mut headers = connector_http_status_code