From 781f024096973cb58566765a83a3a9c610d48a34 Mon Sep 17 00:00:00 2001 From: Prasunna Soppa <70575890+prasunna09@users.noreply.github.com> Date: Mon, 5 Feb 2024 18:25:56 +0530 Subject: [PATCH] fix(connector): [NMI] Handle empty response in psync and error response in complete authorize (#3550) --- .../router/src/connector/nmi/transformers.rs | 93 +++++++++---------- crates/router/src/services/api.rs | 12 +++ 2 files changed, 55 insertions(+), 50 deletions(-) diff --git a/crates/router/src/connector/nmi/transformers.rs b/crates/router/src/connector/nmi/transformers.rs index 5b486aae600c..9dce4960f3a6 100644 --- a/crates/router/src/connector/nmi/transformers.rs +++ b/crates/router/src/connector/nmi/transformers.rs @@ -2,7 +2,7 @@ use api_models::webhooks; use cards::CardNumber; use common_utils::{errors::CustomResult, ext_traits::XmlExt}; use error_stack::{IntoReport, Report, ResultExt}; -use masking::{ExposeInterface, Secret}; +use masking::{ExposeInterface, PeekInterface, Secret}; use serde::{Deserialize, Serialize}; use crate::{ @@ -141,7 +141,7 @@ fn get_card_details( pub struct NmiVaultResponse { pub response: Response, pub responsetext: String, - pub customer_vault_id: Option, + pub customer_vault_id: Option>, pub response_code: String, pub transactionid: String, } @@ -191,11 +191,14 @@ impl )? .to_string(), currency: currency_data, - customer_vault_id: item.response.customer_vault_id.ok_or( - errors::ConnectorError::MissingRequiredField { + customer_vault_id: item + .response + .customer_vault_id + .ok_or(errors::ConnectorError::MissingRequiredField { field_name: "customer_vault_id", - }, - )?, + })? + .peek() + .to_string(), public_key: auth_type.public_key.ok_or( errors::ConnectorError::InvalidConnectorConfig { config: "public_key", @@ -237,40 +240,27 @@ pub struct NmiCompleteRequest { #[serde(rename = "type")] transaction_type: TransactionType, security_key: Secret, - orderid: String, + orderid: Option, ccnumber: CardNumber, ccexp: Secret, - cardholder_auth: CardHolderAuthType, - cavv: String, - xid: String, - three_ds_version: Option, -} - -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "lowercase")] -pub enum CardHolderAuthType { - Verified, - Attempted, -} - -#[derive(Debug, Serialize, Deserialize)] -pub enum ThreeDsVersion { - #[serde(rename = "2.0.0")] - VersionTwo, - #[serde(rename = "2.1.0")] - VersionTwoPointOne, - #[serde(rename = "2.2.0")] - VersionTwoPointTwo, + cardholder_auth: Option, + cavv: Option, + xid: Option, + eci: Option, + three_ds_version: Option, + directory_server_id: Option, } #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct NmiRedirectResponseData { - cavv: String, - xid: String, - card_holder_auth: CardHolderAuthType, - three_ds_version: Option, - order_id: String, + cavv: Option, + xid: Option, + eci: Option, + card_holder_auth: Option, + three_ds_version: Option, + order_id: Option, + directory_server_id: Option, } impl TryFrom<&NmiRouterData<&types::PaymentsCompleteAuthorizeRouterData>> for NmiCompleteRequest { @@ -308,7 +298,9 @@ impl TryFrom<&NmiRouterData<&types::PaymentsCompleteAuthorizeRouterData>> for Nm cardholder_auth: three_ds_data.card_holder_auth, cavv: three_ds_data.cavv, xid: three_ds_data.xid, + eci: three_ds_data.eci, three_ds_version: three_ds_data.three_ds_version, + directory_server_id: three_ds_data.directory_server_id, }) } } @@ -881,21 +873,22 @@ impl TryFrom> item: types::PaymentsSyncResponseRouterData, ) -> Result { let response = SyncResponse::try_from(item.response.response.to_vec())?; - Ok(Self { - status: enums::AttemptStatus::from(NmiStatus::from(response.transaction.condition)), - response: Ok(types::PaymentsResponseData::TransactionResponse { - resource_id: types::ResponseId::ConnectorTransactionId( - response.transaction.transaction_id, - ), - redirection_data: None, - mandate_reference: None, - connector_metadata: None, - network_txn_id: None, - connector_response_reference_id: None, - incremental_authorization_allowed: None, + match response.transaction { + Some(trn) => Ok(Self { + status: enums::AttemptStatus::from(NmiStatus::from(trn.condition)), + response: Ok(types::PaymentsResponseData::TransactionResponse { + resource_id: types::ResponseId::ConnectorTransactionId(trn.transaction_id), + redirection_data: None, + mandate_reference: None, + connector_metadata: None, + network_txn_id: None, + connector_response_reference_id: None, + incremental_authorization_allowed: None, + }), + ..item.data }), - ..item.data - }) + None => Ok(Self { ..item.data }), //when there is empty connector response i.e. response we get in psync when payment status is in authentication_pending + } } } @@ -1081,7 +1074,7 @@ pub struct SyncTransactionResponse { #[derive(Debug, Deserialize, Serialize)] pub struct SyncResponse { - pub transaction: SyncTransactionResponse, + pub transaction: Option, } #[derive(Debug, Deserialize)] @@ -1199,10 +1192,10 @@ pub struct NmiWebhookObject { impl TryFrom<&NmiWebhookBody> for SyncResponse { type Error = Error; fn try_from(item: &NmiWebhookBody) -> Result { - let transaction = SyncTransactionResponse { + let transaction = Some(SyncTransactionResponse { transaction_id: item.event_body.transaction_id.to_owned(), condition: item.event_body.condition.to_owned(), - }; + }); Ok(Self { transaction }) } diff --git a/crates/router/src/services/api.rs b/crates/router/src/services/api.rs index aec0b9bde9e9..13f57cafc678 100644 --- a/crates/router/src/services/api.rs +++ b/crates/router/src/services/api.rs @@ -1715,6 +1715,18 @@ pub fn build_redirection_form( item2.value=e.xid; responseForm.appendChild(item2); + var item6=document.createElement('input'); + item6.type='hidden'; + item6.name='eci'; + item6.value=e.eci; + responseForm.appendChild(item6); + + var item7=document.createElement('input'); + item7.type='hidden'; + item7.name='directoryServerId'; + item7.value=e.directoryServerId; + responseForm.appendChild(item7); + var item3=document.createElement('input'); item3.type='hidden'; item3.name='cardHolderAuth';