mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-28 12:15:40 +08:00
refactor(connector): convert init payment flow to preprocessing flow for nuvei (#4878)
This commit is contained in:
@ -26,7 +26,6 @@ use crate::{
|
||||
self,
|
||||
api::{self, ConnectorCommon, ConnectorCommonExt},
|
||||
storage::enums,
|
||||
transformers::ForeignFrom,
|
||||
ErrorResponse, Response,
|
||||
},
|
||||
utils::ByteSliceExt,
|
||||
@ -124,6 +123,7 @@ impl api::RefundExecute for Nuvei {}
|
||||
impl api::RefundSync for Nuvei {}
|
||||
impl api::PaymentsCompleteAuthorize for Nuvei {}
|
||||
impl api::ConnectorAccessToken for Nuvei {}
|
||||
impl api::PaymentsPreProcessing for Nuvei {}
|
||||
|
||||
impl
|
||||
ConnectorIntegration<
|
||||
@ -524,53 +524,6 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
|
||||
))
|
||||
}
|
||||
|
||||
async fn execute_pretasks(
|
||||
&self,
|
||||
router_data: &mut types::PaymentsAuthorizeRouterData,
|
||||
app_state: &crate::routes::SessionState,
|
||||
) -> CustomResult<(), errors::ConnectorError> {
|
||||
let (enrolled_for_3ds, related_transaction_id) =
|
||||
match (router_data.auth_type, router_data.payment_method) {
|
||||
(
|
||||
diesel_models::enums::AuthenticationType::ThreeDs,
|
||||
diesel_models::enums::PaymentMethod::Card,
|
||||
) => {
|
||||
let integ: Box<
|
||||
&(dyn ConnectorIntegration<
|
||||
api::InitPayment,
|
||||
types::PaymentsAuthorizeData,
|
||||
types::PaymentsResponseData,
|
||||
> + Send
|
||||
+ Sync
|
||||
+ 'static),
|
||||
> = Box::new(&Self);
|
||||
let init_data = &types::PaymentsInitRouterData::foreign_from((
|
||||
&router_data.to_owned(),
|
||||
router_data.request.clone(),
|
||||
));
|
||||
let init_resp = services::execute_connector_processing_step(
|
||||
app_state,
|
||||
integ,
|
||||
init_data,
|
||||
payments::CallConnectorAction::Trigger,
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
match init_resp.response {
|
||||
Ok(types::PaymentsResponseData::ThreeDSEnrollmentResponse {
|
||||
enrolled_v2,
|
||||
related_transaction_id,
|
||||
}) => (enrolled_v2, related_transaction_id),
|
||||
_ => (false, None),
|
||||
}
|
||||
}
|
||||
_ => (false, None),
|
||||
};
|
||||
|
||||
router_data.request.enrolled_for_3ds = enrolled_for_3ds;
|
||||
router_data.request.related_transaction_id = related_transaction_id;
|
||||
Ok(())
|
||||
}
|
||||
fn get_request_body(
|
||||
&self,
|
||||
req: &types::PaymentsAuthorizeRouterData,
|
||||
@ -725,14 +678,14 @@ impl
|
||||
|
||||
impl
|
||||
ConnectorIntegration<
|
||||
api::InitPayment,
|
||||
types::PaymentsAuthorizeData,
|
||||
api::PreProcessing,
|
||||
types::PaymentsPreProcessingData,
|
||||
types::PaymentsResponseData,
|
||||
> for Nuvei
|
||||
{
|
||||
fn get_headers(
|
||||
&self,
|
||||
req: &types::PaymentsInitRouterData,
|
||||
req: &types::PaymentsPreProcessingRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
|
||||
self.build_headers(req, connectors)
|
||||
@ -744,7 +697,7 @@ impl
|
||||
|
||||
fn get_url(
|
||||
&self,
|
||||
_req: &types::PaymentsInitRouterData,
|
||||
_req: &types::PaymentsPreProcessingRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<String, errors::ConnectorError> {
|
||||
Ok(format!(
|
||||
@ -755,7 +708,7 @@ impl
|
||||
|
||||
fn get_request_body(
|
||||
&self,
|
||||
req: &types::PaymentsInitRouterData,
|
||||
req: &types::PaymentsPreProcessingRouterData,
|
||||
_connectors: &settings::Connectors,
|
||||
) -> CustomResult<RequestContent, errors::ConnectorError> {
|
||||
let connector_req = nuvei::NuveiPaymentsRequest::try_from((req, req.get_session_token()?))?;
|
||||
@ -765,16 +718,20 @@ impl
|
||||
|
||||
fn build_request(
|
||||
&self,
|
||||
req: &types::PaymentsInitRouterData,
|
||||
req: &types::PaymentsPreProcessingRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
|
||||
Ok(Some(
|
||||
services::RequestBuilder::new()
|
||||
.method(services::Method::Post)
|
||||
.url(&types::PaymentsInitType::get_url(self, req, connectors)?)
|
||||
.url(&types::PaymentsPreProcessingType::get_url(
|
||||
self, req, connectors,
|
||||
)?)
|
||||
.attach_default_headers()
|
||||
.headers(types::PaymentsInitType::get_headers(self, req, connectors)?)
|
||||
.set_body(types::PaymentsInitType::get_request_body(
|
||||
.headers(types::PaymentsPreProcessingType::get_headers(
|
||||
self, req, connectors,
|
||||
)?)
|
||||
.set_body(types::PaymentsPreProcessingType::get_request_body(
|
||||
self, req, connectors,
|
||||
)?)
|
||||
.build(),
|
||||
@ -783,10 +740,10 @@ impl
|
||||
|
||||
fn handle_response(
|
||||
&self,
|
||||
data: &types::PaymentsInitRouterData,
|
||||
data: &types::PaymentsPreProcessingRouterData,
|
||||
event_builder: Option<&mut ConnectorEvent>,
|
||||
res: Response,
|
||||
) -> CustomResult<types::PaymentsInitRouterData, errors::ConnectorError> {
|
||||
) -> CustomResult<types::PaymentsPreProcessingRouterData, errors::ConnectorError> {
|
||||
let response: nuvei::NuveiPaymentsResponse = res
|
||||
.response
|
||||
.parse_struct("NuveiPaymentsResponse")
|
||||
|
||||
@ -6,7 +6,7 @@ use common_utils::{
|
||||
pii::{Email, IpAddress},
|
||||
};
|
||||
use error_stack::ResultExt;
|
||||
use hyperswitch_domain_models::mandates::MandateDataType;
|
||||
use hyperswitch_domain_models::mandates::{MandateData, MandateDataType};
|
||||
use masking::{ExposeInterface, PeekInterface, Secret};
|
||||
use reqwest::Url;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -14,7 +14,7 @@ use serde::{Deserialize, Serialize};
|
||||
use crate::{
|
||||
connector::utils::{
|
||||
self, AddressDetailsData, BrowserInformationData, PaymentsAuthorizeRequestData,
|
||||
PaymentsCancelRequestData, RouterData,
|
||||
PaymentsCancelRequestData, PaymentsPreProcessingData, RouterData,
|
||||
},
|
||||
consts,
|
||||
core::errors,
|
||||
@ -23,6 +23,133 @@ use crate::{
|
||||
utils::OptionExt,
|
||||
};
|
||||
|
||||
trait NuveiAuthorizePreprocessingCommon {
|
||||
fn get_browser_info(&self) -> Option<BrowserInformation>;
|
||||
fn get_related_transaction_id(&self) -> Option<String>;
|
||||
fn get_email_required(&self) -> Result<Email, error_stack::Report<errors::ConnectorError>>;
|
||||
fn get_setup_mandate_details(&self) -> Option<MandateData>;
|
||||
fn get_complete_authorize_url(&self) -> Option<String>;
|
||||
fn get_connector_mandate_id(&self) -> Option<String>;
|
||||
fn get_return_url_required(
|
||||
&self,
|
||||
) -> Result<String, error_stack::Report<errors::ConnectorError>>;
|
||||
fn get_capture_method(&self) -> Option<enums::CaptureMethod>;
|
||||
fn get_amount_required(&self) -> Result<i64, error_stack::Report<errors::ConnectorError>>;
|
||||
fn get_currency_required(
|
||||
&self,
|
||||
) -> Result<diesel_models::enums::Currency, error_stack::Report<errors::ConnectorError>>;
|
||||
fn get_payment_method_data_required(
|
||||
&self,
|
||||
) -> Result<domain::PaymentMethodData, error_stack::Report<errors::ConnectorError>>;
|
||||
}
|
||||
|
||||
impl NuveiAuthorizePreprocessingCommon for types::PaymentsAuthorizeData {
|
||||
fn get_browser_info(&self) -> Option<BrowserInformation> {
|
||||
self.browser_info.clone()
|
||||
}
|
||||
|
||||
fn get_related_transaction_id(&self) -> Option<String> {
|
||||
self.related_transaction_id.clone()
|
||||
}
|
||||
|
||||
fn get_email_required(&self) -> Result<Email, error_stack::Report<errors::ConnectorError>> {
|
||||
self.get_email()
|
||||
}
|
||||
|
||||
fn get_setup_mandate_details(&self) -> Option<MandateData> {
|
||||
self.setup_mandate_details.clone()
|
||||
}
|
||||
|
||||
fn get_complete_authorize_url(&self) -> Option<String> {
|
||||
self.complete_authorize_url.clone()
|
||||
}
|
||||
|
||||
fn get_connector_mandate_id(&self) -> Option<String> {
|
||||
self.connector_mandate_id().clone()
|
||||
}
|
||||
|
||||
fn get_return_url_required(
|
||||
&self,
|
||||
) -> Result<String, error_stack::Report<errors::ConnectorError>> {
|
||||
self.get_return_url()
|
||||
}
|
||||
|
||||
fn get_capture_method(&self) -> Option<enums::CaptureMethod> {
|
||||
self.capture_method
|
||||
}
|
||||
|
||||
fn get_amount_required(&self) -> Result<i64, error_stack::Report<errors::ConnectorError>> {
|
||||
Ok(self.amount)
|
||||
}
|
||||
|
||||
fn get_currency_required(
|
||||
&self,
|
||||
) -> Result<diesel_models::enums::Currency, error_stack::Report<errors::ConnectorError>> {
|
||||
Ok(self.currency)
|
||||
}
|
||||
fn get_payment_method_data_required(
|
||||
&self,
|
||||
) -> Result<domain::PaymentMethodData, error_stack::Report<errors::ConnectorError>> {
|
||||
Ok(self.payment_method_data.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl NuveiAuthorizePreprocessingCommon for types::PaymentsPreProcessingData {
|
||||
fn get_browser_info(&self) -> Option<BrowserInformation> {
|
||||
self.browser_info.clone()
|
||||
}
|
||||
|
||||
fn get_related_transaction_id(&self) -> Option<String> {
|
||||
self.related_transaction_id.clone()
|
||||
}
|
||||
|
||||
fn get_email_required(&self) -> Result<Email, error_stack::Report<errors::ConnectorError>> {
|
||||
self.get_email()
|
||||
}
|
||||
|
||||
fn get_setup_mandate_details(&self) -> Option<MandateData> {
|
||||
self.setup_mandate_details.clone()
|
||||
}
|
||||
|
||||
fn get_complete_authorize_url(&self) -> Option<String> {
|
||||
self.complete_authorize_url.clone()
|
||||
}
|
||||
|
||||
fn get_connector_mandate_id(&self) -> Option<String> {
|
||||
self.connector_mandate_id()
|
||||
}
|
||||
|
||||
fn get_return_url_required(
|
||||
&self,
|
||||
) -> Result<String, error_stack::Report<errors::ConnectorError>> {
|
||||
self.get_return_url()
|
||||
}
|
||||
|
||||
fn get_capture_method(&self) -> Option<enums::CaptureMethod> {
|
||||
self.capture_method
|
||||
}
|
||||
|
||||
fn get_amount_required(&self) -> Result<i64, error_stack::Report<errors::ConnectorError>> {
|
||||
self.get_amount()
|
||||
}
|
||||
|
||||
fn get_currency_required(
|
||||
&self,
|
||||
) -> Result<diesel_models::enums::Currency, error_stack::Report<errors::ConnectorError>> {
|
||||
self.get_currency()
|
||||
}
|
||||
fn get_payment_method_data_required(
|
||||
&self,
|
||||
) -> Result<domain::PaymentMethodData, error_stack::Report<errors::ConnectorError>> {
|
||||
self.payment_method_data.clone().ok_or(
|
||||
errors::ConnectorError::MissingRequiredField {
|
||||
field_name: "payment_method_data",
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Default, Deserialize)]
|
||||
pub struct NuveiMeta {
|
||||
pub session_token: Secret<String>,
|
||||
@ -628,26 +755,28 @@ impl TryFrom<common_enums::enums::BankNames> for NuveiBIC {
|
||||
}
|
||||
}
|
||||
|
||||
impl<F>
|
||||
impl<F, Req>
|
||||
ForeignTryFrom<(
|
||||
AlternativePaymentMethodType,
|
||||
Option<domain::BankRedirectData>,
|
||||
&types::RouterData<F, types::PaymentsAuthorizeData, types::PaymentsResponseData>,
|
||||
&types::RouterData<F, Req, types::PaymentsResponseData>,
|
||||
)> for NuveiPaymentsRequest
|
||||
where
|
||||
Req: NuveiAuthorizePreprocessingCommon,
|
||||
{
|
||||
type Error = error_stack::Report<errors::ConnectorError>;
|
||||
fn foreign_try_from(
|
||||
data: (
|
||||
AlternativePaymentMethodType,
|
||||
Option<domain::BankRedirectData>,
|
||||
&types::RouterData<F, types::PaymentsAuthorizeData, types::PaymentsResponseData>,
|
||||
&types::RouterData<F, Req, types::PaymentsResponseData>,
|
||||
),
|
||||
) -> Result<Self, Self::Error> {
|
||||
let (payment_method, redirect, item) = data;
|
||||
let (billing_address, bank_id) = match (&payment_method, redirect) {
|
||||
(AlternativePaymentMethodType::Expresscheckout, _) => (
|
||||
Some(BillingAddress {
|
||||
email: item.request.get_email()?,
|
||||
email: item.request.get_email_required()?,
|
||||
country: item.get_billing_country()?,
|
||||
..Default::default()
|
||||
}),
|
||||
@ -655,7 +784,7 @@ impl<F>
|
||||
),
|
||||
(AlternativePaymentMethodType::Giropay, _) => (
|
||||
Some(BillingAddress {
|
||||
email: item.request.get_email()?,
|
||||
email: item.request.get_email_required()?,
|
||||
country: item.get_billing_country()?,
|
||||
..Default::default()
|
||||
}),
|
||||
@ -668,7 +797,7 @@ impl<F>
|
||||
Some(BillingAddress {
|
||||
first_name: Some(first_name.clone()),
|
||||
last_name: Some(address.get_last_name().unwrap_or(first_name).clone()),
|
||||
email: item.request.get_email()?,
|
||||
email: item.request.get_email_required()?,
|
||||
country: item.get_billing_country()?,
|
||||
}),
|
||||
None,
|
||||
@ -686,7 +815,7 @@ impl<F>
|
||||
last_name: Some(
|
||||
address.get_last_name().ok().unwrap_or(&first_name).clone(),
|
||||
),
|
||||
email: item.request.get_email()?,
|
||||
email: item.request.get_email_required()?,
|
||||
country: item.get_billing_country()?,
|
||||
}),
|
||||
bank_name.map(NuveiBIC::try_from).transpose()?,
|
||||
@ -710,10 +839,13 @@ impl<F>
|
||||
}
|
||||
}
|
||||
|
||||
fn get_pay_later_info<F>(
|
||||
fn get_pay_later_info<F, Req>(
|
||||
payment_method_type: AlternativePaymentMethodType,
|
||||
item: &types::RouterData<F, types::PaymentsAuthorizeData, types::PaymentsResponseData>,
|
||||
) -> Result<NuveiPaymentsRequest, error_stack::Report<errors::ConnectorError>> {
|
||||
item: &types::RouterData<F, Req, types::PaymentsResponseData>,
|
||||
) -> Result<NuveiPaymentsRequest, error_stack::Report<errors::ConnectorError>>
|
||||
where
|
||||
Req: NuveiAuthorizePreprocessingCommon,
|
||||
{
|
||||
let address = item
|
||||
.get_billing()?
|
||||
.address
|
||||
@ -728,7 +860,7 @@ fn get_pay_later_info<F>(
|
||||
..Default::default()
|
||||
}),
|
||||
billing_address: Some(BillingAddress {
|
||||
email: item.request.get_email()?,
|
||||
email: item.request.get_email_required()?,
|
||||
first_name: Some(first_name.clone()),
|
||||
last_name: Some(address.get_last_name().unwrap_or(first_name).clone()),
|
||||
country: address.get_country()?.to_owned(),
|
||||
@ -739,21 +871,23 @@ fn get_pay_later_info<F>(
|
||||
})
|
||||
}
|
||||
|
||||
impl<F>
|
||||
impl<F, Req>
|
||||
TryFrom<(
|
||||
&types::RouterData<F, types::PaymentsAuthorizeData, types::PaymentsResponseData>,
|
||||
&types::RouterData<F, Req, types::PaymentsResponseData>,
|
||||
String,
|
||||
)> for NuveiPaymentsRequest
|
||||
where
|
||||
Req: NuveiAuthorizePreprocessingCommon,
|
||||
{
|
||||
type Error = error_stack::Report<errors::ConnectorError>;
|
||||
fn try_from(
|
||||
data: (
|
||||
&types::RouterData<F, types::PaymentsAuthorizeData, types::PaymentsResponseData>,
|
||||
&types::RouterData<F, Req, types::PaymentsResponseData>,
|
||||
String,
|
||||
),
|
||||
) -> Result<Self, Self::Error> {
|
||||
let item = data.0;
|
||||
let request_data = match item.request.payment_method_data.clone() {
|
||||
let request_data = match item.request.get_payment_method_data_required()?.clone() {
|
||||
domain::PaymentMethodData::Card(card) => get_card_info(item, &card),
|
||||
domain::PaymentMethodData::MandatePayment => Self::try_from(item),
|
||||
domain::PaymentMethodData::Wallet(wallet) => match wallet {
|
||||
@ -866,16 +1000,17 @@ impl<F>
|
||||
.into())
|
||||
}
|
||||
}?;
|
||||
let currency = item.request.get_currency_required()?;
|
||||
let request = Self::try_from(NuveiPaymentRequestData {
|
||||
amount: utils::to_currency_base_unit(item.request.amount, item.request.currency)?,
|
||||
currency: item.request.currency,
|
||||
amount: utils::to_currency_base_unit(item.request.get_amount_required()?, currency)?,
|
||||
currency,
|
||||
connector_auth_type: item.connector_auth_type.clone(),
|
||||
client_request_id: item.connector_request_reference_id.clone(),
|
||||
session_token: Secret::new(data.1),
|
||||
capture_method: item.request.capture_method,
|
||||
capture_method: item.request.get_capture_method(),
|
||||
..Default::default()
|
||||
})?;
|
||||
let return_url = item.request.get_return_url()?;
|
||||
let return_url = item.request.get_return_url_required()?;
|
||||
Ok(Self {
|
||||
is_rebilling: request_data.is_rebilling,
|
||||
user_token_id: request_data.user_token_id,
|
||||
@ -893,13 +1028,16 @@ impl<F>
|
||||
}
|
||||
}
|
||||
|
||||
fn get_card_info<F>(
|
||||
item: &types::RouterData<F, types::PaymentsAuthorizeData, types::PaymentsResponseData>,
|
||||
fn get_card_info<F, Req>(
|
||||
item: &types::RouterData<F, Req, types::PaymentsResponseData>,
|
||||
card_details: &domain::Card,
|
||||
) -> Result<NuveiPaymentsRequest, error_stack::Report<errors::ConnectorError>> {
|
||||
let browser_information = item.request.browser_info.clone();
|
||||
) -> Result<NuveiPaymentsRequest, error_stack::Report<errors::ConnectorError>>
|
||||
where
|
||||
Req: NuveiAuthorizePreprocessingCommon,
|
||||
{
|
||||
let browser_information = item.request.get_browser_info().clone();
|
||||
let related_transaction_id = if item.is_three_ds() {
|
||||
item.request.related_transaction_id.clone()
|
||||
item.request.get_related_transaction_id().clone()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@ -914,14 +1052,14 @@ fn get_card_info<F>(
|
||||
Some(BillingAddress {
|
||||
first_name: Some(first_name.clone()),
|
||||
last_name: Some(address.get_last_name().ok().unwrap_or(&first_name).clone()),
|
||||
email: item.request.get_email()?,
|
||||
email: item.request.get_email_required()?,
|
||||
country: item.get_billing_country()?,
|
||||
})
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
let (is_rebilling, additional_params, user_token_id) =
|
||||
match item.request.setup_mandate_details.clone() {
|
||||
match item.request.get_setup_mandate_details().clone() {
|
||||
Some(mandate_data) => {
|
||||
let details = match mandate_data
|
||||
.mandate_type
|
||||
@ -955,7 +1093,7 @@ fn get_card_info<F>(
|
||||
rebill_frequency: Some(mandate_meta.frequency),
|
||||
challenge_window_size: None,
|
||||
}),
|
||||
Some(item.request.get_email()?),
|
||||
Some(item.request.get_email_required()?),
|
||||
)
|
||||
}
|
||||
_ => (None, None, None),
|
||||
@ -982,7 +1120,7 @@ fn get_card_info<F>(
|
||||
Some(ThreeD {
|
||||
browser_details,
|
||||
v2_additional_params: additional_params,
|
||||
notification_url: item.request.complete_authorize_url.clone(),
|
||||
notification_url: item.request.get_complete_authorize_url().clone(),
|
||||
merchant_url: item.return_url.clone(),
|
||||
platform_type: Some(PlatformType::Browser),
|
||||
method_completion_ind: Some(MethodCompletion::Unavailable),
|
||||
@ -997,7 +1135,7 @@ fn get_card_info<F>(
|
||||
is_rebilling,
|
||||
user_token_id,
|
||||
device_details: Option::<DeviceDetails>::foreign_try_from(
|
||||
&item.request.browser_info.clone(),
|
||||
&item.request.get_browser_info().clone(),
|
||||
)?,
|
||||
payment_option: PaymentOption::from(NuveiCardDetails {
|
||||
card: card_details.clone(),
|
||||
@ -1479,12 +1617,12 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<types::PaymentsInitResponseRouterData<NuveiPaymentsResponse>>
|
||||
for types::PaymentsInitRouterData
|
||||
impl TryFrom<types::PaymentsPreprocessingResponseRouterData<NuveiPaymentsResponse>>
|
||||
for types::PaymentsPreProcessingRouterData
|
||||
{
|
||||
type Error = error_stack::Report<errors::ConnectorError>;
|
||||
fn try_from(
|
||||
item: types::PaymentsInitResponseRouterData<NuveiPaymentsResponse>,
|
||||
item: types::PaymentsPreprocessingResponseRouterData<NuveiPaymentsResponse>,
|
||||
) -> Result<Self, Self::Error> {
|
||||
let response = item.response;
|
||||
let is_enrolled_for_3ds = response
|
||||
@ -1558,28 +1696,30 @@ impl TryFrom<types::RefundsResponseRouterData<api::RSync, NuveiPaymentsResponse>
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> TryFrom<&types::RouterData<F, types::PaymentsAuthorizeData, types::PaymentsResponseData>>
|
||||
impl<F, Req> TryFrom<&types::RouterData<F, Req, types::PaymentsResponseData>>
|
||||
for NuveiPaymentsRequest
|
||||
where
|
||||
Req: NuveiAuthorizePreprocessingCommon,
|
||||
{
|
||||
type Error = error_stack::Report<errors::ConnectorError>;
|
||||
fn try_from(
|
||||
data: &types::RouterData<F, types::PaymentsAuthorizeData, types::PaymentsResponseData>,
|
||||
data: &types::RouterData<F, Req, types::PaymentsResponseData>,
|
||||
) -> Result<Self, Self::Error> {
|
||||
{
|
||||
let item = data;
|
||||
let connector_mandate_id = &item.request.connector_mandate_id();
|
||||
let connector_mandate_id = &item.request.get_connector_mandate_id();
|
||||
let related_transaction_id = if item.is_three_ds() {
|
||||
item.request.related_transaction_id.clone()
|
||||
item.request.get_related_transaction_id().clone()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Ok(Self {
|
||||
related_transaction_id,
|
||||
device_details: Option::<DeviceDetails>::foreign_try_from(
|
||||
&item.request.browser_info.clone(),
|
||||
&item.request.get_browser_info().clone(),
|
||||
)?,
|
||||
is_rebilling: Some("1".to_string()), // In case of second installment, rebilling should be 1
|
||||
user_token_id: Some(item.request.get_email()?),
|
||||
user_token_id: Some(item.request.get_email_required()?),
|
||||
payment_option: PaymentOption {
|
||||
user_payment_option_id: connector_mandate_id.clone(),
|
||||
..Default::default()
|
||||
|
||||
@ -615,6 +615,7 @@ pub trait PaymentsPreProcessingData {
|
||||
fn get_return_url(&self) -> Result<String, Error>;
|
||||
fn get_browser_info(&self) -> Result<BrowserInformation, Error>;
|
||||
fn get_complete_authorize_url(&self) -> Result<String, Error>;
|
||||
fn connector_mandate_id(&self) -> Option<String>;
|
||||
}
|
||||
|
||||
impl PaymentsPreProcessingData for types::PaymentsPreProcessingData {
|
||||
@ -664,6 +665,16 @@ impl PaymentsPreProcessingData for types::PaymentsPreProcessingData {
|
||||
.clone()
|
||||
.ok_or_else(missing_field_err("complete_authorize_url"))
|
||||
}
|
||||
fn connector_mandate_id(&self) -> Option<String> {
|
||||
self.mandate_id
|
||||
.as_ref()
|
||||
.and_then(|mandate_ids| match &mandate_ids.mandate_reference_id {
|
||||
Some(payments::MandateReferenceId::ConnectorMandateId(connector_mandate_ids)) => {
|
||||
connector_mandate_ids.connector_mandate_id.clone()
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub trait PaymentsCaptureRequestData {
|
||||
|
||||
@ -1965,6 +1965,12 @@ where
|
||||
) && router_data.status
|
||||
!= common_enums::AttemptStatus::AuthenticationFailed;
|
||||
(router_data, should_continue)
|
||||
} else if connector.connector_name == router_types::Connector::Nuvei
|
||||
&& router_data.auth_type == common_enums::AuthenticationType::ThreeDs
|
||||
&& !is_operation_complete_authorize(&operation)
|
||||
{
|
||||
router_data = router_data.preprocessing_steps(state, connector).await?;
|
||||
(router_data, should_continue_payment)
|
||||
} else {
|
||||
(router_data, should_continue_payment)
|
||||
}
|
||||
|
||||
@ -978,7 +978,6 @@ default_imp_for_pre_processing_steps!(
|
||||
connector::Netcetera,
|
||||
connector::Nexinets,
|
||||
connector::Noon,
|
||||
connector::Nuvei,
|
||||
connector::Opayo,
|
||||
connector::Opennode,
|
||||
connector::Payeezy,
|
||||
|
||||
@ -361,6 +361,16 @@ pub async fn authorize_preprocessing_steps<F: Clone>(
|
||||
);
|
||||
if connector.connector_name == api_models::enums::Connector::Airwallex {
|
||||
authorize_router_data.reference_id = resp.reference_id;
|
||||
} else if connector.connector_name == api_models::enums::Connector::Nuvei {
|
||||
let (enrolled_for_3ds, related_transaction_id) = match &authorize_router_data.response {
|
||||
Ok(types::PaymentsResponseData::ThreeDSEnrollmentResponse {
|
||||
enrolled_v2,
|
||||
related_transaction_id,
|
||||
}) => (*enrolled_v2, related_transaction_id.clone()),
|
||||
_ => (false, None),
|
||||
};
|
||||
authorize_router_data.request.enrolled_for_3ds = enrolled_for_3ds;
|
||||
authorize_router_data.request.related_transaction_id = related_transaction_id;
|
||||
}
|
||||
Ok(authorize_router_data)
|
||||
} else {
|
||||
|
||||
@ -1797,6 +1797,8 @@ impl<F: Clone> TryFrom<PaymentAdditionalData<'_, F>> for types::PaymentsPreProce
|
||||
surcharge_details: payment_data.surcharge_details,
|
||||
connector_transaction_id: payment_data.payment_attempt.connector_transaction_id,
|
||||
redirect_response: None,
|
||||
mandate_id: payment_data.mandate_id,
|
||||
related_transaction_id: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -120,6 +120,8 @@ pub type PaymentsInitResponseRouterData<R> =
|
||||
ResponseRouterData<api::InitPayment, R, PaymentsAuthorizeData, PaymentsResponseData>;
|
||||
pub type PaymentsCaptureResponseRouterData<R> =
|
||||
ResponseRouterData<api::Capture, R, PaymentsCaptureData, PaymentsResponseData>;
|
||||
pub type PaymentsPreprocessingResponseRouterData<R> =
|
||||
ResponseRouterData<api::PreProcessing, R, PaymentsPreProcessingData, PaymentsResponseData>;
|
||||
pub type TokenizationResponseRouterData<R> = ResponseRouterData<
|
||||
api::PaymentMethodToken,
|
||||
R,
|
||||
|
||||
Reference in New Issue
Block a user