mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-11-01 19:42:27 +08:00
feat(core): decide flow based on setup_future_usage (#3569)
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
@ -77,6 +77,9 @@ pub struct MandateCardDetails {
|
||||
pub card_network: Option<api_enums::CardNetwork>,
|
||||
/// The type of the payment card
|
||||
pub card_type: Option<String>,
|
||||
/// The nick_name of the card holder
|
||||
#[schema(value_type = Option<String>)]
|
||||
pub nick_name: Option<Secret<String>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, ToSchema, Serialize)]
|
||||
|
||||
@ -103,6 +103,7 @@ impl Feature<api::Authorize, types::PaymentsAuthorizeData> 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<api::Authorize, types::PaymentsAuthorizeData> for types::PaymentsAu
|
||||
&merchant_account,
|
||||
self.request.payment_method_type,
|
||||
&key_store,
|
||||
is_mandate,
|
||||
))
|
||||
.await;
|
||||
|
||||
|
||||
@ -76,6 +76,9 @@ impl Feature<api::SetupMandate, types::SetupMandateRequestData> 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<api::SetupMandate, types::SetupMandateRequestData> 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?;
|
||||
|
||||
|
||||
@ -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<F: Send + Clone, Ctx: PaymentMethodRetrieve> ValidateRequest<F, api::Paymen
|
||||
|
||||
helpers::validate_payment_method_fields_present(request)?;
|
||||
|
||||
if request.mandate_data.is_none()
|
||||
&& request
|
||||
.setup_future_usage
|
||||
.map(|fut_usage| fut_usage == enums::FutureUsage::OffSession)
|
||||
.unwrap_or(false)
|
||||
{
|
||||
Err(report!(errors::ApiErrorResponse::PreconditionFailed {
|
||||
message: "`setup_future_usage` cannot be `off_session` for normal payments".into()
|
||||
}))?
|
||||
}
|
||||
|
||||
let mandate_type =
|
||||
helpers::validate_mandate(request, payments::is_operation_confirm(self))?;
|
||||
|
||||
|
||||
@ -682,6 +682,17 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve> ValidateRequest<F, api::Paymen
|
||||
|
||||
helpers::validate_payment_method_fields_present(request)?;
|
||||
|
||||
if request.mandate_data.is_none()
|
||||
&& request
|
||||
.setup_future_usage
|
||||
.map(|fut_usage| fut_usage == storage_enums::FutureUsage::OffSession)
|
||||
.unwrap_or(false)
|
||||
{
|
||||
Err(report!(errors::ApiErrorResponse::PreconditionFailed {
|
||||
message: "`setup_future_usage` cannot be `off_session` for normal payments".into()
|
||||
}))?
|
||||
}
|
||||
|
||||
let mandate_type = helpers::validate_mandate(request, false)?;
|
||||
|
||||
Ok((
|
||||
|
||||
@ -22,6 +22,7 @@ use crate::{
|
||||
};
|
||||
|
||||
#[instrument(skip_all)]
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn save_payment_method<F: Clone, FData>(
|
||||
state: &AppState,
|
||||
connector: &api::ConnectorData,
|
||||
@ -30,6 +31,7 @@ pub async fn save_payment_method<F: Clone, FData>(
|
||||
merchant_account: &domain::MerchantAccount,
|
||||
payment_method_type: Option<storage_enums::PaymentMethodType>,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
is_mandate: bool,
|
||||
) -> RouterResult<Option<String>>
|
||||
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()),
|
||||
|
||||
@ -112,6 +112,7 @@ impl From<api::payment_methods::CardDetailFromLocker> 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()
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@ -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",
|
||||
|
||||
Reference in New Issue
Block a user