mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-30 01:27:31 +08:00
feat(router): add NTID flow for cybersource (#4193)
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
@ -297,6 +297,7 @@ pub struct CybersourceAuthorizationOptions {
|
|||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct MerchantInitiatedTransaction {
|
pub struct MerchantInitiatedTransaction {
|
||||||
reason: Option<String>,
|
reason: Option<String>,
|
||||||
|
previous_transaction_id: Option<Secret<String>>,
|
||||||
//Required for recurring mandates payment
|
//Required for recurring mandates payment
|
||||||
original_authorized_amount: Option<String>,
|
original_authorized_amount: Option<String>,
|
||||||
}
|
}
|
||||||
@ -314,6 +315,7 @@ pub struct CybersourcePaymentInitiator {
|
|||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub enum CybersourcePaymentInitiatorTypes {
|
pub enum CybersourcePaymentInitiatorTypes {
|
||||||
Customer,
|
Customer,
|
||||||
|
Merchant,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
@ -503,6 +505,24 @@ impl
|
|||||||
Option<String>,
|
Option<String>,
|
||||||
),
|
),
|
||||||
) -> Result<Self, Self::Error> {
|
) -> Result<Self, Self::Error> {
|
||||||
|
let mut commerce_indicator = solution
|
||||||
|
.as_ref()
|
||||||
|
.map(|pm_solution| match pm_solution {
|
||||||
|
PaymentSolution::ApplePay => network
|
||||||
|
.as_ref()
|
||||||
|
.map(|card_network| match card_network.to_lowercase().as_str() {
|
||||||
|
"amex" => "aesk",
|
||||||
|
"discover" => "dipb",
|
||||||
|
"mastercard" => "spa",
|
||||||
|
"visa" => "internet",
|
||||||
|
_ => "internet",
|
||||||
|
})
|
||||||
|
.unwrap_or("internet"),
|
||||||
|
PaymentSolution::GooglePay => "internet",
|
||||||
|
})
|
||||||
|
.unwrap_or("internet")
|
||||||
|
.to_string();
|
||||||
|
|
||||||
let (action_list, action_token_types, authorization_options) = if item
|
let (action_list, action_token_types, authorization_options) = if item
|
||||||
.router_data
|
.router_data
|
||||||
.request
|
.request
|
||||||
@ -531,7 +551,15 @@ impl
|
|||||||
merchant_intitiated_transaction: None,
|
merchant_intitiated_transaction: None,
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
} else if item.router_data.request.connector_mandate_id().is_some() {
|
} else if item.router_data.request.mandate_id.is_some() {
|
||||||
|
match item
|
||||||
|
.router_data
|
||||||
|
.request
|
||||||
|
.mandate_id
|
||||||
|
.clone()
|
||||||
|
.and_then(|mandate_id| mandate_id.mandate_reference_id)
|
||||||
|
{
|
||||||
|
Some(api_models::payments::MandateReferenceId::ConnectorMandateId(_)) => {
|
||||||
let original_amount = item
|
let original_amount = item
|
||||||
.router_data
|
.router_data
|
||||||
.get_recurring_mandate_payment_data()?
|
.get_recurring_mandate_payment_data()?
|
||||||
@ -552,23 +580,84 @@ impl
|
|||||||
original_amount,
|
original_amount,
|
||||||
original_currency,
|
original_currency,
|
||||||
)?),
|
)?),
|
||||||
|
previous_transaction_id: None,
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
Some(api_models::payments::MandateReferenceId::NetworkMandateId(
|
||||||
|
network_transaction_id,
|
||||||
|
)) => {
|
||||||
|
let (original_amount, original_currency) = match network
|
||||||
|
.clone()
|
||||||
|
.map(|network| network.to_lowercase())
|
||||||
|
.as_deref()
|
||||||
|
{
|
||||||
|
Some("discover") => {
|
||||||
|
let original_amount = Some(
|
||||||
|
item.router_data
|
||||||
|
.get_recurring_mandate_payment_data()?
|
||||||
|
.get_original_payment_amount()?,
|
||||||
|
);
|
||||||
|
let original_currency = Some(
|
||||||
|
item.router_data
|
||||||
|
.get_recurring_mandate_payment_data()?
|
||||||
|
.get_original_payment_currency()?,
|
||||||
|
);
|
||||||
|
(original_amount, original_currency)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let original_amount = item
|
||||||
|
.router_data
|
||||||
|
.recurring_mandate_payment_data
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|recurring_mandate_payment_data| {
|
||||||
|
recurring_mandate_payment_data
|
||||||
|
.original_payment_authorized_amount
|
||||||
|
});
|
||||||
|
|
||||||
|
let original_currency = item
|
||||||
|
.router_data
|
||||||
|
.recurring_mandate_payment_data
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|recurring_mandate_payment_data| {
|
||||||
|
recurring_mandate_payment_data
|
||||||
|
.original_payment_authorized_currency
|
||||||
|
});
|
||||||
|
|
||||||
|
(original_amount, original_currency)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let original_authorized_amount = match (original_amount, original_currency) {
|
||||||
|
(Some(original_amount), Some(original_currency)) => Some(
|
||||||
|
utils::to_currency_base_unit(original_amount, original_currency)?,
|
||||||
|
),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
commerce_indicator = "recurring".to_string();
|
||||||
|
(
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
Some(CybersourceAuthorizationOptions {
|
||||||
|
initiator: Some(CybersourcePaymentInitiator {
|
||||||
|
initiator_type: Some(CybersourcePaymentInitiatorTypes::Merchant),
|
||||||
|
credential_stored_on_file: None,
|
||||||
|
stored_credential_used: Some(true),
|
||||||
|
}),
|
||||||
|
merchant_intitiated_transaction: Some(MerchantInitiatedTransaction {
|
||||||
|
reason: Some("7".to_string()),
|
||||||
|
original_authorized_amount,
|
||||||
|
previous_transaction_id: Some(Secret::new(network_transaction_id)),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
None => (None, None, None),
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
(None, None, None)
|
(None, None, None)
|
||||||
};
|
};
|
||||||
let commerce_indicator = match network {
|
|
||||||
Some(card_network) => match card_network.to_lowercase().as_str() {
|
|
||||||
"amex" => "aesk",
|
|
||||||
"discover" => "dipb",
|
|
||||||
"mastercard" => "spa",
|
|
||||||
"visa" => "internet",
|
|
||||||
_ => "internet",
|
|
||||||
},
|
|
||||||
None => "internet",
|
|
||||||
}
|
|
||||||
.to_string();
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
capture: Some(matches!(
|
capture: Some(matches!(
|
||||||
item.router_data.request.capture_method,
|
item.router_data.request.capture_method,
|
||||||
@ -754,11 +843,11 @@ impl
|
|||||||
expiration_month: ccard.card_exp_month,
|
expiration_month: ccard.card_exp_month,
|
||||||
expiration_year: ccard.card_exp_year,
|
expiration_year: ccard.card_exp_year,
|
||||||
security_code: ccard.card_cvc,
|
security_code: ccard.card_cvc,
|
||||||
card_type,
|
card_type: card_type.clone(),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
let processing_information = ProcessingInformation::try_from((item, None, None))?;
|
let processing_information = ProcessingInformation::try_from((item, None, card_type))?;
|
||||||
let client_reference_information = ClientReferenceInformation::from(item);
|
let client_reference_information = ClientReferenceInformation::from(item);
|
||||||
let merchant_defined_information =
|
let merchant_defined_information =
|
||||||
item.router_data.request.metadata.clone().map(|metadata| {
|
item.router_data.request.metadata.clone().map(|metadata| {
|
||||||
@ -1287,6 +1376,7 @@ impl TryFrom<&CybersourceRouterData<&types::PaymentsIncrementalAuthorizationRout
|
|||||||
}),
|
}),
|
||||||
merchant_intitiated_transaction: Some(MerchantInitiatedTransaction {
|
merchant_intitiated_transaction: Some(MerchantInitiatedTransaction {
|
||||||
reason: Some("5".to_owned()),
|
reason: Some("5".to_owned()),
|
||||||
|
previous_transaction_id: None,
|
||||||
original_authorized_amount: None,
|
original_authorized_amount: None,
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
@ -1537,6 +1627,7 @@ pub struct ClientReferenceInformation {
|
|||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct ClientProcessorInformation {
|
pub struct ClientProcessorInformation {
|
||||||
|
network_transaction_id: Option<String>,
|
||||||
avs: Option<Avs>,
|
avs: Option<Avs>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1667,7 +1758,7 @@ fn get_payment_response(
|
|||||||
.processor_information
|
.processor_information
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|processor_information| serde_json::json!({"avs_response": processor_information.avs})),
|
.map(|processor_information| serde_json::json!({"avs_response": processor_information.avs})),
|
||||||
network_txn_id: None,
|
network_txn_id: info_response.processor_information.as_ref().and_then(|processor_information| processor_information.network_transaction_id.clone()),
|
||||||
connector_response_reference_id: Some(
|
connector_response_reference_id: Some(
|
||||||
info_response
|
info_response
|
||||||
.client_reference_information
|
.client_reference_information
|
||||||
@ -2281,6 +2372,7 @@ impl<F>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// zero dollar response
|
||||||
impl<F, T>
|
impl<F, T>
|
||||||
TryFrom<
|
TryFrom<
|
||||||
types::ResponseRouterData<
|
types::ResponseRouterData<
|
||||||
@ -2328,7 +2420,11 @@ impl<F, T>
|
|||||||
redirection_data: None,
|
redirection_data: None,
|
||||||
mandate_reference,
|
mandate_reference,
|
||||||
connector_metadata: None,
|
connector_metadata: None,
|
||||||
network_txn_id: None,
|
network_txn_id: info_response.processor_information.as_ref().and_then(
|
||||||
|
|processor_information| {
|
||||||
|
processor_information.network_transaction_id.clone()
|
||||||
|
},
|
||||||
|
),
|
||||||
connector_response_reference_id: Some(
|
connector_response_reference_id: Some(
|
||||||
info_response
|
info_response
|
||||||
.client_reference_information
|
.client_reference_information
|
||||||
|
|||||||
Reference in New Issue
Block a user