mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-29 17:19:15 +08:00
fix(connector): [NMI] Handle empty response in psync and error response in complete authorize (#3548)
This commit is contained in:
@ -2,7 +2,7 @@ use api_models::webhooks;
|
|||||||
use cards::CardNumber;
|
use cards::CardNumber;
|
||||||
use common_utils::{errors::CustomResult, ext_traits::XmlExt};
|
use common_utils::{errors::CustomResult, ext_traits::XmlExt};
|
||||||
use error_stack::{IntoReport, Report, ResultExt};
|
use error_stack::{IntoReport, Report, ResultExt};
|
||||||
use masking::{ExposeInterface, Secret};
|
use masking::{ExposeInterface, PeekInterface, Secret};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -141,7 +141,7 @@ fn get_card_details(
|
|||||||
pub struct NmiVaultResponse {
|
pub struct NmiVaultResponse {
|
||||||
pub response: Response,
|
pub response: Response,
|
||||||
pub responsetext: String,
|
pub responsetext: String,
|
||||||
pub customer_vault_id: Option<String>,
|
pub customer_vault_id: Option<Secret<String>>,
|
||||||
pub response_code: String,
|
pub response_code: String,
|
||||||
pub transactionid: String,
|
pub transactionid: String,
|
||||||
}
|
}
|
||||||
@ -191,11 +191,14 @@ impl
|
|||||||
)?
|
)?
|
||||||
.to_string(),
|
.to_string(),
|
||||||
currency: currency_data,
|
currency: currency_data,
|
||||||
customer_vault_id: item.response.customer_vault_id.ok_or(
|
customer_vault_id: item
|
||||||
errors::ConnectorError::MissingRequiredField {
|
.response
|
||||||
|
.customer_vault_id
|
||||||
|
.ok_or(errors::ConnectorError::MissingRequiredField {
|
||||||
field_name: "customer_vault_id",
|
field_name: "customer_vault_id",
|
||||||
},
|
})?
|
||||||
)?,
|
.peek()
|
||||||
|
.to_string(),
|
||||||
public_key: auth_type.public_key.ok_or(
|
public_key: auth_type.public_key.ok_or(
|
||||||
errors::ConnectorError::InvalidConnectorConfig {
|
errors::ConnectorError::InvalidConnectorConfig {
|
||||||
config: "public_key",
|
config: "public_key",
|
||||||
@ -237,40 +240,27 @@ pub struct NmiCompleteRequest {
|
|||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
transaction_type: TransactionType,
|
transaction_type: TransactionType,
|
||||||
security_key: Secret<String>,
|
security_key: Secret<String>,
|
||||||
orderid: String,
|
orderid: Option<String>,
|
||||||
ccnumber: CardNumber,
|
ccnumber: CardNumber,
|
||||||
ccexp: Secret<String>,
|
ccexp: Secret<String>,
|
||||||
cardholder_auth: CardHolderAuthType,
|
cardholder_auth: Option<String>,
|
||||||
cavv: String,
|
cavv: Option<String>,
|
||||||
xid: String,
|
xid: Option<String>,
|
||||||
three_ds_version: Option<ThreeDsVersion>,
|
eci: Option<String>,
|
||||||
}
|
three_ds_version: Option<String>,
|
||||||
|
directory_server_id: Option<String>,
|
||||||
#[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,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct NmiRedirectResponseData {
|
pub struct NmiRedirectResponseData {
|
||||||
cavv: String,
|
cavv: Option<String>,
|
||||||
xid: String,
|
xid: Option<String>,
|
||||||
card_holder_auth: CardHolderAuthType,
|
eci: Option<String>,
|
||||||
three_ds_version: Option<ThreeDsVersion>,
|
card_holder_auth: Option<String>,
|
||||||
order_id: String,
|
three_ds_version: Option<String>,
|
||||||
|
order_id: Option<String>,
|
||||||
|
directory_server_id: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<&NmiRouterData<&types::PaymentsCompleteAuthorizeRouterData>> for NmiCompleteRequest {
|
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,
|
cardholder_auth: three_ds_data.card_holder_auth,
|
||||||
cavv: three_ds_data.cavv,
|
cavv: three_ds_data.cavv,
|
||||||
xid: three_ds_data.xid,
|
xid: three_ds_data.xid,
|
||||||
|
eci: three_ds_data.eci,
|
||||||
three_ds_version: three_ds_data.three_ds_version,
|
three_ds_version: three_ds_data.three_ds_version,
|
||||||
|
directory_server_id: three_ds_data.directory_server_id,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -881,21 +873,22 @@ impl TryFrom<types::PaymentsSyncResponseRouterData<types::Response>>
|
|||||||
item: types::PaymentsSyncResponseRouterData<types::Response>,
|
item: types::PaymentsSyncResponseRouterData<types::Response>,
|
||||||
) -> Result<Self, Self::Error> {
|
) -> Result<Self, Self::Error> {
|
||||||
let response = SyncResponse::try_from(item.response.response.to_vec())?;
|
let response = SyncResponse::try_from(item.response.response.to_vec())?;
|
||||||
Ok(Self {
|
match response.transaction {
|
||||||
status: enums::AttemptStatus::from(NmiStatus::from(response.transaction.condition)),
|
Some(trn) => Ok(Self {
|
||||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
status: enums::AttemptStatus::from(NmiStatus::from(trn.condition)),
|
||||||
resource_id: types::ResponseId::ConnectorTransactionId(
|
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||||
response.transaction.transaction_id,
|
resource_id: types::ResponseId::ConnectorTransactionId(trn.transaction_id),
|
||||||
),
|
redirection_data: None,
|
||||||
redirection_data: None,
|
mandate_reference: None,
|
||||||
mandate_reference: None,
|
connector_metadata: None,
|
||||||
connector_metadata: None,
|
network_txn_id: None,
|
||||||
network_txn_id: None,
|
connector_response_reference_id: None,
|
||||||
connector_response_reference_id: None,
|
incremental_authorization_allowed: 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)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
pub struct SyncResponse {
|
pub struct SyncResponse {
|
||||||
pub transaction: SyncTransactionResponse,
|
pub transaction: Option<SyncTransactionResponse>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
@ -1199,10 +1192,10 @@ pub struct NmiWebhookObject {
|
|||||||
impl TryFrom<&NmiWebhookBody> for SyncResponse {
|
impl TryFrom<&NmiWebhookBody> for SyncResponse {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
fn try_from(item: &NmiWebhookBody) -> Result<Self, Self::Error> {
|
fn try_from(item: &NmiWebhookBody) -> Result<Self, Self::Error> {
|
||||||
let transaction = SyncTransactionResponse {
|
let transaction = Some(SyncTransactionResponse {
|
||||||
transaction_id: item.event_body.transaction_id.to_owned(),
|
transaction_id: item.event_body.transaction_id.to_owned(),
|
||||||
condition: item.event_body.condition.to_owned(),
|
condition: item.event_body.condition.to_owned(),
|
||||||
};
|
});
|
||||||
|
|
||||||
Ok(Self { transaction })
|
Ok(Self { transaction })
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1715,6 +1715,18 @@ pub fn build_redirection_form(
|
|||||||
item2.value=e.xid;
|
item2.value=e.xid;
|
||||||
responseForm.appendChild(item2);
|
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');
|
var item3=document.createElement('input');
|
||||||
item3.type='hidden';
|
item3.type='hidden';
|
||||||
item3.name='cardHolderAuth';
|
item3.name='cardHolderAuth';
|
||||||
|
|||||||
Reference in New Issue
Block a user