Skip to content

Commit 9cb3fa2

Browse files
authored
fix(mandate): make payment_method_data optional for mandate scenario (#1032)
1 parent 73b8988 commit 9cb3fa2

File tree

7 files changed

+49
-23
lines changed

7 files changed

+49
-23
lines changed

crates/api_models/src/payments.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,7 @@ pub enum PaymentMethodData {
520520
BankRedirect(BankRedirectData),
521521
BankDebit(BankDebitData),
522522
Crypto(CryptoData),
523+
MandatePayment,
523524
}
524525

525526
#[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
@@ -536,6 +537,7 @@ pub enum AdditionalPaymentData {
536537
PayLater {},
537538
Crypto {},
538539
BankDebit {},
540+
MandatePayment {},
539541
}
540542

541543
impl From<&PaymentMethodData> for AdditionalPaymentData {
@@ -561,6 +563,7 @@ impl From<&PaymentMethodData> for AdditionalPaymentData {
561563
PaymentMethodData::PayLater(_) => Self::PayLater {},
562564
PaymentMethodData::Crypto(_) => Self::Crypto {},
563565
PaymentMethodData::BankDebit(_) => Self::BankDebit {},
566+
PaymentMethodData::MandatePayment => Self::MandatePayment {},
564567
}
565568
}
566569
}
@@ -790,6 +793,7 @@ pub enum PaymentMethodDataResponse {
790793
BankRedirect(BankRedirectData),
791794
Crypto(CryptoData),
792795
BankDebit(BankDebitData),
796+
MandatePayment,
793797
}
794798

795799
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, ToSchema)]
@@ -1331,6 +1335,7 @@ impl From<PaymentMethodData> for PaymentMethodDataResponse {
13311335
}
13321336
PaymentMethodData::Crypto(crpto_data) => Self::Crypto(crpto_data),
13331337
PaymentMethodData::BankDebit(bank_debit_data) => Self::BankDebit(bank_debit_data),
1338+
PaymentMethodData::MandatePayment => Self::MandatePayment,
13341339
}
13351340
}
13361341
}

crates/router/src/connector/aci/transformers.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,9 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for AciPaymentsRequest {
184184
))?,
185185
}
186186
}
187-
api::PaymentMethodData::Crypto(_) | api::PaymentMethodData::BankDebit(_) => {
187+
api::PaymentMethodData::Crypto(_)
188+
| api::PaymentMethodData::BankDebit(_)
189+
| api::PaymentMethodData::MandatePayment => {
188190
Err(errors::ConnectorError::NotSupported {
189191
message: format!("{:?}", item.payment_method),
190192
connector: "Aci",

crates/router/src/connector/authorizedotnet/transformers.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,9 @@ fn get_pm_and_subsequent_auth_detail(
129129
api::PaymentMethodData::BankRedirect(_) => {
130130
Ok((PaymentDetails::BankRedirect, None, None))
131131
}
132-
api::PaymentMethodData::Crypto(_) | api::PaymentMethodData::BankDebit(_) => {
132+
api::PaymentMethodData::Crypto(_)
133+
| api::PaymentMethodData::BankDebit(_)
134+
| api::PaymentMethodData::MandatePayment => {
133135
Err(errors::ConnectorError::NotSupported {
134136
message: format!("{:?}", item.request.payment_method_data),
135137
connector: "AuthorizeDotNet",

crates/router/src/connector/stripe/transformers.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1864,11 +1864,14 @@ impl
18641864
bank_specific_data: bank_data,
18651865
}))
18661866
}
1867-
api::PaymentMethodData::Crypto(_) => Err(errors::ConnectorError::NotSupported {
1868-
message: format!("{pm_type:?}"),
1869-
connector: "Stripe",
1870-
payment_experience: api_models::enums::PaymentExperience::RedirectToUrl.to_string(),
1871-
})?,
1867+
api::PaymentMethodData::MandatePayment | api::PaymentMethodData::Crypto(_) => {
1868+
Err(errors::ConnectorError::NotSupported {
1869+
message: format!("{pm_type:?}"),
1870+
connector: "Stripe",
1871+
payment_experience: api_models::enums::PaymentExperience::RedirectToUrl
1872+
.to_string(),
1873+
})?
1874+
}
18721875
}
18731876
}
18741877
}

crates/router/src/core/payments.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,9 @@ where
721721
let connector = payment_data.payment_attempt.connector.to_owned();
722722

723723
let payment_data_and_tokenization_action = match connector {
724+
Some(_) if payment_data.mandate_id.is_some() => {
725+
(payment_data, TokenizationAction::SkipConnectorTokenization)
726+
}
724727
Some(connector) if is_operation_confirm(&operation) => {
725728
let payment_method = &payment_data
726729
.payment_attempt

crates/router/src/core/payments/helpers.rs

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -182,20 +182,25 @@ pub async fn get_token_for_recurring_mandate(
182182
.locker_id
183183
.to_owned()
184184
.get_required_value("locker_id")?;
185-
let _ = cards::get_lookup_key_from_locker(state, &token, &payment_method, &locker_id).await?;
186-
187-
if let Some(payment_method_from_request) = req.payment_method {
188-
let pm: storage_enums::PaymentMethod = payment_method_from_request.foreign_into();
189-
if pm != payment_method.payment_method {
190-
Err(report!(errors::ApiErrorResponse::PreconditionFailed {
191-
message: "payment method in request does not match previously provided payment \
192-
method information"
193-
.into()
194-
}))?
195-
}
196-
};
185+
if let storage_models::enums::PaymentMethod::Card = payment_method.payment_method {
186+
let _ =
187+
cards::get_lookup_key_from_locker(state, &token, &payment_method, &locker_id).await?;
188+
if let Some(payment_method_from_request) = req.payment_method {
189+
let pm: storage_enums::PaymentMethod = payment_method_from_request.foreign_into();
190+
if pm != payment_method.payment_method {
191+
Err(report!(errors::ApiErrorResponse::PreconditionFailed {
192+
message:
193+
"payment method in request does not match previously provided payment \
194+
method information"
195+
.into()
196+
}))?
197+
}
198+
};
197199

198-
Ok((Some(token), Some(payment_method.payment_method)))
200+
Ok((Some(token), Some(payment_method.payment_method)))
201+
} else {
202+
Ok((None, Some(payment_method.payment_method)))
203+
}
199204
}
200205

201206
#[instrument(skip_all)]

crates/router/src/core/payments/transformers.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -520,10 +520,16 @@ impl<F: Clone> TryFrom<PaymentAdditionalData<'_, F>> for types::PaymentsAuthoriz
520520
payment_data.creds_identifier.as_deref(),
521521
));
522522

523+
// payment_method_data is not required during recurring mandate payment, in such case keep default PaymentMethodData as MandatePayment
524+
let payment_method_data = payment_data.payment_method_data.or_else(|| {
525+
if payment_data.mandate_id.is_some() {
526+
Some(api_models::payments::PaymentMethodData::MandatePayment)
527+
} else {
528+
None
529+
}
530+
});
523531
Ok(Self {
524-
payment_method_data: payment_data
525-
.payment_method_data
526-
.get_required_value("payment_method_data")?,
532+
payment_method_data: payment_method_data.get_required_value("payment_method_data")?,
527533
setup_future_usage: payment_data.payment_intent.setup_future_usage,
528534
mandate_id: payment_data.mandate_id.clone(),
529535
off_session: payment_data.mandate_id.as_ref().map(|_| true),

0 commit comments

Comments
 (0)