mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-31 01:57:45 +08:00
fix(nuvei): nuvei 3ds fix + psync fix (#9279)
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
@ -53,6 +53,7 @@ use masking::ExposeInterface;
|
|||||||
use transformers as nuvei;
|
use transformers as nuvei;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
connectors::nuvei::transformers::{NuveiPaymentsResponse, NuveiTransactionSyncResponse},
|
||||||
constants::headers,
|
constants::headers,
|
||||||
types::ResponseRouterData,
|
types::ResponseRouterData,
|
||||||
utils::{self, is_mandate_supported, PaymentMethodDataType, RouterData as _},
|
utils::{self, is_mandate_supported, PaymentMethodDataType, RouterData as _},
|
||||||
@ -211,7 +212,7 @@ impl ConnectorIntegration<SetupMandate, SetupMandateRequestData, PaymentsRespons
|
|||||||
RouterData<SetupMandate, SetupMandateRequestData, PaymentsResponseData>,
|
RouterData<SetupMandate, SetupMandateRequestData, PaymentsResponseData>,
|
||||||
errors::ConnectorError,
|
errors::ConnectorError,
|
||||||
> {
|
> {
|
||||||
let response: nuvei::NuveiPaymentsResponse = res
|
let response: NuveiPaymentsResponse = res
|
||||||
.response
|
.response
|
||||||
.parse_struct("NuveiPaymentsResponse")
|
.parse_struct("NuveiPaymentsResponse")
|
||||||
.switch()?;
|
.switch()?;
|
||||||
@ -234,6 +235,85 @@ impl ConnectorIntegration<SetupMandate, SetupMandateRequestData, PaymentsRespons
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ConnectorIntegration<Void, PaymentsCancelData, PaymentsResponseData> for Nuvei {
|
||||||
|
fn get_headers(
|
||||||
|
&self,
|
||||||
|
req: &PaymentsCancelRouterData,
|
||||||
|
connectors: &Connectors,
|
||||||
|
) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
|
||||||
|
self.build_headers(req, connectors)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_content_type(&self) -> &'static str {
|
||||||
|
self.common_get_content_type()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_url(
|
||||||
|
&self,
|
||||||
|
_req: &PaymentsCancelRouterData,
|
||||||
|
connectors: &Connectors,
|
||||||
|
) -> CustomResult<String, errors::ConnectorError> {
|
||||||
|
Ok(format!(
|
||||||
|
"{}ppp/api/v1/voidTransaction.do",
|
||||||
|
ConnectorCommon::base_url(self, connectors)
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_request_body(
|
||||||
|
&self,
|
||||||
|
req: &PaymentsCancelRouterData,
|
||||||
|
_connectors: &Connectors,
|
||||||
|
) -> CustomResult<RequestContent, errors::ConnectorError> {
|
||||||
|
let connector_req = nuvei::NuveiPaymentFlowRequest::try_from(req)?;
|
||||||
|
Ok(RequestContent::Json(Box::new(connector_req)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_request(
|
||||||
|
&self,
|
||||||
|
req: &PaymentsCancelRouterData,
|
||||||
|
connectors: &Connectors,
|
||||||
|
) -> CustomResult<Option<Request>, errors::ConnectorError> {
|
||||||
|
let request = RequestBuilder::new()
|
||||||
|
.method(Method::Post)
|
||||||
|
.url(&types::PaymentsVoidType::get_url(self, req, connectors)?)
|
||||||
|
.attach_default_headers()
|
||||||
|
.headers(types::PaymentsVoidType::get_headers(self, req, connectors)?)
|
||||||
|
.set_body(types::PaymentsVoidType::get_request_body(
|
||||||
|
self, req, connectors,
|
||||||
|
)?)
|
||||||
|
.build();
|
||||||
|
Ok(Some(request))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_response(
|
||||||
|
&self,
|
||||||
|
data: &PaymentsCancelRouterData,
|
||||||
|
event_builder: Option<&mut ConnectorEvent>,
|
||||||
|
res: Response,
|
||||||
|
) -> CustomResult<PaymentsCancelRouterData, errors::ConnectorError> {
|
||||||
|
let response: NuveiPaymentsResponse = res
|
||||||
|
.response
|
||||||
|
.parse_struct("NuveiPaymentsResponse")
|
||||||
|
.switch()?;
|
||||||
|
event_builder.map(|i| i.set_response_body(&response));
|
||||||
|
router_env::logger::info!(connector_response=?response);
|
||||||
|
RouterData::try_from(ResponseRouterData {
|
||||||
|
response,
|
||||||
|
data: data.clone(),
|
||||||
|
http_code: res.status_code,
|
||||||
|
})
|
||||||
|
.change_context(errors::ConnectorError::ResponseHandlingFailed)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_error_response(
|
||||||
|
&self,
|
||||||
|
res: Response,
|
||||||
|
event_builder: Option<&mut ConnectorEvent>,
|
||||||
|
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
|
||||||
|
self.build_error_response(res, event_builder)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ConnectorIntegration<CompleteAuthorize, CompleteAuthorizeData, PaymentsResponseData>
|
impl ConnectorIntegration<CompleteAuthorize, CompleteAuthorizeData, PaymentsResponseData>
|
||||||
for Nuvei
|
for Nuvei
|
||||||
{
|
{
|
||||||
@ -293,87 +373,7 @@ impl ConnectorIntegration<CompleteAuthorize, CompleteAuthorizeData, PaymentsResp
|
|||||||
event_builder: Option<&mut ConnectorEvent>,
|
event_builder: Option<&mut ConnectorEvent>,
|
||||||
res: Response,
|
res: Response,
|
||||||
) -> CustomResult<PaymentsCompleteAuthorizeRouterData, errors::ConnectorError> {
|
) -> CustomResult<PaymentsCompleteAuthorizeRouterData, errors::ConnectorError> {
|
||||||
let response: nuvei::NuveiPaymentsResponse = res
|
let response: NuveiPaymentsResponse = res
|
||||||
.response
|
|
||||||
.parse_struct("NuveiPaymentsResponse")
|
|
||||||
.switch()?;
|
|
||||||
event_builder.map(|i| i.set_response_body(&response));
|
|
||||||
router_env::logger::info!(connector_response=?response);
|
|
||||||
|
|
||||||
RouterData::try_from(ResponseRouterData {
|
|
||||||
response,
|
|
||||||
data: data.clone(),
|
|
||||||
http_code: res.status_code,
|
|
||||||
})
|
|
||||||
.change_context(errors::ConnectorError::ResponseHandlingFailed)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_error_response(
|
|
||||||
&self,
|
|
||||||
res: Response,
|
|
||||||
event_builder: Option<&mut ConnectorEvent>,
|
|
||||||
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
|
|
||||||
self.build_error_response(res, event_builder)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ConnectorIntegration<Void, PaymentsCancelData, PaymentsResponseData> for Nuvei {
|
|
||||||
fn get_headers(
|
|
||||||
&self,
|
|
||||||
req: &PaymentsCancelRouterData,
|
|
||||||
connectors: &Connectors,
|
|
||||||
) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
|
|
||||||
self.build_headers(req, connectors)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_content_type(&self) -> &'static str {
|
|
||||||
self.common_get_content_type()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_url(
|
|
||||||
&self,
|
|
||||||
_req: &PaymentsCancelRouterData,
|
|
||||||
connectors: &Connectors,
|
|
||||||
) -> CustomResult<String, errors::ConnectorError> {
|
|
||||||
Ok(format!(
|
|
||||||
"{}ppp/api/v1/voidTransaction.do",
|
|
||||||
ConnectorCommon::base_url(self, connectors)
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_request_body(
|
|
||||||
&self,
|
|
||||||
req: &PaymentsCancelRouterData,
|
|
||||||
_connectors: &Connectors,
|
|
||||||
) -> CustomResult<RequestContent, errors::ConnectorError> {
|
|
||||||
let connector_req = nuvei::NuveiPaymentFlowRequest::try_from(req)?;
|
|
||||||
Ok(RequestContent::Json(Box::new(connector_req)))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_request(
|
|
||||||
&self,
|
|
||||||
req: &PaymentsCancelRouterData,
|
|
||||||
connectors: &Connectors,
|
|
||||||
) -> CustomResult<Option<Request>, errors::ConnectorError> {
|
|
||||||
let request = RequestBuilder::new()
|
|
||||||
.method(Method::Post)
|
|
||||||
.url(&types::PaymentsVoidType::get_url(self, req, connectors)?)
|
|
||||||
.attach_default_headers()
|
|
||||||
.headers(types::PaymentsVoidType::get_headers(self, req, connectors)?)
|
|
||||||
.set_body(types::PaymentsVoidType::get_request_body(
|
|
||||||
self, req, connectors,
|
|
||||||
)?)
|
|
||||||
.build();
|
|
||||||
Ok(Some(request))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_response(
|
|
||||||
&self,
|
|
||||||
data: &PaymentsCancelRouterData,
|
|
||||||
event_builder: Option<&mut ConnectorEvent>,
|
|
||||||
res: Response,
|
|
||||||
) -> CustomResult<PaymentsCancelRouterData, errors::ConnectorError> {
|
|
||||||
let response: nuvei::NuveiPaymentsResponse = res
|
|
||||||
.response
|
.response
|
||||||
.parse_struct("NuveiPaymentsResponse")
|
.parse_struct("NuveiPaymentsResponse")
|
||||||
.switch()?;
|
.switch()?;
|
||||||
@ -458,7 +458,7 @@ impl ConnectorIntegration<PostCaptureVoid, PaymentsCancelPostCaptureData, Paymen
|
|||||||
event_builder: Option<&mut ConnectorEvent>,
|
event_builder: Option<&mut ConnectorEvent>,
|
||||||
res: Response,
|
res: Response,
|
||||||
) -> CustomResult<PaymentsCancelPostCaptureRouterData, errors::ConnectorError> {
|
) -> CustomResult<PaymentsCancelPostCaptureRouterData, errors::ConnectorError> {
|
||||||
let response: nuvei::NuveiPaymentsResponse = res
|
let response: NuveiPaymentsResponse = res
|
||||||
.response
|
.response
|
||||||
.parse_struct("NuveiPaymentsResponse")
|
.parse_struct("NuveiPaymentsResponse")
|
||||||
.switch()?;
|
.switch()?;
|
||||||
@ -501,7 +501,7 @@ impl ConnectorIntegration<PSync, PaymentsSyncData, PaymentsResponseData> for Nuv
|
|||||||
connectors: &Connectors,
|
connectors: &Connectors,
|
||||||
) -> CustomResult<String, errors::ConnectorError> {
|
) -> CustomResult<String, errors::ConnectorError> {
|
||||||
Ok(format!(
|
Ok(format!(
|
||||||
"{}ppp/api/v1/getPaymentStatus.do",
|
"{}ppp/api/v1/getTransactionDetails.do",
|
||||||
ConnectorCommon::base_url(self, connectors)
|
ConnectorCommon::base_url(self, connectors)
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -546,9 +546,9 @@ impl ConnectorIntegration<PSync, PaymentsSyncData, PaymentsResponseData> for Nuv
|
|||||||
event_builder: Option<&mut ConnectorEvent>,
|
event_builder: Option<&mut ConnectorEvent>,
|
||||||
res: Response,
|
res: Response,
|
||||||
) -> CustomResult<PaymentsSyncRouterData, errors::ConnectorError> {
|
) -> CustomResult<PaymentsSyncRouterData, errors::ConnectorError> {
|
||||||
let response: nuvei::NuveiPaymentsResponse = res
|
let response: NuveiTransactionSyncResponse = res
|
||||||
.response
|
.response
|
||||||
.parse_struct("NuveiPaymentsResponse")
|
.parse_struct("NuveiTransactionSyncResponse")
|
||||||
.switch()?;
|
.switch()?;
|
||||||
|
|
||||||
event_builder.map(|i| i.set_response_body(&response));
|
event_builder.map(|i| i.set_response_body(&response));
|
||||||
@ -622,7 +622,7 @@ impl ConnectorIntegration<Capture, PaymentsCaptureData, PaymentsResponseData> fo
|
|||||||
event_builder: Option<&mut ConnectorEvent>,
|
event_builder: Option<&mut ConnectorEvent>,
|
||||||
res: Response,
|
res: Response,
|
||||||
) -> CustomResult<PaymentsCaptureRouterData, errors::ConnectorError> {
|
) -> CustomResult<PaymentsCaptureRouterData, errors::ConnectorError> {
|
||||||
let response: nuvei::NuveiPaymentsResponse = res
|
let response: NuveiPaymentsResponse = res
|
||||||
.response
|
.response
|
||||||
.parse_struct("NuveiPaymentsResponse")
|
.parse_struct("NuveiPaymentsResponse")
|
||||||
.switch()?;
|
.switch()?;
|
||||||
@ -678,7 +678,6 @@ impl ConnectorIntegration<Authorize, PaymentsAuthorizeData, PaymentsResponseData
|
|||||||
_connectors: &Connectors,
|
_connectors: &Connectors,
|
||||||
) -> CustomResult<RequestContent, errors::ConnectorError> {
|
) -> CustomResult<RequestContent, errors::ConnectorError> {
|
||||||
let connector_req = nuvei::NuveiPaymentsRequest::try_from((req, req.get_session_token()?))?;
|
let connector_req = nuvei::NuveiPaymentsRequest::try_from((req, req.get_session_token()?))?;
|
||||||
|
|
||||||
Ok(RequestContent::Json(Box::new(connector_req)))
|
Ok(RequestContent::Json(Box::new(connector_req)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -710,7 +709,7 @@ impl ConnectorIntegration<Authorize, PaymentsAuthorizeData, PaymentsResponseData
|
|||||||
event_builder: Option<&mut ConnectorEvent>,
|
event_builder: Option<&mut ConnectorEvent>,
|
||||||
res: Response,
|
res: Response,
|
||||||
) -> CustomResult<PaymentsAuthorizeRouterData, errors::ConnectorError> {
|
) -> CustomResult<PaymentsAuthorizeRouterData, errors::ConnectorError> {
|
||||||
let response: nuvei::NuveiPaymentsResponse = res
|
let response: NuveiPaymentsResponse = res
|
||||||
.response
|
.response
|
||||||
.parse_struct("NuveiPaymentsResponse")
|
.parse_struct("NuveiPaymentsResponse")
|
||||||
.switch()?;
|
.switch()?;
|
||||||
@ -883,13 +882,12 @@ impl ConnectorIntegration<PreProcessing, PaymentsPreProcessingData, PaymentsResp
|
|||||||
event_builder: Option<&mut ConnectorEvent>,
|
event_builder: Option<&mut ConnectorEvent>,
|
||||||
res: Response,
|
res: Response,
|
||||||
) -> CustomResult<PaymentsPreProcessingRouterData, errors::ConnectorError> {
|
) -> CustomResult<PaymentsPreProcessingRouterData, errors::ConnectorError> {
|
||||||
let response: nuvei::NuveiPaymentsResponse = res
|
let response: NuveiPaymentsResponse = res
|
||||||
.response
|
.response
|
||||||
.parse_struct("NuveiPaymentsResponse")
|
.parse_struct("NuveiPaymentsResponse")
|
||||||
.switch()?;
|
.switch()?;
|
||||||
event_builder.map(|i| i.set_response_body(&response));
|
event_builder.map(|i| i.set_response_body(&response));
|
||||||
router_env::logger::info!(connector_response=?response);
|
router_env::logger::info!(connector_response=?response);
|
||||||
|
|
||||||
RouterData::try_from(ResponseRouterData {
|
RouterData::try_from(ResponseRouterData {
|
||||||
response,
|
response,
|
||||||
data: data.clone(),
|
data: data.clone(),
|
||||||
@ -965,7 +963,7 @@ impl ConnectorIntegration<Execute, RefundsData, RefundsResponseData> for Nuvei {
|
|||||||
event_builder: Option<&mut ConnectorEvent>,
|
event_builder: Option<&mut ConnectorEvent>,
|
||||||
res: Response,
|
res: Response,
|
||||||
) -> CustomResult<RefundsRouterData<Execute>, errors::ConnectorError> {
|
) -> CustomResult<RefundsRouterData<Execute>, errors::ConnectorError> {
|
||||||
let response: nuvei::NuveiPaymentsResponse = res
|
let response: NuveiPaymentsResponse = res
|
||||||
.response
|
.response
|
||||||
.parse_struct("NuveiPaymentsResponse")
|
.parse_struct("NuveiPaymentsResponse")
|
||||||
.switch()?;
|
.switch()?;
|
||||||
@ -1124,10 +1122,8 @@ impl IncomingWebhook for Nuvei {
|
|||||||
// Parse the webhook payload
|
// Parse the webhook payload
|
||||||
let webhook = serde_urlencoded::from_str::<nuvei::NuveiWebhook>(&request.query_params)
|
let webhook = serde_urlencoded::from_str::<nuvei::NuveiWebhook>(&request.query_params)
|
||||||
.change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;
|
.change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;
|
||||||
|
|
||||||
// Convert webhook to payments response
|
// Convert webhook to payments response
|
||||||
let payment_response = nuvei::NuveiPaymentsResponse::from(webhook);
|
let payment_response = NuveiPaymentsResponse::from(webhook);
|
||||||
|
|
||||||
Ok(Box::new(payment_response))
|
Ok(Box::new(payment_response))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -49,7 +49,8 @@ use crate::{
|
|||||||
utils::{
|
utils::{
|
||||||
self, convert_amount, missing_field_err, AddressData, AddressDetailsData,
|
self, convert_amount, missing_field_err, AddressData, AddressDetailsData,
|
||||||
BrowserInformationData, ForeignTryFrom, PaymentsAuthorizeRequestData,
|
BrowserInformationData, ForeignTryFrom, PaymentsAuthorizeRequestData,
|
||||||
PaymentsCancelRequestData, PaymentsPreProcessingRequestData, RouterData as _,
|
PaymentsCancelRequestData, PaymentsPreProcessingRequestData,
|
||||||
|
PaymentsSetupMandateRequestData, RouterData as _,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -136,9 +137,7 @@ impl NuveiAuthorizePreprocessingCommon for SetupMandateRequestData {
|
|||||||
fn get_return_url_required(
|
fn get_return_url_required(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<String, error_stack::Report<errors::ConnectorError>> {
|
) -> Result<String, error_stack::Report<errors::ConnectorError>> {
|
||||||
self.router_return_url
|
self.get_router_return_url()
|
||||||
.clone()
|
|
||||||
.ok_or_else(missing_field_err("return_url"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_capture_method(&self) -> Option<CaptureMethod> {
|
fn get_capture_method(&self) -> Option<CaptureMethod> {
|
||||||
@ -201,10 +200,6 @@ impl NuveiAuthorizePreprocessingCommon for PaymentsAuthorizeData {
|
|||||||
self.customer_id.clone()
|
self.customer_id.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_complete_authorize_url(&self) -> Option<String> {
|
|
||||||
self.complete_authorize_url.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_connector_mandate_id(&self) -> Option<String> {
|
fn get_connector_mandate_id(&self) -> Option<String> {
|
||||||
self.connector_mandate_id().clone()
|
self.connector_mandate_id().clone()
|
||||||
}
|
}
|
||||||
@ -219,6 +214,10 @@ impl NuveiAuthorizePreprocessingCommon for PaymentsAuthorizeData {
|
|||||||
self.capture_method
|
self.capture_method
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_complete_authorize_url(&self) -> Option<String> {
|
||||||
|
self.complete_authorize_url.clone()
|
||||||
|
}
|
||||||
|
|
||||||
fn get_minor_amount_required(
|
fn get_minor_amount_required(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<MinorUnit, error_stack::Report<errors::ConnectorError>> {
|
) -> Result<MinorUnit, error_stack::Report<errors::ConnectorError>> {
|
||||||
@ -273,10 +272,6 @@ impl NuveiAuthorizePreprocessingCommon for PaymentsPreProcessingData {
|
|||||||
&& self.setup_future_usage == Some(FutureUsage::OffSession)
|
&& self.setup_future_usage == Some(FutureUsage::OffSession)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_complete_authorize_url(&self) -> Option<String> {
|
|
||||||
self.complete_authorize_url.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_connector_mandate_id(&self) -> Option<String> {
|
fn get_connector_mandate_id(&self) -> Option<String> {
|
||||||
self.connector_mandate_id()
|
self.connector_mandate_id()
|
||||||
}
|
}
|
||||||
@ -291,6 +286,10 @@ impl NuveiAuthorizePreprocessingCommon for PaymentsPreProcessingData {
|
|||||||
self.capture_method
|
self.capture_method
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_complete_authorize_url(&self) -> Option<String> {
|
||||||
|
self.complete_authorize_url.clone()
|
||||||
|
}
|
||||||
|
|
||||||
fn get_minor_amount_required(
|
fn get_minor_amount_required(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<MinorUnit, error_stack::Report<errors::ConnectorError>> {
|
) -> Result<MinorUnit, error_stack::Report<errors::ConnectorError>> {
|
||||||
@ -502,7 +501,11 @@ pub struct NuveiPaymentFlowRequest {
|
|||||||
#[derive(Debug, Serialize, Default)]
|
#[derive(Debug, Serialize, Default)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct NuveiPaymentSyncRequest {
|
pub struct NuveiPaymentSyncRequest {
|
||||||
pub session_token: Secret<String>,
|
pub merchant_id: Secret<String>,
|
||||||
|
pub merchant_site_id: Secret<String>,
|
||||||
|
pub time_stamp: String,
|
||||||
|
pub checksum: Secret<String>,
|
||||||
|
pub transaction_id: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Serialize, Deserialize)]
|
#[derive(Debug, Default, Serialize, Deserialize)]
|
||||||
@ -848,9 +851,9 @@ pub struct NuveiACSResponse {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub enum LiabilityShift {
|
pub enum LiabilityShift {
|
||||||
#[serde(rename = "Y", alias = "1")]
|
#[serde(rename = "Y", alias = "1", alias = "y")]
|
||||||
Success,
|
Success,
|
||||||
#[serde(rename = "N", alias = "0")]
|
#[serde(rename = "N", alias = "0", alias = "n")]
|
||||||
Failed,
|
Failed,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1724,8 +1727,8 @@ where
|
|||||||
let shipping_address: Option<ShippingAddress> =
|
let shipping_address: Option<ShippingAddress> =
|
||||||
item.get_optional_shipping().map(|address| address.into());
|
item.get_optional_shipping().map(|address| address.into());
|
||||||
|
|
||||||
let billing_address: Option<BillingAddress> = address.map(|ref address| address.into());
|
let billing_address: Option<BillingAddress> =
|
||||||
|
address.clone().map(|ref address| address.into());
|
||||||
let device_details = if request_data
|
let device_details = if request_data
|
||||||
.device_details
|
.device_details
|
||||||
.ip_address
|
.ip_address
|
||||||
@ -1902,25 +1905,7 @@ impl TryFrom<(&types::PaymentsCompleteAuthorizeRouterData, Secret<String>)>
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Some(PaymentMethodData::Wallet(..))
|
_ => Err(errors::ConnectorError::NotImplemented(
|
||||||
| Some(PaymentMethodData::PayLater(..))
|
|
||||||
| Some(PaymentMethodData::BankDebit(..))
|
|
||||||
| Some(PaymentMethodData::BankRedirect(..))
|
|
||||||
| Some(PaymentMethodData::BankTransfer(..))
|
|
||||||
| Some(PaymentMethodData::Crypto(..))
|
|
||||||
| Some(PaymentMethodData::MandatePayment)
|
|
||||||
| Some(PaymentMethodData::GiftCard(..))
|
|
||||||
| Some(PaymentMethodData::Voucher(..))
|
|
||||||
| Some(PaymentMethodData::CardRedirect(..))
|
|
||||||
| Some(PaymentMethodData::Reward)
|
|
||||||
| Some(PaymentMethodData::RealTimePayment(..))
|
|
||||||
| Some(PaymentMethodData::MobilePayment(..))
|
|
||||||
| Some(PaymentMethodData::Upi(..))
|
|
||||||
| Some(PaymentMethodData::OpenBanking(_))
|
|
||||||
| Some(PaymentMethodData::CardToken(..))
|
|
||||||
| Some(PaymentMethodData::NetworkToken(..))
|
|
||||||
| Some(PaymentMethodData::CardDetailsForNetworkTransactionId(_))
|
|
||||||
| None => Err(errors::ConnectorError::NotImplemented(
|
|
||||||
utils::get_unimplemented_payment_method_error_message("nuvei"),
|
utils::get_unimplemented_payment_method_error_message("nuvei"),
|
||||||
)),
|
)),
|
||||||
}?;
|
}?;
|
||||||
@ -1938,7 +1923,7 @@ impl TryFrom<(&types::PaymentsCompleteAuthorizeRouterData, Secret<String>)>
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
})?;
|
})?;
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
related_transaction_id: request_data.related_transaction_id,
|
related_transaction_id: item.request.connector_transaction_id.clone(),
|
||||||
payment_option: request_data.payment_option,
|
payment_option: request_data.payment_option,
|
||||||
device_details: request_data.device_details,
|
device_details: request_data.device_details,
|
||||||
..request
|
..request
|
||||||
@ -2071,9 +2056,33 @@ impl TryFrom<&types::RefundExecuteRouterData> for NuveiPaymentFlowRequest {
|
|||||||
impl TryFrom<&types::PaymentsSyncRouterData> for NuveiPaymentSyncRequest {
|
impl TryFrom<&types::PaymentsSyncRouterData> for NuveiPaymentSyncRequest {
|
||||||
type Error = error_stack::Report<errors::ConnectorError>;
|
type Error = error_stack::Report<errors::ConnectorError>;
|
||||||
fn try_from(value: &types::PaymentsSyncRouterData) -> Result<Self, Self::Error> {
|
fn try_from(value: &types::PaymentsSyncRouterData) -> Result<Self, Self::Error> {
|
||||||
let meta: NuveiMeta = utils::to_connector_meta(value.request.connector_meta.clone())?;
|
let connector_meta: NuveiAuthType = NuveiAuthType::try_from(&value.connector_auth_type)?;
|
||||||
|
let merchant_id = connector_meta.merchant_id.clone();
|
||||||
|
let merchant_site_id = connector_meta.merchant_site_id.clone();
|
||||||
|
let merchant_secret = connector_meta.merchant_secret.clone();
|
||||||
|
let time_stamp =
|
||||||
|
date_time::format_date(date_time::now(), date_time::DateFormat::YYYYMMDDHHmmss)
|
||||||
|
.change_context(errors::ConnectorError::RequestEncodingFailed)?;
|
||||||
|
let transaction_id = value
|
||||||
|
.request
|
||||||
|
.connector_transaction_id
|
||||||
|
.clone()
|
||||||
|
.get_connector_transaction_id()
|
||||||
|
.change_context(errors::ConnectorError::MissingConnectorTransactionID)?;
|
||||||
|
let checksum = Secret::new(encode_payload(&[
|
||||||
|
merchant_id.peek(),
|
||||||
|
merchant_site_id.peek(),
|
||||||
|
&transaction_id,
|
||||||
|
&time_stamp,
|
||||||
|
merchant_secret.peek(),
|
||||||
|
])?);
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
session_token: meta.session_token,
|
merchant_id,
|
||||||
|
merchant_site_id,
|
||||||
|
time_stamp,
|
||||||
|
checksum,
|
||||||
|
transaction_id,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2189,11 +2198,17 @@ pub enum NuveiPaymentStatus {
|
|||||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
|
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
|
||||||
#[serde(rename_all = "UPPERCASE")]
|
#[serde(rename_all = "UPPERCASE")]
|
||||||
pub enum NuveiTransactionStatus {
|
pub enum NuveiTransactionStatus {
|
||||||
|
#[serde(alias = "Approved", alias = "APPROVED")]
|
||||||
Approved,
|
Approved,
|
||||||
|
#[serde(alias = "Declined", alias = "DECLINED")]
|
||||||
Declined,
|
Declined,
|
||||||
|
#[serde(alias = "Filter Error", alias = "ERROR", alias = "Error")]
|
||||||
Error,
|
Error,
|
||||||
|
#[serde(alias = "Redirect", alias = "REDIRECT")]
|
||||||
Redirect,
|
Redirect,
|
||||||
|
#[serde(alias = "Pending", alias = "PENDING")]
|
||||||
Pending,
|
Pending,
|
||||||
|
#[serde(alias = "Processing", alias = "PROCESSING")]
|
||||||
#[default]
|
#[default]
|
||||||
Processing,
|
Processing,
|
||||||
}
|
}
|
||||||
@ -2251,19 +2266,90 @@ pub struct NuveiPaymentsResponse {
|
|||||||
pub client_request_id: Option<String>,
|
pub client_request_id: Option<String>,
|
||||||
pub merchant_advice_code: Option<String>,
|
pub merchant_advice_code: Option<String>,
|
||||||
}
|
}
|
||||||
impl NuveiPaymentsResponse {
|
|
||||||
/// returns amount_captured and minor_amount_capturable
|
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||||
pub fn get_amount_captured(
|
#[serde(rename_all = "camelCase")]
|
||||||
&self,
|
pub struct NuveiTxnPartialApproval {
|
||||||
) -> Result<(Option<i64>, Option<MinorUnit>), error_stack::Report<errors::ConnectorError>> {
|
requested_amount: Option<StringMajorUnit>,
|
||||||
|
requested_currency: Option<enums::Currency>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct NuveiTransactionSyncResponseDetails {
|
||||||
|
gw_error_code: Option<i64>,
|
||||||
|
gw_error_reason: Option<String>,
|
||||||
|
gw_extended_error_code: Option<i64>,
|
||||||
|
transaction_id: Option<String>,
|
||||||
|
transaction_status: Option<NuveiTransactionStatus>,
|
||||||
|
transaction_type: Option<NuveiTransactionType>,
|
||||||
|
auth_code: Option<String>,
|
||||||
|
processed_amount: Option<StringMajorUnit>,
|
||||||
|
processed_currency: Option<enums::Currency>,
|
||||||
|
acquiring_bank_name: Option<String>,
|
||||||
|
}
|
||||||
|
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct NuveiTransactionSyncResponse {
|
||||||
|
pub payment_option: Option<PaymentOption>,
|
||||||
|
pub partial_approval: Option<NuveiTxnPartialApproval>,
|
||||||
|
pub is_currency_converted: Option<bool>,
|
||||||
|
pub transaction_details: Option<NuveiTransactionSyncResponseDetails>,
|
||||||
|
pub fraud_details: Option<FraudDetails>,
|
||||||
|
pub client_unique_id: Option<String>,
|
||||||
|
pub internal_request_id: Option<i64>,
|
||||||
|
pub status: NuveiPaymentStatus,
|
||||||
|
pub err_code: Option<i64>,
|
||||||
|
pub reason: Option<String>,
|
||||||
|
pub merchant_id: Option<Secret<String>>,
|
||||||
|
pub merchant_site_id: Option<Secret<String>>,
|
||||||
|
pub version: Option<String>,
|
||||||
|
pub client_request_id: Option<String>,
|
||||||
|
pub merchant_advice_code: Option<String>,
|
||||||
|
}
|
||||||
|
impl NuveiTransactionSyncResponse {
|
||||||
|
pub fn get_partial_approval(&self) -> Option<NuveiPartialApproval> {
|
||||||
match &self.partial_approval {
|
match &self.partial_approval {
|
||||||
|
Some(partial_approval) => match (
|
||||||
|
partial_approval.requested_amount.clone(),
|
||||||
|
partial_approval.requested_currency,
|
||||||
|
self.transaction_details
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|txn| txn.processed_amount.clone()),
|
||||||
|
self.transaction_details
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|txn| txn.processed_currency),
|
||||||
|
) {
|
||||||
|
(
|
||||||
|
Some(requested_amount),
|
||||||
|
Some(requested_currency),
|
||||||
|
Some(processed_amount),
|
||||||
|
Some(processed_currency),
|
||||||
|
) => Some(NuveiPartialApproval {
|
||||||
|
requested_amount,
|
||||||
|
requested_currency,
|
||||||
|
processed_amount,
|
||||||
|
processed_currency,
|
||||||
|
}),
|
||||||
|
_ => None,
|
||||||
|
},
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_amount_captured(
|
||||||
|
partial_approval_data: Option<NuveiPartialApproval>,
|
||||||
|
transaction_type: Option<NuveiTransactionType>,
|
||||||
|
) -> Result<(Option<i64>, Option<MinorUnit>), error_stack::Report<errors::ConnectorError>> {
|
||||||
|
match partial_approval_data {
|
||||||
Some(partial_approval) => {
|
Some(partial_approval) => {
|
||||||
let amount = utils::convert_back_amount_to_minor_units(
|
let amount = utils::convert_back_amount_to_minor_units(
|
||||||
NUVEI_AMOUNT_CONVERTOR,
|
NUVEI_AMOUNT_CONVERTOR,
|
||||||
partial_approval.processed_amount.clone(),
|
partial_approval.processed_amount.clone(),
|
||||||
partial_approval.processed_currency,
|
partial_approval.processed_currency,
|
||||||
)?;
|
)?;
|
||||||
match self.transaction_type {
|
match transaction_type {
|
||||||
None => Ok((None, None)),
|
None => Ok((None, None)),
|
||||||
Some(NuveiTransactionType::Sale) => {
|
Some(NuveiTransactionType::Sale) => {
|
||||||
Ok((Some(MinorUnit::get_amount_as_i64(amount)), None))
|
Ok((Some(MinorUnit::get_amount_as_i64(amount)), None))
|
||||||
@ -2280,7 +2366,6 @@ impl NuveiPaymentsResponse {
|
|||||||
}
|
}
|
||||||
None => Ok((None, None)),
|
None => Ok((None, None)),
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||||
@ -2301,13 +2386,15 @@ pub struct FraudDetails {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_payment_status(
|
fn get_payment_status(
|
||||||
response: &NuveiPaymentsResponse,
|
|
||||||
amount: Option<i64>,
|
amount: Option<i64>,
|
||||||
is_post_capture_void: bool,
|
is_post_capture_void: bool,
|
||||||
|
transaction_type: Option<NuveiTransactionType>,
|
||||||
|
transaction_status: Option<NuveiTransactionStatus>,
|
||||||
|
status: NuveiPaymentStatus,
|
||||||
) -> enums::AttemptStatus {
|
) -> enums::AttemptStatus {
|
||||||
// ZERO dollar authorization
|
// ZERO dollar authorization
|
||||||
if amount == Some(0) && response.transaction_type.clone() == Some(NuveiTransactionType::Auth) {
|
if amount == Some(0) && transaction_type == Some(NuveiTransactionType::Auth) {
|
||||||
return match response.transaction_status.clone() {
|
return match transaction_status {
|
||||||
Some(NuveiTransactionStatus::Approved) => enums::AttemptStatus::Charged,
|
Some(NuveiTransactionStatus::Approved) => enums::AttemptStatus::Charged,
|
||||||
Some(NuveiTransactionStatus::Declined) | Some(NuveiTransactionStatus::Error) => {
|
Some(NuveiTransactionStatus::Declined) | Some(NuveiTransactionStatus::Error) => {
|
||||||
enums::AttemptStatus::AuthorizationFailed
|
enums::AttemptStatus::AuthorizationFailed
|
||||||
@ -2316,7 +2403,7 @@ fn get_payment_status(
|
|||||||
enums::AttemptStatus::Pending
|
enums::AttemptStatus::Pending
|
||||||
}
|
}
|
||||||
Some(NuveiTransactionStatus::Redirect) => enums::AttemptStatus::AuthenticationPending,
|
Some(NuveiTransactionStatus::Redirect) => enums::AttemptStatus::AuthenticationPending,
|
||||||
None => match response.status {
|
None => match status {
|
||||||
NuveiPaymentStatus::Failed | NuveiPaymentStatus::Error => {
|
NuveiPaymentStatus::Failed | NuveiPaymentStatus::Error => {
|
||||||
enums::AttemptStatus::Failure
|
enums::AttemptStatus::Failure
|
||||||
}
|
}
|
||||||
@ -2325,10 +2412,12 @@ fn get_payment_status(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
match response.transaction_status.clone() {
|
match transaction_status {
|
||||||
Some(status) => match status {
|
Some(status) => match status {
|
||||||
NuveiTransactionStatus::Approved => match response.transaction_type {
|
NuveiTransactionStatus::Approved => match transaction_type {
|
||||||
Some(NuveiTransactionType::Auth) => enums::AttemptStatus::Authorized,
|
Some(NuveiTransactionType::InitAuth3D) | Some(NuveiTransactionType::Auth) => {
|
||||||
|
enums::AttemptStatus::Authorized
|
||||||
|
}
|
||||||
Some(NuveiTransactionType::Sale) | Some(NuveiTransactionType::Settle) => {
|
Some(NuveiTransactionType::Sale) | Some(NuveiTransactionType::Settle) => {
|
||||||
enums::AttemptStatus::Charged
|
enums::AttemptStatus::Charged
|
||||||
}
|
}
|
||||||
@ -2336,14 +2425,14 @@ fn get_payment_status(
|
|||||||
enums::AttemptStatus::VoidedPostCharge
|
enums::AttemptStatus::VoidedPostCharge
|
||||||
}
|
}
|
||||||
Some(NuveiTransactionType::Void) => enums::AttemptStatus::Voided,
|
Some(NuveiTransactionType::Void) => enums::AttemptStatus::Voided,
|
||||||
|
Some(NuveiTransactionType::Auth3D) => enums::AttemptStatus::AuthenticationPending,
|
||||||
_ => enums::AttemptStatus::Pending,
|
_ => enums::AttemptStatus::Pending,
|
||||||
},
|
},
|
||||||
NuveiTransactionStatus::Declined | NuveiTransactionStatus::Error => {
|
NuveiTransactionStatus::Declined | NuveiTransactionStatus::Error => {
|
||||||
match response.transaction_type {
|
match transaction_type {
|
||||||
Some(NuveiTransactionType::Auth) => enums::AttemptStatus::AuthorizationFailed,
|
Some(NuveiTransactionType::Auth) => enums::AttemptStatus::AuthorizationFailed,
|
||||||
Some(NuveiTransactionType::Void) => enums::AttemptStatus::VoidFailed,
|
Some(NuveiTransactionType::Void) => enums::AttemptStatus::VoidFailed,
|
||||||
Some(NuveiTransactionType::Auth3D) => {
|
Some(NuveiTransactionType::Auth3D) | Some(NuveiTransactionType::InitAuth3D) => {
|
||||||
enums::AttemptStatus::AuthenticationFailed
|
enums::AttemptStatus::AuthenticationFailed
|
||||||
}
|
}
|
||||||
_ => enums::AttemptStatus::Failure,
|
_ => enums::AttemptStatus::Failure,
|
||||||
@ -2354,37 +2443,49 @@ fn get_payment_status(
|
|||||||
}
|
}
|
||||||
NuveiTransactionStatus::Redirect => enums::AttemptStatus::AuthenticationPending,
|
NuveiTransactionStatus::Redirect => enums::AttemptStatus::AuthenticationPending,
|
||||||
},
|
},
|
||||||
None => match response.status {
|
None => match status {
|
||||||
NuveiPaymentStatus::Failed | NuveiPaymentStatus::Error => enums::AttemptStatus::Failure,
|
NuveiPaymentStatus::Failed | NuveiPaymentStatus::Error => enums::AttemptStatus::Failure,
|
||||||
_ => enums::AttemptStatus::Pending,
|
_ => enums::AttemptStatus::Pending,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_error_response(response: &NuveiPaymentsResponse, http_code: u16) -> Option<ErrorResponse> {
|
#[derive(Debug)]
|
||||||
match response.status {
|
struct ErrorResponseParams {
|
||||||
|
http_code: u16,
|
||||||
|
status: NuveiPaymentStatus,
|
||||||
|
err_code: Option<i64>,
|
||||||
|
err_msg: Option<String>,
|
||||||
|
merchant_advice_code: Option<String>,
|
||||||
|
gw_error_code: Option<i64>,
|
||||||
|
gw_error_reason: Option<String>,
|
||||||
|
transaction_status: Option<NuveiTransactionStatus>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_error_response(params: ErrorResponseParams) -> Option<ErrorResponse> {
|
||||||
|
match params.status {
|
||||||
NuveiPaymentStatus::Error => Some(get_error_response(
|
NuveiPaymentStatus::Error => Some(get_error_response(
|
||||||
response.err_code,
|
params.err_code,
|
||||||
&response.reason,
|
params.err_msg.clone(),
|
||||||
http_code,
|
params.http_code,
|
||||||
&response.merchant_advice_code,
|
params.merchant_advice_code.clone(),
|
||||||
&response.gw_error_code.map(|e| e.to_string()),
|
params.gw_error_code.map(|code| code.to_string()),
|
||||||
&response.gw_error_reason,
|
params.gw_error_reason.clone(),
|
||||||
)),
|
)),
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
let err = Some(get_error_response(
|
let err = Some(get_error_response(
|
||||||
response.gw_error_code,
|
params.gw_error_code,
|
||||||
&response.gw_error_reason,
|
params.gw_error_reason.clone(),
|
||||||
http_code,
|
params.http_code,
|
||||||
&response.merchant_advice_code,
|
params.merchant_advice_code,
|
||||||
&response.gw_error_code.map(|e| e.to_string()),
|
params.gw_error_code.map(|e| e.to_string()),
|
||||||
&response.gw_error_reason,
|
params.gw_error_reason.clone(),
|
||||||
));
|
));
|
||||||
|
|
||||||
match response.transaction_status {
|
match params.transaction_status {
|
||||||
Some(NuveiTransactionStatus::Error) | Some(NuveiTransactionStatus::Declined) => err,
|
Some(NuveiTransactionStatus::Error) | Some(NuveiTransactionStatus::Declined) => err,
|
||||||
_ => match response
|
_ => match params
|
||||||
.gw_error_reason
|
.gw_error_reason
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|r| r.eq("Missing argument"))
|
.map(|r| r.eq("Missing argument"))
|
||||||
@ -2433,11 +2534,15 @@ impl
|
|||||||
>,
|
>,
|
||||||
) -> Result<Self, Self::Error> {
|
) -> Result<Self, Self::Error> {
|
||||||
let amount = item.data.request.amount;
|
let amount = item.data.request.amount;
|
||||||
|
let response = &item.response;
|
||||||
|
let (status, redirection_data, connector_response_data) = process_nuvei_payment_response(
|
||||||
|
NuveiPaymentResponseData::new(amount, false, item.data.payment_method, response),
|
||||||
|
)?;
|
||||||
|
|
||||||
let (status, redirection_data, connector_response_data) =
|
let (amount_captured, minor_amount_capturable) = get_amount_captured(
|
||||||
process_nuvei_payment_response(&item, amount, false)?;
|
response.partial_approval.clone(),
|
||||||
|
response.transaction_type.clone(),
|
||||||
let (amount_captured, minor_amount_capturable) = item.response.get_amount_captured()?;
|
)?;
|
||||||
|
|
||||||
let ip_address = item
|
let ip_address = item
|
||||||
.data
|
.data
|
||||||
@ -2453,16 +2558,31 @@ impl
|
|||||||
field_name: "browser_info.ip_address",
|
field_name: "browser_info.ip_address",
|
||||||
})?
|
})?
|
||||||
.to_string();
|
.to_string();
|
||||||
|
let response = &item.response;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
status,
|
status,
|
||||||
response: if let Some(err) = build_error_response(&item.response, item.http_code) {
|
response: if let Some(err) = build_error_response(ErrorResponseParams {
|
||||||
|
http_code: item.http_code,
|
||||||
|
status: response.status.clone(),
|
||||||
|
err_code: response.err_code,
|
||||||
|
err_msg: response.reason.clone(),
|
||||||
|
merchant_advice_code: response.merchant_advice_code.clone(),
|
||||||
|
gw_error_code: response.gw_error_code,
|
||||||
|
gw_error_reason: response.gw_error_reason.clone(),
|
||||||
|
transaction_status: response.transaction_status.clone(),
|
||||||
|
}) {
|
||||||
Err(err)
|
Err(err)
|
||||||
} else {
|
} else {
|
||||||
|
let response = &item.response;
|
||||||
Ok(create_transaction_response(
|
Ok(create_transaction_response(
|
||||||
&item.response,
|
|
||||||
redirection_data,
|
redirection_data,
|
||||||
Some(ip_address),
|
Some(ip_address),
|
||||||
|
response.transaction_id.clone(),
|
||||||
|
response.order_id.clone(),
|
||||||
|
response.session_token.clone(),
|
||||||
|
response.external_scheme_transaction_id.clone(),
|
||||||
|
response.payment_option.clone(),
|
||||||
)?)
|
)?)
|
||||||
},
|
},
|
||||||
amount_captured,
|
amount_captured,
|
||||||
@ -2475,10 +2595,64 @@ impl
|
|||||||
|
|
||||||
// Helper function to process Nuvei payment response
|
// Helper function to process Nuvei payment response
|
||||||
|
|
||||||
fn process_nuvei_payment_response<F, T>(
|
/// Struct to encapsulate parameters for processing Nuvei payment responses
|
||||||
item: &ResponseRouterData<F, NuveiPaymentsResponse, T, PaymentsResponseData>,
|
#[derive(Debug)]
|
||||||
|
pub struct NuveiPaymentResponseData {
|
||||||
|
pub amount: Option<i64>,
|
||||||
|
pub is_post_capture_void: bool,
|
||||||
|
pub payment_method: enums::PaymentMethod,
|
||||||
|
pub payment_option: Option<PaymentOption>,
|
||||||
|
pub transaction_type: Option<NuveiTransactionType>,
|
||||||
|
pub transaction_status: Option<NuveiTransactionStatus>,
|
||||||
|
pub status: NuveiPaymentStatus,
|
||||||
|
pub merchant_advice_code: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NuveiPaymentResponseData {
|
||||||
|
pub fn new(
|
||||||
amount: Option<i64>,
|
amount: Option<i64>,
|
||||||
is_post_capture_void: bool,
|
is_post_capture_void: bool,
|
||||||
|
payment_method: enums::PaymentMethod,
|
||||||
|
response: &NuveiPaymentsResponse,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
amount,
|
||||||
|
is_post_capture_void,
|
||||||
|
payment_method,
|
||||||
|
payment_option: response.payment_option.clone(),
|
||||||
|
transaction_type: response.transaction_type.clone(),
|
||||||
|
transaction_status: response.transaction_status.clone(),
|
||||||
|
status: response.status.clone(),
|
||||||
|
merchant_advice_code: response.merchant_advice_code.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_from_sync_response(
|
||||||
|
amount: Option<i64>,
|
||||||
|
is_post_capture_void: bool,
|
||||||
|
payment_method: enums::PaymentMethod,
|
||||||
|
response: &NuveiTransactionSyncResponse,
|
||||||
|
) -> Self {
|
||||||
|
let transaction_details = &response.transaction_details;
|
||||||
|
Self {
|
||||||
|
amount,
|
||||||
|
is_post_capture_void,
|
||||||
|
payment_method,
|
||||||
|
payment_option: response.payment_option.clone(),
|
||||||
|
transaction_type: transaction_details
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|details| details.transaction_type.clone()),
|
||||||
|
transaction_status: transaction_details
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|details| details.transaction_status.clone()),
|
||||||
|
status: response.status.clone(),
|
||||||
|
merchant_advice_code: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_nuvei_payment_response(
|
||||||
|
data: NuveiPaymentResponseData,
|
||||||
) -> Result<
|
) -> Result<
|
||||||
(
|
(
|
||||||
enums::AttemptStatus,
|
enums::AttemptStatus,
|
||||||
@ -2486,20 +2660,14 @@ fn process_nuvei_payment_response<F, T>(
|
|||||||
Option<ConnectorResponseData>,
|
Option<ConnectorResponseData>,
|
||||||
),
|
),
|
||||||
error_stack::Report<errors::ConnectorError>,
|
error_stack::Report<errors::ConnectorError>,
|
||||||
>
|
> {
|
||||||
where
|
let redirection_data = match data.payment_method {
|
||||||
F: std::fmt::Debug,
|
enums::PaymentMethod::Wallet | enums::PaymentMethod::BankRedirect => data
|
||||||
T: std::fmt::Debug,
|
|
||||||
{
|
|
||||||
let redirection_data = match item.data.payment_method {
|
|
||||||
enums::PaymentMethod::Wallet | enums::PaymentMethod::BankRedirect => item
|
|
||||||
.response
|
|
||||||
.payment_option
|
.payment_option
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|po| po.redirect_url.clone())
|
.and_then(|po| po.redirect_url.clone())
|
||||||
.map(|base_url| RedirectForm::from((base_url, Method::Get))),
|
.map(|base_url| RedirectForm::from((base_url, Method::Get))),
|
||||||
_ => item
|
_ => data
|
||||||
.response
|
|
||||||
.payment_option
|
.payment_option
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|o| o.card.clone())
|
.and_then(|o| o.card.clone())
|
||||||
@ -2511,32 +2679,42 @@ where
|
|||||||
form_fields: std::collections::HashMap::from([("creq".to_string(), creq.expose())]),
|
form_fields: std::collections::HashMap::from([("creq".to_string(), creq.expose())]),
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
let connector_response_data =
|
|
||||||
convert_to_additional_payment_method_connector_response(&item.response)
|
|
||||||
.map(ConnectorResponseData::with_additional_payment_method_data);
|
|
||||||
|
|
||||||
let status = get_payment_status(&item.response, amount, is_post_capture_void);
|
let connector_response_data = convert_to_additional_payment_method_connector_response(
|
||||||
|
data.payment_option.clone(),
|
||||||
|
data.merchant_advice_code,
|
||||||
|
)
|
||||||
|
.map(ConnectorResponseData::with_additional_payment_method_data);
|
||||||
|
let status = get_payment_status(
|
||||||
|
data.amount,
|
||||||
|
data.is_post_capture_void,
|
||||||
|
data.transaction_type,
|
||||||
|
data.transaction_status,
|
||||||
|
data.status,
|
||||||
|
);
|
||||||
|
|
||||||
Ok((status, redirection_data, connector_response_data))
|
Ok((status, redirection_data, connector_response_data))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to create transaction response
|
// Helper function to create transaction response
|
||||||
fn create_transaction_response(
|
fn create_transaction_response(
|
||||||
response: &NuveiPaymentsResponse,
|
|
||||||
redirection_data: Option<RedirectForm>,
|
redirection_data: Option<RedirectForm>,
|
||||||
ip_address: Option<String>,
|
ip_address: Option<String>,
|
||||||
|
transaction_id: Option<String>,
|
||||||
|
order_id: Option<String>,
|
||||||
|
session_token: Option<Secret<String>>,
|
||||||
|
external_scheme_transaction_id: Option<Secret<String>>,
|
||||||
|
payment_option: Option<PaymentOption>,
|
||||||
) -> Result<PaymentsResponseData, error_stack::Report<errors::ConnectorError>> {
|
) -> Result<PaymentsResponseData, error_stack::Report<errors::ConnectorError>> {
|
||||||
Ok(PaymentsResponseData::TransactionResponse {
|
Ok(PaymentsResponseData::TransactionResponse {
|
||||||
resource_id: response
|
resource_id: transaction_id
|
||||||
.transaction_id
|
|
||||||
.clone()
|
.clone()
|
||||||
.map_or(response.order_id.clone(), Some) // For paypal there will be no transaction_id, only order_id will be present
|
.map_or(order_id.clone(), Some) // For paypal there will be no transaction_id, only order_id will be present
|
||||||
.map(ResponseId::ConnectorTransactionId)
|
.map(ResponseId::ConnectorTransactionId)
|
||||||
.ok_or(errors::ConnectorError::MissingConnectorTransactionID)?,
|
.ok_or(errors::ConnectorError::MissingConnectorTransactionID)?,
|
||||||
redirection_data: Box::new(redirection_data),
|
redirection_data: Box::new(redirection_data),
|
||||||
mandate_reference: Box::new(
|
mandate_reference: Box::new(
|
||||||
response
|
payment_option
|
||||||
.payment_option
|
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|po| po.user_payment_option_id.clone())
|
.and_then(|po| po.user_payment_option_id.clone())
|
||||||
.map(|id| MandateReference {
|
.map(|id| MandateReference {
|
||||||
@ -2548,7 +2726,7 @@ fn create_transaction_response(
|
|||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
// we don't need to save session token for capture, void flow so ignoring if it is not present
|
// we don't need to save session token for capture, void flow so ignoring if it is not present
|
||||||
connector_metadata: if let Some(token) = response.session_token.clone() {
|
connector_metadata: if let Some(token) = session_token {
|
||||||
Some(
|
Some(
|
||||||
serde_json::to_value(NuveiMeta {
|
serde_json::to_value(NuveiMeta {
|
||||||
session_token: token,
|
session_token: token,
|
||||||
@ -2558,11 +2736,10 @@ fn create_transaction_response(
|
|||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
network_txn_id: response
|
network_txn_id: external_scheme_transaction_id
|
||||||
.external_scheme_transaction_id
|
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|ntid| ntid.clone().expose()),
|
.map(|ntid| ntid.clone().expose()),
|
||||||
connector_response_reference_id: response.order_id.clone(),
|
connector_response_reference_id: order_id.clone(),
|
||||||
incremental_authorization_allowed: None,
|
incremental_authorization_allowed: None,
|
||||||
charges: None,
|
charges: None,
|
||||||
})
|
})
|
||||||
@ -2590,11 +2767,15 @@ impl
|
|||||||
) -> Result<Self, Self::Error> {
|
) -> Result<Self, Self::Error> {
|
||||||
// Get amount directly from the authorize data
|
// Get amount directly from the authorize data
|
||||||
let amount = Some(item.data.request.amount);
|
let amount = Some(item.data.request.amount);
|
||||||
|
let response = &item.response;
|
||||||
|
let (status, redirection_data, connector_response_data) = process_nuvei_payment_response(
|
||||||
|
NuveiPaymentResponseData::new(amount, false, item.data.payment_method, response),
|
||||||
|
)?;
|
||||||
|
|
||||||
let (status, redirection_data, connector_response_data) =
|
let (amount_captured, minor_amount_capturable) = get_amount_captured(
|
||||||
process_nuvei_payment_response(&item, amount, false)?;
|
response.partial_approval.clone(),
|
||||||
|
response.transaction_type.clone(),
|
||||||
let (amount_captured, minor_amount_capturable) = item.response.get_amount_captured()?;
|
)?;
|
||||||
|
|
||||||
let ip_address = item
|
let ip_address = item
|
||||||
.data
|
.data
|
||||||
@ -2605,13 +2786,27 @@ impl
|
|||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
status,
|
status,
|
||||||
response: if let Some(err) = build_error_response(&item.response, item.http_code) {
|
response: if let Some(err) = build_error_response(ErrorResponseParams {
|
||||||
|
http_code: item.http_code,
|
||||||
|
status: response.status.clone(),
|
||||||
|
err_code: response.err_code,
|
||||||
|
err_msg: response.reason.clone(),
|
||||||
|
merchant_advice_code: response.merchant_advice_code.clone(),
|
||||||
|
gw_error_code: response.gw_error_code,
|
||||||
|
gw_error_reason: response.gw_error_reason.clone(),
|
||||||
|
transaction_status: response.transaction_status.clone(),
|
||||||
|
}) {
|
||||||
Err(err)
|
Err(err)
|
||||||
} else {
|
} else {
|
||||||
|
let response = &item.response;
|
||||||
Ok(create_transaction_response(
|
Ok(create_transaction_response(
|
||||||
&item.response,
|
|
||||||
redirection_data,
|
redirection_data,
|
||||||
ip_address,
|
ip_address,
|
||||||
|
response.transaction_id.clone(),
|
||||||
|
response.order_id.clone(),
|
||||||
|
response.session_token.clone(),
|
||||||
|
response.external_scheme_transaction_id.clone(),
|
||||||
|
response.payment_option.clone(),
|
||||||
)?)
|
)?)
|
||||||
},
|
},
|
||||||
amount_captured,
|
amount_captured,
|
||||||
@ -2638,19 +2833,113 @@ where
|
|||||||
.data
|
.data
|
||||||
.minor_amount_capturable
|
.minor_amount_capturable
|
||||||
.map(|amount| amount.get_amount_as_i64());
|
.map(|amount| amount.get_amount_as_i64());
|
||||||
|
let response = &item.response;
|
||||||
let (status, redirection_data, connector_response_data) =
|
let (status, redirection_data, connector_response_data) =
|
||||||
process_nuvei_payment_response(&item, amount, F::is_post_capture_void())?;
|
process_nuvei_payment_response(NuveiPaymentResponseData::new(
|
||||||
|
amount,
|
||||||
|
F::is_post_capture_void(),
|
||||||
|
item.data.payment_method,
|
||||||
|
response,
|
||||||
|
))?;
|
||||||
|
|
||||||
let (amount_captured, minor_amount_capturable) = item.response.get_amount_captured()?;
|
let (amount_captured, minor_amount_capturable) = get_amount_captured(
|
||||||
|
response.partial_approval.clone(),
|
||||||
|
response.transaction_type.clone(),
|
||||||
|
)?;
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
status,
|
status,
|
||||||
response: if let Some(err) = build_error_response(&item.response, item.http_code) {
|
response: if let Some(err) = build_error_response(ErrorResponseParams {
|
||||||
|
http_code: item.http_code,
|
||||||
|
status: response.status.clone(),
|
||||||
|
err_code: response.err_code,
|
||||||
|
err_msg: response.reason.clone(),
|
||||||
|
merchant_advice_code: response.merchant_advice_code.clone(),
|
||||||
|
gw_error_code: response.gw_error_code,
|
||||||
|
gw_error_reason: response.gw_error_reason.clone(),
|
||||||
|
transaction_status: response.transaction_status.clone(),
|
||||||
|
}) {
|
||||||
|
Err(err)
|
||||||
|
} else {
|
||||||
|
let response = &item.response;
|
||||||
|
Ok(create_transaction_response(
|
||||||
|
redirection_data,
|
||||||
|
None,
|
||||||
|
response.transaction_id.clone(),
|
||||||
|
response.order_id.clone(),
|
||||||
|
response.session_token.clone(),
|
||||||
|
response.external_scheme_transaction_id.clone(),
|
||||||
|
response.payment_option.clone(),
|
||||||
|
)?)
|
||||||
|
},
|
||||||
|
amount_captured,
|
||||||
|
minor_amount_capturable,
|
||||||
|
connector_response: connector_response_data,
|
||||||
|
..item.data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generic implementation for other flow types
|
||||||
|
impl<F, T> TryFrom<ResponseRouterData<F, NuveiTransactionSyncResponse, T, PaymentsResponseData>>
|
||||||
|
for RouterData<F, T, PaymentsResponseData>
|
||||||
|
where
|
||||||
|
F: NuveiPaymentsGenericResponse + std::fmt::Debug,
|
||||||
|
T: std::fmt::Debug,
|
||||||
|
F: std::any::Any,
|
||||||
|
{
|
||||||
|
type Error = error_stack::Report<errors::ConnectorError>;
|
||||||
|
fn try_from(
|
||||||
|
item: ResponseRouterData<F, NuveiTransactionSyncResponse, T, PaymentsResponseData>,
|
||||||
|
) -> Result<Self, Self::Error> {
|
||||||
|
let amount = item
|
||||||
|
.data
|
||||||
|
.minor_amount_capturable
|
||||||
|
.map(|amount| amount.get_amount_as_i64());
|
||||||
|
let response = &item.response;
|
||||||
|
let transaction_details = &response.transaction_details;
|
||||||
|
let transaction_type = transaction_details
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|details| details.transaction_type.clone());
|
||||||
|
let (status, redirection_data, connector_response_data) =
|
||||||
|
process_nuvei_payment_response(NuveiPaymentResponseData::new_from_sync_response(
|
||||||
|
amount,
|
||||||
|
F::is_post_capture_void(),
|
||||||
|
item.data.payment_method,
|
||||||
|
response,
|
||||||
|
))?;
|
||||||
|
|
||||||
|
let (amount_captured, minor_amount_capturable) =
|
||||||
|
get_amount_captured(response.get_partial_approval(), transaction_type.clone())?;
|
||||||
|
Ok(Self {
|
||||||
|
status,
|
||||||
|
response: if let Some(err) = build_error_response(ErrorResponseParams {
|
||||||
|
http_code: item.http_code,
|
||||||
|
status: response.status.clone(),
|
||||||
|
err_code: response.err_code,
|
||||||
|
err_msg: response.reason.clone(),
|
||||||
|
merchant_advice_code: None,
|
||||||
|
gw_error_code: transaction_details
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|details| details.gw_error_code),
|
||||||
|
gw_error_reason: transaction_details
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|details| details.gw_error_reason.clone()),
|
||||||
|
transaction_status: transaction_details
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|details| details.transaction_status.clone()),
|
||||||
|
}) {
|
||||||
Err(err)
|
Err(err)
|
||||||
} else {
|
} else {
|
||||||
Ok(create_transaction_response(
|
Ok(create_transaction_response(
|
||||||
&item.response,
|
|
||||||
redirection_data,
|
redirection_data,
|
||||||
None,
|
None,
|
||||||
|
transaction_details
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|data| data.transaction_id.clone()),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
response.payment_option.clone(),
|
||||||
)?)
|
)?)
|
||||||
},
|
},
|
||||||
amount_captured,
|
amount_captured,
|
||||||
@ -2678,12 +2967,17 @@ impl TryFrom<PaymentsPreprocessingResponseRouterData<NuveiPaymentsResponse>>
|
|||||||
.map(to_boolean)
|
.map(to_boolean)
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
status: get_payment_status(&response, item.data.request.amount, false),
|
status: get_payment_status(
|
||||||
|
item.data.request.amount,
|
||||||
|
false,
|
||||||
|
response.transaction_type,
|
||||||
|
response.transaction_status,
|
||||||
|
response.status,
|
||||||
|
),
|
||||||
response: Ok(PaymentsResponseData::ThreeDSEnrollmentResponse {
|
response: Ok(PaymentsResponseData::ThreeDSEnrollmentResponse {
|
||||||
enrolled_v2: is_enrolled_for_3ds,
|
enrolled_v2: is_enrolled_for_3ds,
|
||||||
related_transaction_id: response.transaction_id,
|
related_transaction_id: response.transaction_id,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
..item.data
|
..item.data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -2760,11 +3054,7 @@ where
|
|||||||
.request
|
.request
|
||||||
.get_customer_id_required()
|
.get_customer_id_required()
|
||||||
.ok_or(missing_field_err("customer_id")())?;
|
.ok_or(missing_field_err("customer_id")())?;
|
||||||
let related_transaction_id = if item.is_three_ds() {
|
let related_transaction_id = item.request.get_related_transaction_id().clone();
|
||||||
item.request.get_related_transaction_id().clone()
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let ip_address = data
|
let ip_address = data
|
||||||
.recurring_mandate_payment_data
|
.recurring_mandate_payment_data
|
||||||
@ -2823,20 +3113,20 @@ fn get_refund_response(
|
|||||||
match response.status {
|
match response.status {
|
||||||
NuveiPaymentStatus::Error => Err(Box::new(get_error_response(
|
NuveiPaymentStatus::Error => Err(Box::new(get_error_response(
|
||||||
response.err_code,
|
response.err_code,
|
||||||
&response.reason,
|
response.reason.clone(),
|
||||||
http_code,
|
http_code,
|
||||||
&response.merchant_advice_code,
|
response.merchant_advice_code,
|
||||||
&response.gw_error_code.map(|e| e.to_string()),
|
response.gw_error_code.map(|e| e.to_string()),
|
||||||
&response.gw_error_reason,
|
response.gw_error_reason,
|
||||||
))),
|
))),
|
||||||
_ => match response.transaction_status {
|
_ => match response.transaction_status {
|
||||||
Some(NuveiTransactionStatus::Error) => Err(Box::new(get_error_response(
|
Some(NuveiTransactionStatus::Error) => Err(Box::new(get_error_response(
|
||||||
response.err_code,
|
response.err_code,
|
||||||
&response.reason,
|
response.reason,
|
||||||
http_code,
|
http_code,
|
||||||
&response.merchant_advice_code,
|
response.merchant_advice_code,
|
||||||
&response.gw_error_code.map(|e| e.to_string()),
|
response.gw_error_code.map(|e| e.to_string()),
|
||||||
&response.gw_error_reason,
|
response.gw_error_reason,
|
||||||
))),
|
))),
|
||||||
_ => Ok(RefundsResponseData {
|
_ => Ok(RefundsResponseData {
|
||||||
connector_refund_id: txn_id,
|
connector_refund_id: txn_id,
|
||||||
@ -2848,11 +3138,11 @@ fn get_refund_response(
|
|||||||
|
|
||||||
fn get_error_response(
|
fn get_error_response(
|
||||||
error_code: Option<i64>,
|
error_code: Option<i64>,
|
||||||
error_msg: &Option<String>,
|
error_msg: Option<String>,
|
||||||
http_code: u16,
|
http_code: u16,
|
||||||
network_advice_code: &Option<String>,
|
network_advice_code: Option<String>,
|
||||||
network_decline_code: &Option<String>,
|
network_decline_code: Option<String>,
|
||||||
network_error_message: &Option<String>,
|
network_error_message: Option<String>,
|
||||||
) -> ErrorResponse {
|
) -> ErrorResponse {
|
||||||
ErrorResponse {
|
ErrorResponse {
|
||||||
code: error_code
|
code: error_code
|
||||||
@ -3049,6 +3339,7 @@ impl From<NuveiWebhook> for NuveiPaymentsResponse {
|
|||||||
TransactionStatus::Declined => NuveiTransactionStatus::Declined,
|
TransactionStatus::Declined => NuveiTransactionStatus::Declined,
|
||||||
TransactionStatus::Error => NuveiTransactionStatus::Error,
|
TransactionStatus::Error => NuveiTransactionStatus::Error,
|
||||||
TransactionStatus::Settled => NuveiTransactionStatus::Approved,
|
TransactionStatus::Settled => NuveiTransactionStatus::Approved,
|
||||||
|
|
||||||
_ => NuveiTransactionStatus::Processing,
|
_ => NuveiTransactionStatus::Processing,
|
||||||
}),
|
}),
|
||||||
transaction_id: notification.transaction_id,
|
transaction_id: notification.transaction_id,
|
||||||
@ -3116,21 +3407,17 @@ pub fn concat_strings(strings: &[String]) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn convert_to_additional_payment_method_connector_response(
|
fn convert_to_additional_payment_method_connector_response(
|
||||||
transaction_response: &NuveiPaymentsResponse,
|
payment_option: Option<PaymentOption>,
|
||||||
|
merchant_advice_code: Option<String>,
|
||||||
) -> Option<AdditionalPaymentMethodConnectorResponse> {
|
) -> Option<AdditionalPaymentMethodConnectorResponse> {
|
||||||
let card = transaction_response
|
let card = payment_option.as_ref()?.card.as_ref()?;
|
||||||
.payment_option
|
|
||||||
.as_ref()?
|
|
||||||
.card
|
|
||||||
.as_ref()?;
|
|
||||||
let avs_code = card.avs_code.as_ref();
|
let avs_code = card.avs_code.as_ref();
|
||||||
let cvv2_code = card.cvv2_reply.as_ref();
|
let cvv2_code = card.cvv2_reply.as_ref();
|
||||||
let merchant_advice_code = transaction_response.merchant_advice_code.as_ref();
|
|
||||||
|
|
||||||
let avs_description = avs_code.and_then(|code| get_avs_response_description(code));
|
let avs_description = avs_code.and_then(|code| get_avs_response_description(code));
|
||||||
let cvv_description = cvv2_code.and_then(|code| get_cvv2_response_description(code));
|
let cvv_description = cvv2_code.and_then(|code| get_cvv2_response_description(code));
|
||||||
let merchant_advice_description =
|
let merchant_advice_description = merchant_advice_code
|
||||||
merchant_advice_code.and_then(|code| get_merchant_advice_code_description(code));
|
.as_ref()
|
||||||
|
.and_then(|code| get_merchant_advice_code_description(code));
|
||||||
|
|
||||||
let payment_checks = serde_json::json!({
|
let payment_checks = serde_json::json!({
|
||||||
"avs_result": avs_code,
|
"avs_result": avs_code,
|
||||||
|
|||||||
@ -38,7 +38,7 @@ const multiUseMandateData = {
|
|||||||
// Payment method data objects for responses
|
// Payment method data objects for responses
|
||||||
const payment_method_data_no3ds = {
|
const payment_method_data_no3ds = {
|
||||||
card: {
|
card: {
|
||||||
authentication_data: {},
|
authentication_data: { challengePreferenceReason: "12" },
|
||||||
last4: "1111",
|
last4: "1111",
|
||||||
card_type: "CREDIT",
|
card_type: "CREDIT",
|
||||||
card_network: "Visa",
|
card_network: "Visa",
|
||||||
|
|||||||
Reference in New Issue
Block a user