mirror of
				https://github.com/juspay/hyperswitch.git
				synced 2025-10-31 01:57:45 +08:00 
			
		
		
		
	refactor(connector): [NMI] Include mandatory fields for card 3DS (#3203)
This commit is contained in:
		| @ -357,6 +357,7 @@ stripe = { payment_method = "bank_transfer" } | |||||||
| nuvei = { payment_method = "card" } | nuvei = { payment_method = "card" } | ||||||
| shift4 = { payment_method = "card" } | shift4 = { payment_method = "card" } | ||||||
| bluesnap = { payment_method = "card" } | bluesnap = { payment_method = "card" } | ||||||
|  | nmi = {payment_method = "card"} | ||||||
|  |  | ||||||
| [dummy_connector] | [dummy_connector] | ||||||
| enabled = true                                  # Whether dummy connector is enabled or not | enabled = true                                  # Whether dummy connector is enabled or not | ||||||
|  | |||||||
| @ -434,6 +434,7 @@ stripe = {payment_method = "bank_transfer"} | |||||||
| nuvei = {payment_method = "card"} | nuvei = {payment_method = "card"} | ||||||
| shift4 = {payment_method = "card"} | shift4 = {payment_method = "card"} | ||||||
| bluesnap = {payment_method = "card"} | bluesnap = {payment_method = "card"} | ||||||
|  | nmi = {payment_method = "card"} | ||||||
|  |  | ||||||
| [connector_customer] | [connector_customer] | ||||||
| connector_list = "gocardless,stax,stripe" | connector_list = "gocardless,stax,stripe" | ||||||
|  | |||||||
| @ -247,6 +247,7 @@ stripe = {payment_method = "bank_transfer"} | |||||||
| nuvei = {payment_method = "card"} | nuvei = {payment_method = "card"} | ||||||
| shift4 = {payment_method = "card"} | shift4 = {payment_method = "card"} | ||||||
| bluesnap = {payment_method = "card"} | bluesnap = {payment_method = "card"} | ||||||
|  | nmi = {payment_method = "card"} | ||||||
|  |  | ||||||
| [dummy_connector] | [dummy_connector] | ||||||
| enabled = true | enabled = true | ||||||
|  | |||||||
| @ -1450,7 +1450,25 @@ impl Default for super::settings::RequiredFields { | |||||||
|                                                     field_type: enums::FieldType::UserCardCvc, |                                                     field_type: enums::FieldType::UserCardCvc, | ||||||
|                                                     value: None, |                                                     value: None, | ||||||
|                                                 } |                                                 } | ||||||
|                                             ) |                                             ), | ||||||
|  |                                             ( | ||||||
|  |                                                 "billing.address.first_name".to_string(), | ||||||
|  |                                                 RequiredFieldInfo { | ||||||
|  |                                                     required_field: "billing.address.first_name".to_string(), | ||||||
|  |                                                     display_name: "billing_first_name".to_string(), | ||||||
|  |                                                     field_type: enums::FieldType::UserBillingName, | ||||||
|  |                                                     value: None, | ||||||
|  |                                                 } | ||||||
|  |                                             ), | ||||||
|  |                                             ( | ||||||
|  |                                                 "billing.address.last_name".to_string(), | ||||||
|  |                                                 RequiredFieldInfo { | ||||||
|  |                                                     required_field: "billing.address.last_name".to_string(), | ||||||
|  |                                                     display_name: "billing_last_name".to_string(), | ||||||
|  |                                                     field_type: enums::FieldType::UserBillingName, | ||||||
|  |                                                     value: None, | ||||||
|  |                                                 } | ||||||
|  |                                             ), | ||||||
|                                         ] |                                         ] | ||||||
|                                     ), |                                     ), | ||||||
|                                     common: HashMap::new(), |                                     common: HashMap::new(), | ||||||
| @ -3481,7 +3499,25 @@ impl Default for super::settings::RequiredFields { | |||||||
|                                                     field_type: enums::FieldType::UserCardCvc, |                                                     field_type: enums::FieldType::UserCardCvc, | ||||||
|                                                     value: None, |                                                     value: None, | ||||||
|                                                 } |                                                 } | ||||||
|                                             ) |                                             ), | ||||||
|  |                                             ( | ||||||
|  |                                                 "billing.address.first_name".to_string(), | ||||||
|  |                                                 RequiredFieldInfo { | ||||||
|  |                                                     required_field: "billing.address.first_name".to_string(), | ||||||
|  |                                                     display_name: "billing_first_name".to_string(), | ||||||
|  |                                                     field_type: enums::FieldType::UserBillingName, | ||||||
|  |                                                     value: None, | ||||||
|  |                                                 } | ||||||
|  |                                             ), | ||||||
|  |                                             ( | ||||||
|  |                                                 "billing.address.last_name".to_string(), | ||||||
|  |                                                 RequiredFieldInfo { | ||||||
|  |                                                     required_field: "billing.address.last_name".to_string(), | ||||||
|  |                                                     display_name: "billing_last_name".to_string(), | ||||||
|  |                                                     field_type: enums::FieldType::UserBillingName, | ||||||
|  |                                                     value: None, | ||||||
|  |                                                 } | ||||||
|  |                                             ), | ||||||
|                                         ] |                                         ] | ||||||
|                                     ), |                                     ), | ||||||
|                                     common: HashMap::new(), |                                     common: HashMap::new(), | ||||||
|  | |||||||
| @ -6,7 +6,10 @@ use masking::{ExposeInterface, Secret}; | |||||||
| use serde::{Deserialize, Serialize}; | use serde::{Deserialize, Serialize}; | ||||||
|  |  | ||||||
| use crate::{ | use crate::{ | ||||||
|     connector::utils::{self, PaymentsAuthorizeRequestData, PaymentsCompleteAuthorizeRequestData}, |     connector::utils::{ | ||||||
|  |         self, AddressDetailsData, PaymentsAuthorizeRequestData, | ||||||
|  |         PaymentsCompleteAuthorizeRequestData, RouterData, | ||||||
|  |     }, | ||||||
|     core::errors, |     core::errors, | ||||||
|     services, |     services, | ||||||
|     types::{self, api, storage::enums, transformers::ForeignFrom, ConnectorAuthType}, |     types::{self, api, storage::enums, transformers::ForeignFrom, ConnectorAuthType}, | ||||||
| @ -83,6 +86,9 @@ pub struct NmiVaultRequest { | |||||||
|     security_key: Secret<String>, |     security_key: Secret<String>, | ||||||
|     ccnumber: CardNumber, |     ccnumber: CardNumber, | ||||||
|     ccexp: Secret<String>, |     ccexp: Secret<String>, | ||||||
|  |     cvv: Secret<String>, | ||||||
|  |     first_name: Secret<String>, | ||||||
|  |     last_name: Secret<String>, | ||||||
|     customer_vault: CustomerAction, |     customer_vault: CustomerAction, | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -97,12 +103,16 @@ impl TryFrom<&types::PaymentsPreProcessingRouterData> for NmiVaultRequest { | |||||||
|     type Error = Error; |     type Error = Error; | ||||||
|     fn try_from(item: &types::PaymentsPreProcessingRouterData) -> Result<Self, Self::Error> { |     fn try_from(item: &types::PaymentsPreProcessingRouterData) -> Result<Self, Self::Error> { | ||||||
|         let auth_type: NmiAuthType = (&item.connector_auth_type).try_into()?; |         let auth_type: NmiAuthType = (&item.connector_auth_type).try_into()?; | ||||||
|         let (ccnumber, ccexp) = get_card_details(item.request.payment_method_data.clone())?; |         let (ccnumber, ccexp, cvv) = get_card_details(item.request.payment_method_data.clone())?; | ||||||
|  |         let billing_details = item.get_billing_address()?; | ||||||
|  |  | ||||||
|         Ok(Self { |         Ok(Self { | ||||||
|             security_key: auth_type.api_key, |             security_key: auth_type.api_key, | ||||||
|             ccnumber, |             ccnumber, | ||||||
|             ccexp, |             ccexp, | ||||||
|  |             cvv, | ||||||
|  |             first_name: billing_details.get_first_name()?.to_owned(), | ||||||
|  |             last_name: billing_details.get_last_name()?.to_owned(), | ||||||
|             customer_vault: CustomerAction::AddCustomer, |             customer_vault: CustomerAction::AddCustomer, | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
| @ -110,7 +120,7 @@ impl TryFrom<&types::PaymentsPreProcessingRouterData> for NmiVaultRequest { | |||||||
|  |  | ||||||
| fn get_card_details( | fn get_card_details( | ||||||
|     payment_method_data: Option<api::PaymentMethodData>, |     payment_method_data: Option<api::PaymentMethodData>, | ||||||
| ) -> CustomResult<(CardNumber, Secret<String>), errors::ConnectorError> { | ) -> CustomResult<(CardNumber, Secret<String>, Secret<String>), errors::ConnectorError> { | ||||||
|     match payment_method_data { |     match payment_method_data { | ||||||
|         Some(api::PaymentMethodData::Card(ref card_details)) => Ok(( |         Some(api::PaymentMethodData::Card(ref card_details)) => Ok(( | ||||||
|             card_details.card_number.clone(), |             card_details.card_number.clone(), | ||||||
| @ -118,6 +128,7 @@ fn get_card_details( | |||||||
|                 card_details, |                 card_details, | ||||||
|                 "".to_string(), |                 "".to_string(), | ||||||
|             ), |             ), | ||||||
|  |             card_details.card_cvc.clone(), | ||||||
|         )), |         )), | ||||||
|         _ => Err(errors::ConnectorError::NotImplemented( |         _ => Err(errors::ConnectorError::NotImplemented( | ||||||
|             utils::get_unimplemented_payment_method_error_message("Nmi"), |             utils::get_unimplemented_payment_method_error_message("Nmi"), | ||||||
| @ -189,6 +200,7 @@ impl | |||||||
|                                 config: "public_key", |                                 config: "public_key", | ||||||
|                             }, |                             }, | ||||||
|                         )?, |                         )?, | ||||||
|  |                         order_id: item.data.connector_request_reference_id.clone(), | ||||||
|                     }), |                     }), | ||||||
|                     mandate_reference: None, |                     mandate_reference: None, | ||||||
|                     connector_metadata: None, |                     connector_metadata: None, | ||||||
| @ -220,13 +232,17 @@ impl | |||||||
|  |  | ||||||
| #[derive(Debug, Serialize)] | #[derive(Debug, Serialize)] | ||||||
| pub struct NmiCompleteRequest { | pub struct NmiCompleteRequest { | ||||||
|  |     amount: f64, | ||||||
|     #[serde(rename = "type")] |     #[serde(rename = "type")] | ||||||
|     transaction_type: TransactionType, |     transaction_type: TransactionType, | ||||||
|     security_key: Secret<String>, |     security_key: Secret<String>, | ||||||
|  |     orderid: String, | ||||||
|  |     ccnumber: CardNumber, | ||||||
|  |     ccexp: Secret<String>, | ||||||
|     cardholder_auth: CardHolderAuthType, |     cardholder_auth: CardHolderAuthType, | ||||||
|     cavv: String, |     cavv: String, | ||||||
|     xid: String, |     xid: String, | ||||||
|     three_ds_version: ThreeDsVersion, |     three_ds_version: Option<ThreeDsVersion>, | ||||||
| } | } | ||||||
|  |  | ||||||
| #[derive(Debug, Serialize, Deserialize)] | #[derive(Debug, Serialize, Deserialize)] | ||||||
| @ -240,6 +256,8 @@ pub enum CardHolderAuthType { | |||||||
| pub enum ThreeDsVersion { | pub enum ThreeDsVersion { | ||||||
|     #[serde(rename = "2.0.0")] |     #[serde(rename = "2.0.0")] | ||||||
|     VersionTwo, |     VersionTwo, | ||||||
|  |     #[serde(rename = "2.1.0")] | ||||||
|  |     VersionTwoPointOne, | ||||||
|     #[serde(rename = "2.2.0")] |     #[serde(rename = "2.2.0")] | ||||||
|     VersionTwoPointTwo, |     VersionTwoPointTwo, | ||||||
| } | } | ||||||
| @ -250,7 +268,8 @@ pub struct NmiRedirectResponseData { | |||||||
|     cavv: String, |     cavv: String, | ||||||
|     xid: String, |     xid: String, | ||||||
|     card_holder_auth: CardHolderAuthType, |     card_holder_auth: CardHolderAuthType, | ||||||
|     three_ds_version: ThreeDsVersion, |     three_ds_version: Option<ThreeDsVersion>, | ||||||
|  |     order_id: String, | ||||||
| } | } | ||||||
|  |  | ||||||
| impl TryFrom<&NmiRouterData<&types::PaymentsCompleteAuthorizeRouterData>> for NmiCompleteRequest { | impl TryFrom<&NmiRouterData<&types::PaymentsCompleteAuthorizeRouterData>> for NmiCompleteRequest { | ||||||
| @ -275,9 +294,16 @@ impl TryFrom<&NmiRouterData<&types::PaymentsCompleteAuthorizeRouterData>> for Nm | |||||||
|                 field_name: "three_ds_data", |                 field_name: "three_ds_data", | ||||||
|             })?; |             })?; | ||||||
|  |  | ||||||
|  |         let (ccnumber, ccexp, ..) = | ||||||
|  |             get_card_details(item.router_data.request.payment_method_data.clone())?; | ||||||
|  |  | ||||||
|         Ok(Self { |         Ok(Self { | ||||||
|  |             amount: item.amount, | ||||||
|             transaction_type, |             transaction_type, | ||||||
|             security_key: auth_type.api_key, |             security_key: auth_type.api_key, | ||||||
|  |             orderid: three_ds_data.order_id, | ||||||
|  |             ccnumber, | ||||||
|  |             ccexp, | ||||||
|             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, | ||||||
|  | |||||||
| @ -778,6 +778,7 @@ pub enum RedirectForm { | |||||||
|         currency: Currency, |         currency: Currency, | ||||||
|         public_key: Secret<String>, |         public_key: Secret<String>, | ||||||
|         customer_vault_id: String, |         customer_vault_id: String, | ||||||
|  |         order_id: String, | ||||||
|     }, |     }, | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -1507,6 +1508,7 @@ pub fn build_redirection_form( | |||||||
|             currency, |             currency, | ||||||
|             public_key, |             public_key, | ||||||
|             customer_vault_id, |             customer_vault_id, | ||||||
|  |             order_id, | ||||||
|         } => { |         } => { | ||||||
|             let public_key_val = public_key.peek(); |             let public_key_val = public_key.peek(); | ||||||
|             maud::html! { |             maud::html! { | ||||||
| @ -1563,6 +1565,12 @@ pub fn build_redirection_form( | |||||||
|                         item4.value=e.threeDsVersion; |                         item4.value=e.threeDsVersion; | ||||||
|                         responseForm.appendChild(item4); |                         responseForm.appendChild(item4); | ||||||
|  |  | ||||||
|  |                         var item5=document.createElement('input'); | ||||||
|  |                         item4.type='hidden'; | ||||||
|  |                         item4.name='orderId'; | ||||||
|  |                         item4.value='{order_id}'; | ||||||
|  |                         responseForm.appendChild(item5); | ||||||
|  |  | ||||||
|                         document.body.appendChild(responseForm); |                         document.body.appendChild(responseForm); | ||||||
|                         responseForm.submit(); |                         responseForm.submit(); | ||||||
|                     }}); |                     }}); | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 Sakil Mostak
					Sakil Mostak