From 4567aebccf2bb12b5097c8c0a050b75b597d53d2 Mon Sep 17 00:00:00 2001 From: Deepanshu Bansal Date: Tue, 15 Jul 2025 17:01:48 +0530 Subject: [PATCH 1/6] feat(connector): [NMI] Add mandates flow --- .../src/connectors/nmi.rs | 12 +- .../src/connectors/nmi/transformers.rs | 117 ++++++++++++++---- 2 files changed, 101 insertions(+), 28 deletions(-) diff --git a/crates/hyperswitch_connectors/src/connectors/nmi.rs b/crates/hyperswitch_connectors/src/connectors/nmi.rs index b2037c45256..7d040c30215 100644 --- a/crates/hyperswitch_connectors/src/connectors/nmi.rs +++ b/crates/hyperswitch_connectors/src/connectors/nmi.rs @@ -48,7 +48,7 @@ use transformers as nmi; use crate::{ types::ResponseRouterData, - utils::{construct_not_supported_error_report, convert_amount, get_header_key_value}, + utils::{self, construct_not_supported_error_report, convert_amount, get_header_key_value}, }; #[derive(Clone)] @@ -161,6 +161,16 @@ impl ConnectorValidation for Nmi { // in case we dont have transaction id, we can make psync using attempt id Ok(()) } + + fn validate_mandate_payment( + &self, + pm_type: Option, + pm_data: hyperswitch_domain_models::payment_method_data::PaymentMethodData, + ) -> CustomResult<(), ConnectorError> { + let mandate_supported_pmd = + std::collections::HashSet::from([utils::PaymentMethodDataType::Card]); + utils::is_mandate_supported(pm_data, pm_type, mandate_supported_pmd, self.id()) + } } impl ConnectorIntegration diff --git a/crates/hyperswitch_connectors/src/connectors/nmi/transformers.rs b/crates/hyperswitch_connectors/src/connectors/nmi/transformers.rs index f235e553795..eac9bc1ea93 100644 --- a/crates/hyperswitch_connectors/src/connectors/nmi/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/nmi/transformers.rs @@ -1,8 +1,6 @@ use api_models::webhooks::IncomingWebhookEvent; use cards::CardNumber; -use common_enums::{ - AttemptStatus, AuthenticationType, CaptureMethod, CountryAlpha2, Currency, RefundStatus, -}; +use common_enums::{AttemptStatus, AuthenticationType, CountryAlpha2, Currency, RefundStatus}; use common_utils::{errors::CustomResult, ext_traits::XmlExt, pii::Email, types::FloatMajorUnit}; use error_stack::{report, Report, ResultExt}; use hyperswitch_domain_models::{ @@ -384,7 +382,7 @@ impl incremental_authorization_allowed: None, charges: None, }), - if let Some(CaptureMethod::Automatic) = item.data.request.capture_method { + if item.data.request.is_auto_capture()? { AttemptStatus::CaptureInitiated } else { AttemptStatus::Authorizing @@ -429,6 +427,8 @@ pub struct NmiPaymentsRequest { #[serde(flatten)] merchant_defined_field: Option, orderid: String, + #[serde(skip_serializing_if = "Option::is_none")] + customer_vault: Option, } #[derive(Debug, Serialize)] @@ -462,6 +462,12 @@ pub enum PaymentMethod { CardThreeDs(Box), GPay(Box), ApplePay(Box), + MandatePayment(Box), +} + +#[derive(Debug, Serialize)] +pub struct MandatePayment { + customer_vault_id: Secret, } #[derive(Debug, Serialize)] @@ -503,25 +509,70 @@ impl TryFrom<&NmiRouterData<&PaymentsAuthorizeRouterData>> for NmiPaymentsReques }; let auth_type: NmiAuthType = (&item.router_data.connector_auth_type).try_into()?; let amount = item.amount; - let payment_method = PaymentMethod::try_from(( - &item.router_data.request.payment_method_data, - Some(item.router_data), - ))?; - Ok(Self { - transaction_type, - security_key: auth_type.api_key, - amount, - currency: item.router_data.request.currency, - payment_method, - merchant_defined_field: item - .router_data - .request - .metadata - .as_ref() - .map(NmiMerchantDefinedField::new), - orderid: item.router_data.connector_request_reference_id.clone(), - }) + match item + .router_data + .request + .mandate_id + .clone() + .and_then(|mandate_ids| mandate_ids.mandate_reference_id) + { + Some(api_models::payments::MandateReferenceId::ConnectorMandateId( + connector_mandate_id, + )) => Ok(Self { + transaction_type, + security_key: auth_type.api_key, + amount, + currency: item.router_data.request.currency, + payment_method: PaymentMethod::MandatePayment(Box::new(MandatePayment { + customer_vault_id: Secret::new( + connector_mandate_id + .get_connector_mandate_id() + .ok_or(ConnectorError::MissingConnectorMandateID)?, + ), + })), + merchant_defined_field: item + .router_data + .request + .metadata + .as_ref() + .map(NmiMerchantDefinedField::new), + orderid: item.router_data.connector_request_reference_id.clone(), + customer_vault: None, + }), + Some(api_models::payments::MandateReferenceId::NetworkMandateId(_)) + | Some(api_models::payments::MandateReferenceId::NetworkTokenWithNTI(_)) => { + Err(ConnectorError::NotImplemented( + get_unimplemented_payment_method_error_message("nmi"), + ))? + } + None => { + let payment_method = PaymentMethod::try_from(( + &item.router_data.request.payment_method_data, + Some(item.router_data), + ))?; + + Ok(Self { + transaction_type, + security_key: auth_type.api_key, + amount, + currency: item.router_data.request.currency, + payment_method, + merchant_defined_field: item + .router_data + .request + .metadata + .as_ref() + .map(NmiMerchantDefinedField::new), + orderid: item.router_data.connector_request_reference_id.clone(), + customer_vault: item + .router_data + .request + .is_mandate_payment() + .then(|| CustomerAction::AddCustomer), + }) + } + } } } @@ -674,6 +725,7 @@ impl TryFrom<&SetupMandateRouterData> for NmiPaymentsRequest { payment_method, merchant_defined_field: None, orderid: item.connector_request_reference_id.clone(), + customer_vault: Some(CustomerAction::AddCustomer), }) } } @@ -745,7 +797,7 @@ impl incremental_authorization_allowed: None, charges: None, }), - AttemptStatus::CaptureInitiated, + AttemptStatus::Charged, ), Response::Declined | Response::Error => ( Err(get_standard_error_response(item.response, item.http_code)), @@ -826,6 +878,7 @@ pub struct StandardResponse { pub cvvresponse: Option, pub orderid: String, pub response_code: String, + pub customer_vault_id: Option>, } impl TryFrom> @@ -896,15 +949,25 @@ impl TryFrom> item.response.transactionid.clone(), ), redirection_data: Box::new(None), - mandate_reference: Box::new(None), + mandate_reference: match item.response.customer_vault_id { + Some(vault_id) => Box::new(Some( + hyperswitch_domain_models::router_response_types::MandateReference { + connector_mandate_id: Some(vault_id.expose()), + payment_method_id: None, + mandate_metadata: None, + connector_mandate_request_reference_id: None, + }, + )), + None => Box::new(None), + }, connector_metadata: None, network_txn_id: None, connector_response_reference_id: Some(item.response.orderid), incremental_authorization_allowed: None, charges: None, }), - if let Some(CaptureMethod::Automatic) = item.data.request.capture_method { - AttemptStatus::CaptureInitiated + if item.data.request.is_auto_capture()? { + AttemptStatus::Charged } else { AttemptStatus::Authorized }, @@ -1093,7 +1156,7 @@ impl TryFrom> for RefundsRo impl From for RefundStatus { fn from(item: Response) -> Self { match item { - Response::Approved => Self::Pending, + Response::Approved => Self::Success, Response::Declined | Response::Error => Self::Failure, } } From 37bda5524536f07e71cb09fb89620589f65f6f70 Mon Sep 17 00:00:00 2001 From: Deepanshu Bansal Date: Fri, 1 Aug 2025 17:13:57 +0530 Subject: [PATCH 2/6] feat(connector): [NMI] Add setup mandate flow --- .../src/connectors/nmi.rs | 28 ++++---- .../src/connectors/nmi/transformers.rs | 67 ++++++++++++++----- 2 files changed, 64 insertions(+), 31 deletions(-) diff --git a/crates/hyperswitch_connectors/src/connectors/nmi.rs b/crates/hyperswitch_connectors/src/connectors/nmi.rs index 7d040c30215..7ae21664e73 100644 --- a/crates/hyperswitch_connectors/src/connectors/nmi.rs +++ b/crates/hyperswitch_connectors/src/connectors/nmi.rs @@ -38,7 +38,7 @@ use hyperswitch_interfaces::{ types::{ PaymentsAuthorizeType, PaymentsCaptureType, PaymentsCompleteAuthorizeType, PaymentsPreProcessingType, PaymentsSyncType, PaymentsVoidType, RefundExecuteType, - RefundSyncType, Response, + RefundSyncType, Response, SetupMandateType, }, webhooks::{IncomingWebhook, IncomingWebhookRequestDetails}, }; @@ -204,27 +204,23 @@ impl ConnectorIntegration CustomResult { - let connector_req = nmi::NmiPaymentsRequest::try_from(req)?; + let connector_req = nmi::NmiValidateRequest::try_from(req)?; Ok(RequestContent::FormUrlEncoded(Box::new(connector_req))) } fn build_request( &self, - _req: &SetupMandateRouterData, - _connectors: &Connectors, + req: &SetupMandateRouterData, + connectors: &Connectors, ) -> CustomResult, ConnectorError> { - Err(ConnectorError::NotImplemented("Setup Mandate flow for Nmi".to_string()).into()) - - // Ok(Some( - // RequestBuilder::new() - // .method(Method::Post) - // .url(&SetupMandateType::get_url(self, req, connectors)?) - // .headers(SetupMandateType::get_headers(self, req, connectors)?) - // .set_body(SetupMandateType::get_request_body( - // self, req, connectors, - // )?) - // .build(), - // )) + Ok(Some( + RequestBuilder::new() + .method(Method::Post) + .url(&SetupMandateType::get_url(self, req, connectors)?) + .headers(SetupMandateType::get_headers(self, req, connectors)?) + .set_body(SetupMandateType::get_request_body(self, req, connectors)?) + .build(), + )) } fn handle_response( diff --git a/crates/hyperswitch_connectors/src/connectors/nmi/transformers.rs b/crates/hyperswitch_connectors/src/connectors/nmi/transformers.rs index eac9bc1ea93..dd0c8012224 100644 --- a/crates/hyperswitch_connectors/src/connectors/nmi/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/nmi/transformers.rs @@ -415,6 +415,18 @@ fn get_nmi_error_response(response: NmiCompleteResponse, http_code: u16) -> Erro } } +#[derive(Debug, Serialize)] +pub struct NmiValidateRequest { + #[serde(rename = "type")] + transaction_type: TransactionType, + security_key: Secret, + ccnumber: CardNumber, + ccexp: Secret, + cvv: Secret, + orderid: String, + customer_vault: CustomerAction, +} + #[derive(Debug, Serialize)] pub struct NmiPaymentsRequest { #[serde(rename = "type")] @@ -569,7 +581,7 @@ impl TryFrom<&NmiRouterData<&PaymentsAuthorizeRouterData>> for NmiPaymentsReques .router_data .request .is_mandate_payment() - .then(|| CustomerAction::AddCustomer), + .then_some(CustomerAction::AddCustomer), }) } } @@ -712,21 +724,36 @@ impl From<&ApplePayWalletData> for PaymentMethod { } } -impl TryFrom<&SetupMandateRouterData> for NmiPaymentsRequest { +impl TryFrom<&SetupMandateRouterData> for NmiValidateRequest { type Error = Error; fn try_from(item: &SetupMandateRouterData) -> Result { - let auth_type: NmiAuthType = (&item.connector_auth_type).try_into()?; - let payment_method = PaymentMethod::try_from((&item.request.payment_method_data, None))?; - Ok(Self { - transaction_type: TransactionType::Validate, - security_key: auth_type.api_key, - amount: FloatMajorUnit::zero(), - currency: item.request.currency, - payment_method, - merchant_defined_field: None, - orderid: item.connector_request_reference_id.clone(), - customer_vault: Some(CustomerAction::AddCustomer), - }) + match item.request.amount { + Some(amount) if amount > 0 => Err(ConnectorError::FlowNotSupported { + flow: "Setup Mandate with non zero amount".to_string(), + connector: "NMI".to_string(), + } + .into()), + _ => { + if let PaymentMethodData::Card(card_details) = &item.request.payment_method_data { + let auth_type: NmiAuthType = (&item.connector_auth_type).try_into()?; + Ok(Self { + transaction_type: TransactionType::Validate, + security_key: auth_type.api_key, + ccnumber: card_details.card_number.clone(), + ccexp: card_details + .get_card_expiry_month_year_2_digit_with_delimiter("".to_string())?, + cvv: card_details.card_cvc.clone(), + orderid: item.connector_request_reference_id.clone(), + customer_vault: CustomerAction::AddCustomer, + }) + } else { + Err(ConnectorError::NotImplemented( + get_unimplemented_payment_method_error_message("Nmi"), + ) + .into()) + } + } + } } } @@ -895,7 +922,17 @@ impl TryFrom Box::new(Some( + hyperswitch_domain_models::router_response_types::MandateReference { + connector_mandate_id: Some(vault_id.expose()), + payment_method_id: None, + mandate_metadata: None, + connector_mandate_request_reference_id: None, + }, + )), + None => Box::new(None), + }, connector_metadata: None, network_txn_id: None, connector_response_reference_id: Some(item.response.orderid), From fb44bb9b6e6d51bd7eb76a8fbd66ab04b4d9cebe Mon Sep 17 00:00:00 2001 From: Deepanshu Bansal Date: Fri, 1 Aug 2025 17:42:53 +0530 Subject: [PATCH 3/6] feat(connector): [NMI] Update cypress tests --- .../cypress/e2e/configs/Payment/Nmi.js | 41 ++++++++----------- 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/cypress-tests/cypress/e2e/configs/Payment/Nmi.js b/cypress-tests/cypress/e2e/configs/Payment/Nmi.js index de8a1a5f77b..a3a4a202037 100644 --- a/cypress-tests/cypress/e2e/configs/Payment/Nmi.js +++ b/cypress-tests/cypress/e2e/configs/Payment/Nmi.js @@ -83,7 +83,7 @@ export const connectorDetails = { Response: { status: 200, body: { - status: "processing", + status: "succeeded", shipping_cost: 50, amount: 6000, }, @@ -149,7 +149,7 @@ export const connectorDetails = { Response: { status: 200, body: { - status: "processing", + status: "succeeded", }, }, }, @@ -160,9 +160,9 @@ export const connectorDetails = { Response: { status: 200, body: { - status: "processing", + status: "succeeded", amount: 6000, - amount_capturable: 6000, + amount_capturable: 0, }, }, }, @@ -173,9 +173,9 @@ export const connectorDetails = { Response: { status: 200, body: { - status: "processing", + status: "partially_captured", amount: 6000, - amount_capturable: 6000, + amount_capturable: 0, }, }, }, @@ -209,7 +209,7 @@ export const connectorDetails = { Response: { status: 200, body: { - status: "pending", + status: "succeeded", }, }, }, @@ -220,7 +220,7 @@ export const connectorDetails = { Response: { status: 200, body: { - status: "pending", + status: "succeeded", }, }, }, @@ -231,7 +231,7 @@ export const connectorDetails = { Response: { status: 200, body: { - status: "pending", + status: "succeeded", }, }, }, @@ -242,7 +242,7 @@ export const connectorDetails = { Response: { status: 200, body: { - status: "pending", + status: "succeeded", }, }, }, @@ -256,13 +256,9 @@ export const connectorDetails = { }, ZeroAuthMandate: { Response: { - status: 501, + status: 200, body: { - error: { - type: "invalid_request", - message: "Setup Mandate flow for Nmi is not implemented", - code: "IR_00", - }, + status: "succeeded", }, }, }, @@ -289,13 +285,10 @@ export const connectorDetails = { }, }, Response: { - status: 501, + status: 200, body: { - error: { - type: "invalid_request", - message: "Setup Mandate flow for Nmi is not implemented", - code: "IR_00", - }, + status: "succeeded", + setup_future_usage: "off_session", }, }, }, @@ -311,7 +304,7 @@ export const connectorDetails = { Response: { status: 200, body: { - status: "processing", + status: "succeeded", }, }, }, @@ -462,7 +455,7 @@ export const connectorDetails = { Response: { status: 200, body: { - status: "processing", + status: "succeeded", }, }, }, From 44bed1ef2a271485623cf03b849bb8c75ad45f91 Mon Sep 17 00:00:00 2001 From: Deepanshu Bansal Date: Mon, 4 Aug 2025 19:02:10 +0530 Subject: [PATCH 4/6] chore: fix cypress --- .../cypress/e2e/configs/Payment/Nmi.js | 42 ++++++++++++++++++- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/cypress-tests/cypress/e2e/configs/Payment/Nmi.js b/cypress-tests/cypress/e2e/configs/Payment/Nmi.js index a3a4a202037..98b067aa11a 100644 --- a/cypress-tests/cypress/e2e/configs/Payment/Nmi.js +++ b/cypress-tests/cypress/e2e/configs/Payment/Nmi.js @@ -1,6 +1,6 @@ const successfulNo3DSCardDetails = { - card_number: "4000000000002503", - card_exp_month: "08", + card_number: "4532111111111112", + card_exp_month: "10", card_exp_year: "50", card_holder_name: "joseph Doe", card_cvc: "999", @@ -255,6 +255,14 @@ export const connectorDetails = { }, }, ZeroAuthMandate: { + Request: { + payment_type: "setup_mandate", + payment_method: "card", + setup_future_usage: "off_session", + payment_method_data: { + card: successfulNo3DSCardDetails, + }, + }, Response: { status: 200, body: { @@ -280,6 +288,7 @@ export const connectorDetails = { Request: { payment_type: "setup_mandate", payment_method: "card", + payment_method_type: "credit", payment_method_data: { card: successfulNo3DSCardDetails, }, @@ -558,5 +567,34 @@ export const connectorDetails = { }, }, }, + PaymentIntentOffSession: { + Request: { + amount: 6000, + authentication_type: "no_three_ds", + currency: "USD", + customer_acceptance: null, + setup_future_usage: "off_session", + }, + Response: { + status: 200, + body: { + status: "requires_payment_method", + }, + }, + }, + SaveCardConfirmAutoCaptureOffSession: { + Request: { + setup_future_usage: "off_session", + payment_method_data: { + card: successfulNo3DSCardDetails, + }, + }, + Response: { + status: 200, + body: { + status: "succeeded", + }, + }, + }, }, }; From bbc63d2e0667e899747acf5075beb451032a7dc4 Mon Sep 17 00:00:00 2001 From: Deepanshu Bansal Date: Tue, 5 Aug 2025 14:11:10 +0530 Subject: [PATCH 5/6] chore: Update 3DS Cypress --- .../src/connectors/nmi/transformers.rs | 17 +- .../cypress/e2e/configs/Payment/Nmi.js | 156 ++++++++++++++---- 2 files changed, 142 insertions(+), 31 deletions(-) diff --git a/crates/hyperswitch_connectors/src/connectors/nmi/transformers.rs b/crates/hyperswitch_connectors/src/connectors/nmi/transformers.rs index c1c432a5b27..32436f307af 100644 --- a/crates/hyperswitch_connectors/src/connectors/nmi/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/nmi/transformers.rs @@ -349,6 +349,7 @@ pub struct NmiCompleteResponse { pub cvvresponse: Option, pub orderid: String, pub response_code: String, + customer_vault_id: Option>, } impl @@ -375,7 +376,17 @@ impl Ok(PaymentsResponseData::TransactionResponse { resource_id: ResponseId::ConnectorTransactionId(item.response.transactionid), redirection_data: Box::new(None), - mandate_reference: Box::new(None), + mandate_reference: match item.response.customer_vault_id { + Some(vault_id) => Box::new(Some( + hyperswitch_domain_models::router_response_types::MandateReference { + connector_mandate_id: Some(vault_id.expose()), + payment_method_id: None, + mandate_metadata: None, + connector_mandate_request_reference_id: None, + }, + )), + None => Box::new(None), + }, connector_metadata: None, network_txn_id: None, connector_response_reference_id: Some(item.response.orderid), @@ -383,9 +394,9 @@ impl charges: None, }), if item.data.request.is_auto_capture()? { - AttemptStatus::CaptureInitiated + AttemptStatus::Charged } else { - AttemptStatus::Authorizing + AttemptStatus::Authorized }, ), Response::Declined | Response::Error => ( diff --git a/cypress-tests/cypress/e2e/configs/Payment/Nmi.js b/cypress-tests/cypress/e2e/configs/Payment/Nmi.js index 98b067aa11a..006925d13c2 100644 --- a/cypress-tests/cypress/e2e/configs/Payment/Nmi.js +++ b/cypress-tests/cypress/e2e/configs/Payment/Nmi.js @@ -153,6 +153,15 @@ export const connectorDetails = { }, }, }, + MITManualCapture: { + Request: {}, + Response: { + status: 200, + body: { + status: "requires_capture", + }, + }, + }, Capture: { Request: { amount_to_capture: 6000, @@ -487,10 +496,36 @@ export const connectorDetails = { }, }, }, - PaymentMethodIdMandateNo3DSAutoCapture: { - Configs: { - TRIGGER_SKIP: true, + PaymentIntentOffSession: { + Request: { + amount: 6000, + authentication_type: "no_three_ds", + currency: "USD", + customer_acceptance: null, + setup_future_usage: "off_session", + }, + Response: { + status: 200, + body: { + status: "requires_payment_method", + }, + }, + }, + SaveCardConfirmAutoCaptureOffSession: { + Request: { + setup_future_usage: "off_session", + payment_method_data: { + card: successfulNo3DSCardDetails, + }, + }, + Response: { + status: 200, + body: { + status: "succeeded", + }, }, + }, + PaymentMethodIdMandateNo3DSAutoCapture: { Request: { payment_method: "card", payment_method_data: { @@ -507,38 +542,43 @@ export const connectorDetails = { }, }, }, - PaymentMethodIdMandateNo3DSManualCapture: { + SaveCardUseNo3DSAutoCaptureOffSession: { Configs: { - TRIGGER_SKIP: true, + CONNECTOR_CREDENTIAL: { + specName: ["connectorAgnosticNTID"], + value: "connector_2", + }, }, Request: { payment_method: "card", + payment_method_type: "debit", payment_method_data: { card: successfulNo3DSCardDetails, }, - currency: "USD", - mandate_data: null, + setup_future_usage: "off_session", customer_acceptance: customerAcceptance, }, Response: { status: 200, body: { - status: "requires_capture", + status: "succeeded", }, }, }, - PaymentMethodIdMandate3DSAutoCapture: { + SaveCardUse3DSAutoCaptureOffSession: { Configs: { - // Skipping redirection here for mandate 3ds auto capture as it requires changes from the core - TRIGGER_SKIP: true, + CONNECTOR_CREDENTIAL: { + specName: ["connectorAgnosticNTID"], + value: "connector_2", + }, }, Request: { payment_method: "card", + payment_method_type: "debit", payment_method_data: { card: successfulThreeDSTestCardDetails, }, - mandate_data: null, - authentication_type: "three_ds", + setup_future_usage: "off_session", customer_acceptance: customerAcceptance, }, Response: { @@ -548,51 +588,111 @@ export const connectorDetails = { }, }, }, - PaymentMethodIdMandate3DSManualCapture: { + SaveCardUseNo3DSManualCaptureOffSession: { + Request: { + payment_method: "card", + payment_method_data: { + card: successfulNo3DSCardDetails, + }, + setup_future_usage: "off_session", + customer_acceptance: customerAcceptance, + }, + Response: { + status: 200, + body: { + status: "requires_capture", + }, + }, + }, + SaveCardConfirmAutoCaptureOffSession: { Configs: { - TRIGGER_SKIP: true, + CONNECTOR_CREDENTIAL: { + specName: ["connectorAgnosticNTID"], + value: "connector_2", + }, + }, + Request: { + setup_future_usage: "off_session", + }, + Response: { + status: 200, + body: { + status: "succeeded", + }, + }, + }, + SaveCardConfirmManualCaptureOffSession: { + Request: { + setup_future_usage: "off_session", + }, + Response: { + status: 200, + body: { + status: "requires_capture", + }, + }, + }, + SaveCardConfirmAutoCaptureOffSessionWithoutBilling: { + Request: { + setup_future_usage: "off_session", + billing: null, + }, + Response: { + status: 200, + body: { + status: "succeeded", + }, }, + }, + PaymentMethodIdMandateNo3DSManualCapture: { Request: { + payment_method: "card", payment_method_data: { - card: successfulThreeDSTestCardDetails, + card: successfulNo3DSCardDetails, }, + currency: "USD", mandate_data: null, - authentication_type: "three_ds", customer_acceptance: customerAcceptance, }, Response: { status: 200, body: { - status: "requires_customer_action", + status: "requires_capture", }, }, }, - PaymentIntentOffSession: { + PaymentMethodIdMandate3DSAutoCapture: { Request: { - amount: 6000, - authentication_type: "no_three_ds", + payment_method: "card", + payment_method_data: { + card: successfulThreeDSTestCardDetails, + }, currency: "USD", - customer_acceptance: null, - setup_future_usage: "off_session", + mandate_data: null, + authentication_type: "three_ds", + customer_acceptance: customerAcceptance, }, Response: { status: 200, body: { - status: "requires_payment_method", + status: "requires_customer_action", }, }, }, - SaveCardConfirmAutoCaptureOffSession: { + PaymentMethodIdMandate3DSManualCapture: { Request: { - setup_future_usage: "off_session", + payment_method: "card", payment_method_data: { - card: successfulNo3DSCardDetails, + card: successfulThreeDSTestCardDetails, }, + mandate_data: null, + authentication_type: "three_ds", + customer_acceptance: customerAcceptance, }, Response: { status: 200, body: { - status: "succeeded", + status: "requires_customer_action", }, }, }, From 1e199c404ee379d3c9ad3f8a1bbd2eec1edff765 Mon Sep 17 00:00:00 2001 From: Deepanshu Bansal Date: Tue, 5 Aug 2025 14:57:53 +0530 Subject: [PATCH 6/6] chore: Update Cypress --- .../cypress/e2e/configs/Payment/Nmi.js | 56 ------------------- 1 file changed, 56 deletions(-) diff --git a/cypress-tests/cypress/e2e/configs/Payment/Nmi.js b/cypress-tests/cypress/e2e/configs/Payment/Nmi.js index 006925d13c2..db9f90f3d04 100644 --- a/cypress-tests/cypress/e2e/configs/Payment/Nmi.js +++ b/cypress-tests/cypress/e2e/configs/Payment/Nmi.js @@ -542,29 +542,6 @@ export const connectorDetails = { }, }, }, - SaveCardUseNo3DSAutoCaptureOffSession: { - Configs: { - CONNECTOR_CREDENTIAL: { - specName: ["connectorAgnosticNTID"], - value: "connector_2", - }, - }, - Request: { - payment_method: "card", - payment_method_type: "debit", - payment_method_data: { - card: successfulNo3DSCardDetails, - }, - setup_future_usage: "off_session", - customer_acceptance: customerAcceptance, - }, - Response: { - status: 200, - body: { - status: "succeeded", - }, - }, - }, SaveCardUse3DSAutoCaptureOffSession: { Configs: { CONNECTOR_CREDENTIAL: { @@ -588,39 +565,6 @@ export const connectorDetails = { }, }, }, - SaveCardUseNo3DSManualCaptureOffSession: { - Request: { - payment_method: "card", - payment_method_data: { - card: successfulNo3DSCardDetails, - }, - setup_future_usage: "off_session", - customer_acceptance: customerAcceptance, - }, - Response: { - status: 200, - body: { - status: "requires_capture", - }, - }, - }, - SaveCardConfirmAutoCaptureOffSession: { - Configs: { - CONNECTOR_CREDENTIAL: { - specName: ["connectorAgnosticNTID"], - value: "connector_2", - }, - }, - Request: { - setup_future_usage: "off_session", - }, - Response: { - status: 200, - body: { - status: "succeeded", - }, - }, - }, SaveCardConfirmManualCaptureOffSession: { Request: { setup_future_usage: "off_session",