diff --git a/crates/api_models/src/mandates.rs b/crates/api_models/src/mandates.rs index b29f4e0d0c..7c20a902d2 100644 --- a/crates/api_models/src/mandates.rs +++ b/crates/api_models/src/mandates.rs @@ -77,6 +77,9 @@ pub struct MandateCardDetails { pub card_network: Option, /// The type of the payment card pub card_type: Option, + /// The nick_name of the card holder + #[schema(value_type = Option)] + pub nick_name: Option>, } #[derive(Clone, Debug, Deserialize, ToSchema, Serialize)] diff --git a/crates/router/src/core/payments/flows/authorize_flow.rs b/crates/router/src/core/payments/flows/authorize_flow.rs index c6de222f7d..c64912195e 100644 --- a/crates/router/src/core/payments/flows/authorize_flow.rs +++ b/crates/router/src/core/payments/flows/authorize_flow.rs @@ -103,6 +103,7 @@ impl Feature for types::PaymentsAu merchant_account, self.request.payment_method_type, key_store, + is_mandate, )) .await?; Ok(mandate::mandate_procedure( @@ -134,6 +135,7 @@ impl Feature for types::PaymentsAu &merchant_account, self.request.payment_method_type, &key_store, + is_mandate, )) .await; diff --git a/crates/router/src/core/payments/flows/setup_mandate_flow.rs b/crates/router/src/core/payments/flows/setup_mandate_flow.rs index 8b0b54158f..712184308d 100644 --- a/crates/router/src/core/payments/flows/setup_mandate_flow.rs +++ b/crates/router/src/core/payments/flows/setup_mandate_flow.rs @@ -76,6 +76,9 @@ impl Feature for types::Setup ) .await .to_setup_mandate_failed_response()?; + + let is_mandate = resp.request.setup_mandate_details.is_some(); + let pm_id = Box::pin(tokenization::save_payment_method( state, connector, @@ -84,6 +87,7 @@ impl Feature for types::Setup merchant_account, self.request.payment_method_type, key_store, + is_mandate, )) .await?; @@ -280,6 +284,8 @@ impl types::SetupMandateRouterData { let payment_method_type = self.request.payment_method_type; + let is_mandate = resp.request.setup_mandate_details.is_some(); + let pm_id = Box::pin(tokenization::save_payment_method( state, connector, @@ -288,6 +294,7 @@ impl types::SetupMandateRouterData { merchant_account, payment_method_type, key_store, + is_mandate, )) .await?; diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs index 97ff3a6c9c..8d37fc486c 100644 --- a/crates/router/src/core/payments/operations/payment_create.rs +++ b/crates/router/src/core/payments/operations/payment_create.rs @@ -8,7 +8,7 @@ use data_models::{ payments::payment_attempt::PaymentAttempt, }; use diesel_models::ephemeral_key; -use error_stack::{self, ResultExt}; +use error_stack::{self, report, ResultExt}; use masking::PeekInterface; use router_derive::PaymentOperation; use router_env::{instrument, tracing}; @@ -629,6 +629,17 @@ impl ValidateRequest ValidateRequest( state: &AppState, connector: &api::ConnectorData, @@ -30,6 +31,7 @@ pub async fn save_payment_method( merchant_account: &domain::MerchantAccount, payment_method_type: Option, key_store: &domain::MerchantKeyStore, + is_mandate: bool, ) -> RouterResult> where FData: mandate::MandateBehaviour, @@ -62,8 +64,16 @@ where } else { None }; + let future_usage_validation = resp + .request + .get_setup_future_usage() + .map(|future_usage| { + (future_usage == storage_enums::FutureUsage::OffSession && is_mandate) + || (future_usage == storage_enums::FutureUsage::OnSession && !is_mandate) + }) + .unwrap_or(false); - let pm_id = if resp.request.get_setup_future_usage().is_some() { + let pm_id = if future_usage_validation { let customer = maybe_customer.to_owned().get_required_value("customer")?; let payment_method_create_request = helpers::get_payment_method_create_request( Some(&resp.request.get_payment_method_data()), diff --git a/crates/router/src/types/api/mandates.rs b/crates/router/src/types/api/mandates.rs index f6b2d7bba9..051547dfa9 100644 --- a/crates/router/src/types/api/mandates.rs +++ b/crates/router/src/types/api/mandates.rs @@ -112,6 +112,7 @@ impl From for MandateCardDetails { card_issuer: card_details_from_locker.card_issuer, card_network: card_details_from_locker.card_network, card_type: card_details_from_locker.card_type, + nick_name: card_details_from_locker.nick_name, } .into() } diff --git a/openapi/openapi_spec.json b/openapi/openapi_spec.json index b6531771e1..2803141b38 100644 --- a/openapi/openapi_spec.json +++ b/openapi/openapi_spec.json @@ -9098,6 +9098,11 @@ "type": "string", "description": "The type of the payment card", "nullable": true + }, + "nick_name": { + "type": "string", + "description": "The nick_name of the card holder", + "nullable": true } } }, diff --git a/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario23- Update Amount/Payments - Confirm/request.json b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario23- Update Amount/Payments - Confirm/request.json index 4d4486b1d4..5b0c090f2b 100644 --- a/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario23- Update Amount/Payments - Confirm/request.json +++ b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario23- Update Amount/Payments - Confirm/request.json @@ -62,7 +62,7 @@ "card_cvc": "737" } }, - "setup_future_usage": "off_session", + "setup_future_usage": "on_session", "browser_info": { "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36", "accept_header": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8", @@ -79,14 +79,8 @@ }, "url": { "raw": "{{baseUrl}}/payments/:id/confirm", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "payments", - ":id", - "confirm" - ], + "host": ["{{baseUrl}}"], + "path": ["payments", ":id", "confirm"], "variable": [ { "key": "id",