mirror of
				https://github.com/juspay/hyperswitch.git
				synced 2025-11-01 02:57:02 +08:00 
			
		
		
		
	feat(mandates): recurring payment support for bank redirect and bank debit payment method for stripe (#1119)
Co-authored-by: pixincreate@work <69745008+pixincreate@users.noreply.github.com>
This commit is contained in:
		| @ -593,10 +593,11 @@ impl | ||||
|                 x | ||||
|             )), | ||||
|             Ok(x) => Ok(format!( | ||||
|                 "{}{}/{}", | ||||
|                 "{}{}/{}{}", | ||||
|                 self.base_url(connectors), | ||||
|                 "v1/payment_intents", | ||||
|                 x | ||||
|                 x, | ||||
|                 "?expand[0]=latest_charge" //updated payment_id(if present) reside inside latest_charge field | ||||
|             )), | ||||
|             x => x.change_context(errors::ConnectorError::MissingConnectorTransactionID), | ||||
|         } | ||||
| @ -1883,7 +1884,8 @@ impl services::ConnectorRedirectResponse for Stripe { | ||||
|             .map_or( | ||||
|                 payments::CallConnectorAction::Trigger, | ||||
|                 |status| match status { | ||||
|                     transformers::StripePaymentStatus::Failed => { | ||||
|                     transformers::StripePaymentStatus::Failed | ||||
|                     | transformers::StripePaymentStatus::Pending => { | ||||
|                         payments::CallConnectorAction::Trigger | ||||
|                     } | ||||
|                     _ => payments::CallConnectorAction::StatusUpdate { | ||||
|  | ||||
| @ -70,19 +70,24 @@ pub enum Auth3ds { | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Eq, PartialEq, Serialize)] | ||||
| #[serde(rename_all = "snake_case")] | ||||
| #[serde( | ||||
|     rename_all = "snake_case", | ||||
|     tag = "mandate_data[customer_acceptance][type]" | ||||
| )] | ||||
| pub enum StripeMandateType { | ||||
|     Online, | ||||
|     Online { | ||||
|         #[serde(rename = "mandate_data[customer_acceptance][online][ip_address]")] | ||||
|         ip_address: Secret<String, pii::IpAddress>, | ||||
|         #[serde(rename = "mandate_data[customer_acceptance][online][user_agent]")] | ||||
|         user_agent: String, | ||||
|     }, | ||||
|     Offline, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Eq, PartialEq, Serialize)] | ||||
| pub struct StripeMandateRequest { | ||||
|     #[serde(rename = "mandate_data[customer_acceptance][type]")] | ||||
|     pub mandate_type: StripeMandateType, | ||||
|     #[serde(rename = "mandate_data[customer_acceptance][online][ip_address]")] | ||||
|     pub ip_address: Secret<String, pii::IpAddress>, | ||||
|     #[serde(rename = "mandate_data[customer_acceptance][online][user_agent]")] | ||||
|     pub user_agent: String, | ||||
|     #[serde(flatten)] | ||||
|     mandate_type: StripeMandateType, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Eq, PartialEq, Serialize)] | ||||
| @ -115,6 +120,8 @@ pub struct PaymentIntentRequest { | ||||
|     pub payment_method_options: Option<StripePaymentMethodOptions>, // For mandate txns using network_txns_id, needs to be validated | ||||
|     pub setup_future_usage: Option<enums::FutureUsage>, | ||||
|     pub off_session: Option<bool>, | ||||
|     #[serde(rename = "payment_method_types[0]")] | ||||
|     pub payment_method_types: Option<StripePaymentMethodType>, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Eq, PartialEq, Serialize)] | ||||
| @ -137,8 +144,6 @@ pub struct SetupIntentRequest { | ||||
|  | ||||
| #[derive(Debug, Eq, PartialEq, Serialize)] | ||||
| pub struct StripeCardData { | ||||
|     #[serde(rename = "payment_method_types[]")] | ||||
|     pub payment_method_types: StripePaymentMethodType, | ||||
|     #[serde(rename = "payment_method_data[type]")] | ||||
|     pub payment_method_data_type: StripePaymentMethodType, | ||||
|     #[serde(rename = "payment_method_data[card][number]")] | ||||
| @ -154,8 +159,6 @@ pub struct StripeCardData { | ||||
| } | ||||
| #[derive(Debug, Eq, PartialEq, Serialize)] | ||||
| pub struct StripePayLaterData { | ||||
|     #[serde(rename = "payment_method_types[]")] | ||||
|     pub payment_method_types: StripePaymentMethodType, | ||||
|     #[serde(rename = "payment_method_data[type]")] | ||||
|     pub payment_method_data_type: StripePaymentMethodType, | ||||
| } | ||||
| @ -277,8 +280,6 @@ fn get_bank_name( | ||||
|  | ||||
| #[derive(Debug, Eq, PartialEq, Serialize)] | ||||
| pub struct StripeBankRedirectData { | ||||
|     #[serde(rename = "payment_method_types[]")] | ||||
|     pub payment_method_types: StripePaymentMethodType, | ||||
|     #[serde(rename = "payment_method_data[type]")] | ||||
|     pub payment_method_data_type: StripePaymentMethodType, | ||||
|     // Required only for eps and ideal | ||||
| @ -403,8 +404,6 @@ pub enum BankDebitData { | ||||
|  | ||||
| #[derive(Debug, Eq, PartialEq, Serialize)] | ||||
| pub struct StripeBankDebitData { | ||||
|     #[serde(rename = "payment_method_types[]")] | ||||
|     pub payment_method_types: StripePaymentMethodType, | ||||
|     #[serde(flatten)] | ||||
|     pub bank_specific_data: BankDebitData, | ||||
| } | ||||
| @ -459,16 +458,12 @@ pub struct ApplepayPayment { | ||||
|  | ||||
| #[derive(Debug, Eq, PartialEq, Serialize)] | ||||
| pub struct AlipayPayment { | ||||
|     #[serde(rename = "payment_method_types[]")] | ||||
|     pub payment_method_types: StripePaymentMethodType, | ||||
|     #[serde(rename = "payment_method_data[type]")] | ||||
|     pub payment_method_data_type: StripePaymentMethodType, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Eq, PartialEq, Serialize)] | ||||
| pub struct WechatpayPayment { | ||||
|     #[serde(rename = "payment_method_types[]")] | ||||
|     pub payment_method_types: StripePaymentMethodType, | ||||
|     #[serde(rename = "payment_method_data[type]")] | ||||
|     pub payment_method_data_type: StripePaymentMethodType, | ||||
|     #[serde(rename = "payment_method_options[wechat_pay][client]")] | ||||
| @ -520,6 +515,36 @@ pub enum StripePaymentMethodType { | ||||
|     Multibanco, | ||||
| } | ||||
|  | ||||
| impl TryFrom<enums::PaymentMethodType> for StripePaymentMethodType { | ||||
|     type Error = error_stack::Report<errors::ConnectorError>; | ||||
|     fn try_from(value: enums::PaymentMethodType) -> Result<Self, Self::Error> { | ||||
|         match value { | ||||
|             enums::PaymentMethodType::Credit => Ok(Self::Card), | ||||
|             enums::PaymentMethodType::Debit => Ok(Self::Card), | ||||
|             enums::PaymentMethodType::Klarna => Ok(Self::Klarna), | ||||
|             enums::PaymentMethodType::Affirm => Ok(Self::Affirm), | ||||
|             enums::PaymentMethodType::AfterpayClearpay => Ok(Self::AfterpayClearpay), | ||||
|             enums::PaymentMethodType::Eps => Ok(Self::Eps), | ||||
|             enums::PaymentMethodType::Giropay => Ok(Self::Giropay), | ||||
|             enums::PaymentMethodType::Ideal => Ok(Self::Ideal), | ||||
|             enums::PaymentMethodType::Sofort => Ok(Self::Sofort), | ||||
|             enums::PaymentMethodType::ApplePay => Ok(Self::ApplePay), | ||||
|             enums::PaymentMethodType::Ach => Ok(Self::Ach), | ||||
|             enums::PaymentMethodType::Sepa => Ok(Self::Sepa), | ||||
|             enums::PaymentMethodType::Becs => Ok(Self::Becs), | ||||
|             enums::PaymentMethodType::Bacs => Ok(Self::Bacs), | ||||
|             enums::PaymentMethodType::BancontactCard => Ok(Self::Bancontact), | ||||
|             enums::PaymentMethodType::WeChatPay => Ok(Self::Wechatpay), | ||||
|             enums::PaymentMethodType::AliPay => Ok(Self::Alipay), | ||||
|             enums::PaymentMethodType::Przelewy24 => Ok(Self::Przelewy24), | ||||
|             _ => Err(errors::ConnectorError::NotImplemented( | ||||
|                 "this payment method for stripe".to_string(), | ||||
|             ) | ||||
|             .into()), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Eq, PartialEq, Serialize, Clone)] | ||||
| #[serde(rename_all = "snake_case")] | ||||
| pub enum BankTransferType { | ||||
| @ -873,6 +898,7 @@ impl TryFrom<&payments::BankRedirectData> for StripeBillingAddress { | ||||
|                 billing_details, .. | ||||
|             } => Ok(Self { | ||||
|                 name: billing_details.billing_name.clone(), | ||||
|                 email: billing_details.email.clone(), | ||||
|                 ..Self::default() | ||||
|             }), | ||||
|             payments::BankRedirectData::Przelewy24 { | ||||
| @ -883,14 +909,39 @@ impl TryFrom<&payments::BankRedirectData> for StripeBillingAddress { | ||||
|             }), | ||||
|             payments::BankRedirectData::BancontactCard { | ||||
|                 billing_details, .. | ||||
|             } => { | ||||
|                 let billing_details = billing_details.as_ref().ok_or( | ||||
|                     errors::ConnectorError::MissingRequiredField { | ||||
|                         field_name: "billing_details", | ||||
|                     }, | ||||
|                 )?; | ||||
|                 Ok(Self { | ||||
|                     name: Some( | ||||
|                         billing_details | ||||
|                             .billing_name | ||||
|                             .as_ref() | ||||
|                             .ok_or(errors::ConnectorError::MissingRequiredField { | ||||
|                                 field_name: "billing_details.billing_name", | ||||
|                             })? | ||||
|                             .to_owned(), | ||||
|                     ), | ||||
|                     email: Some( | ||||
|                         billing_details | ||||
|                             .email | ||||
|                             .as_ref() | ||||
|                             .ok_or(errors::ConnectorError::MissingRequiredField { | ||||
|                                 field_name: "billing_details.email", | ||||
|                             })? | ||||
|                             .to_owned(), | ||||
|                     ), | ||||
|                     ..Self::default() | ||||
|                 }) | ||||
|             } | ||||
|             payments::BankRedirectData::Sofort { | ||||
|                 billing_details, .. | ||||
|             } => Ok(Self { | ||||
|                 name: billing_details | ||||
|                     .as_ref() | ||||
|                     .ok_or(errors::ConnectorError::MissingRequiredField { | ||||
|                         field_name: "bancontact_card.billing_name", | ||||
|                     })? | ||||
|                     .billing_name | ||||
|                     .clone(), | ||||
|                 name: billing_details.billing_name.clone(), | ||||
|                 email: billing_details.email.clone(), | ||||
|                 ..Self::default() | ||||
|             }), | ||||
|             _ => Ok(Self::default()), | ||||
| @ -996,7 +1047,6 @@ fn create_stripe_payment_method( | ||||
|             }; | ||||
|             Ok(( | ||||
|                 StripePaymentMethodData::Card(StripeCardData { | ||||
|                     payment_method_types: StripePaymentMethodType::Card, | ||||
|                     payment_method_data_type: StripePaymentMethodType::Card, | ||||
|                     payment_method_data_card_number: card_details.card_number.clone(), | ||||
|                     payment_method_data_card_exp_month: card_details.card_exp_month.clone(), | ||||
| @ -1023,7 +1073,6 @@ fn create_stripe_payment_method( | ||||
|  | ||||
|             Ok(( | ||||
|                 StripePaymentMethodData::PayLater(StripePayLaterData { | ||||
|                     payment_method_types: stripe_pm_type, | ||||
|                     payment_method_data_type: stripe_pm_type, | ||||
|                 }), | ||||
|                 stripe_pm_type, | ||||
| @ -1038,7 +1087,6 @@ fn create_stripe_payment_method( | ||||
|  | ||||
|             Ok(( | ||||
|                 StripePaymentMethodData::BankRedirect(StripeBankRedirectData { | ||||
|                     payment_method_types: pm_type, | ||||
|                     payment_method_data_type: pm_type, | ||||
|                     bank_name, | ||||
|                     bank_specific_data, | ||||
| @ -1063,7 +1111,6 @@ fn create_stripe_payment_method( | ||||
|             payments::WalletData::WeChatPay(_) => Ok(( | ||||
|                 StripePaymentMethodData::Wallet(StripeWallet::WechatpayPayment(WechatpayPayment { | ||||
|                     client: WechatClient::Web, | ||||
|                     payment_method_types: StripePaymentMethodType::Wechatpay, | ||||
|                     payment_method_data_type: StripePaymentMethodType::Wechatpay, | ||||
|                 })), | ||||
|                 StripePaymentMethodType::Wechatpay, | ||||
| @ -1071,7 +1118,6 @@ fn create_stripe_payment_method( | ||||
|             )), | ||||
|             payments::WalletData::AliPayRedirect(_) => Ok(( | ||||
|                 StripePaymentMethodData::Wallet(StripeWallet::AlipayPayment(AlipayPayment { | ||||
|                     payment_method_types: StripePaymentMethodType::Alipay, | ||||
|                     payment_method_data_type: StripePaymentMethodType::Alipay, | ||||
|                 })), | ||||
|                 StripePaymentMethodType::Alipay, | ||||
| @ -1091,7 +1137,6 @@ fn create_stripe_payment_method( | ||||
|             let (pm_type, bank_debit_data, billing_address) = get_bank_debit_data(bank_debit_data); | ||||
|  | ||||
|             let pm_data = StripePaymentMethodData::BankDebit(StripeBankDebitData { | ||||
|                 payment_method_types: pm_type, | ||||
|                 bank_specific_data: bank_debit_data, | ||||
|             }); | ||||
|  | ||||
| @ -1232,7 +1277,7 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for PaymentIntentRequest { | ||||
|         }; | ||||
|         let mut payment_method_options = None; | ||||
|  | ||||
|         let (mut payment_data, payment_method, mandate, billing_address) = { | ||||
|         let (mut payment_data, payment_method, mandate, billing_address, payment_method_types) = { | ||||
|             match item | ||||
|                 .request | ||||
|                 .mandate_id | ||||
| @ -1246,6 +1291,7 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for PaymentIntentRequest { | ||||
|                     connector_mandate_ids.payment_method_id, | ||||
|                     connector_mandate_ids.connector_mandate_id, | ||||
|                     StripeBillingAddress::default(), | ||||
|                     None, | ||||
|                 ), | ||||
|                 Some(api_models::payments::MandateReferenceId::NetworkMandateId( | ||||
|                     network_transaction_id, | ||||
| @ -1257,7 +1303,7 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for PaymentIntentRequest { | ||||
|                             network_transaction_id: Secret::new(network_transaction_id), | ||||
|                         }), | ||||
|                     }); | ||||
|                     (None, None, None, StripeBillingAddress::default()) | ||||
|                     (None, None, None, StripeBillingAddress::default(), None) | ||||
|                 } | ||||
|                 _ => { | ||||
|                     let (payment_method_data, payment_method_type, billing_address) = | ||||
| @ -1273,11 +1319,26 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for PaymentIntentRequest { | ||||
|                         &payment_method_type, | ||||
|                     )?; | ||||
|  | ||||
|                     (Some(payment_method_data), None, None, billing_address) | ||||
|                     ( | ||||
|                         Some(payment_method_data), | ||||
|                         None, | ||||
|                         None, | ||||
|                         billing_address, | ||||
|                         Some(payment_method_type), | ||||
|                     ) | ||||
|                 } | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         //if payment_method is Some(), That means, it is a recurring mandate payment. | ||||
|         //payment_method_types will not be not be available in router_data.request. But stripe requires that field. | ||||
|         //here we will get that field from router_data.recurring_mandate_payment_data | ||||
|         let payment_method_types = if payment_method.is_some() { | ||||
|             //if recurring payment get payment_method_type | ||||
|             get_payment_method_type_for_saved_payment_method_payment(item).map(Some)? | ||||
|         } else { | ||||
|             payment_method_types | ||||
|         }; | ||||
|         payment_data = match item.request.payment_method_data { | ||||
|             payments::PaymentMethodData::Wallet(payments::WalletData::ApplePay(_)) => Some( | ||||
|                 StripePaymentMethodData::Wallet(StripeWallet::ApplepayPayment(ApplepayPayment { | ||||
| @ -1300,25 +1361,62 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for PaymentIntentRequest { | ||||
|             .and_then(|mandate_details| { | ||||
|                 mandate_details | ||||
|                     .customer_acceptance | ||||
|                     .as_ref()? | ||||
|                     .online | ||||
|                     .as_ref() | ||||
|                     .map(|online_details| { | ||||
|                         Ok::<_, error_stack::Report<errors::ConnectorError>>(StripeMandateRequest { | ||||
|                             mandate_type: StripeMandateType::Online, | ||||
|                             ip_address: online_details | ||||
|                                 .ip_address | ||||
|                                 .clone() | ||||
|                                 .get_required_value("ip_address") | ||||
|                                 .change_context(errors::ConnectorError::MissingRequiredField { | ||||
|                                     field_name: "ip_address", | ||||
|                                 })?, | ||||
|                             user_agent: online_details.user_agent.to_owned(), | ||||
|                         }) | ||||
|                     .map(|customer_acceptance| { | ||||
|                         Ok::<_, error_stack::Report<errors::ConnectorError>>( | ||||
|                             match customer_acceptance.acceptance_type { | ||||
|                                 payments::AcceptanceType::Online => { | ||||
|                                     let online_mandate = customer_acceptance | ||||
|                                         .online | ||||
|                                         .clone() | ||||
|                                         .get_required_value("online") | ||||
|                                         .change_context( | ||||
|                                             errors::ConnectorError::MissingRequiredField { | ||||
|                                                 field_name: "online", | ||||
|                                             }, | ||||
|                                         )?; | ||||
|                                     StripeMandateRequest { | ||||
|                                         mandate_type: StripeMandateType::Online { | ||||
|                                             ip_address: online_mandate | ||||
|                                                 .ip_address | ||||
|                                                 .get_required_value("ip_address") | ||||
|                                                 .change_context( | ||||
|                                                     errors::ConnectorError::MissingRequiredField { | ||||
|                                                         field_name: "ip_address", | ||||
|                                                     }, | ||||
|                                                 )?, | ||||
|                                             user_agent: online_mandate.user_agent, | ||||
|                                         }, | ||||
|                                     } | ||||
|                                 } | ||||
|                                 payments::AcceptanceType::Offline => StripeMandateRequest { | ||||
|                                     mandate_type: StripeMandateType::Offline, | ||||
|                                 }, | ||||
|                             }, | ||||
|                         ) | ||||
|                     }) | ||||
|             }) | ||||
|             .transpose()?; | ||||
|  | ||||
|             .transpose()? | ||||
|             .or_else(|| { | ||||
|                 //stripe requires us to send mandate_data while making recurring payment through saved bank debit | ||||
|                 if payment_method.is_some() { | ||||
|                     //check if payment is done through saved payment method | ||||
|                     match &payment_method_types { | ||||
|                         //check if payment method is bank debit | ||||
|                         Some( | ||||
|                             StripePaymentMethodType::Ach | ||||
|                             | StripePaymentMethodType::Sepa | ||||
|                             | StripePaymentMethodType::Becs | ||||
|                             | StripePaymentMethodType::Bacs, | ||||
|                         ) => Some(StripeMandateRequest { | ||||
|                             mandate_type: StripeMandateType::Offline, | ||||
|                         }), | ||||
|                         _ => None, | ||||
|                     } | ||||
|                 } else { | ||||
|                     None | ||||
|                 } | ||||
|             }); | ||||
|         Ok(Self { | ||||
|             amount: item.request.amount, //hopefully we don't loose some cents here | ||||
|             currency: item.request.currency.to_string(), //we need to copy the value and not transfer ownership | ||||
| @ -1345,10 +1443,38 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for PaymentIntentRequest { | ||||
|             setup_mandate_details, | ||||
|             off_session: item.request.off_session, | ||||
|             setup_future_usage: item.request.setup_future_usage, | ||||
|             payment_method_types, | ||||
|         }) | ||||
|     } | ||||
| } | ||||
|  | ||||
| fn get_payment_method_type_for_saved_payment_method_payment( | ||||
|     item: &types::PaymentsAuthorizeRouterData, | ||||
| ) -> Result<StripePaymentMethodType, error_stack::Report<errors::ConnectorError>> { | ||||
|     let stripe_payment_method_type = match item.recurring_mandate_payment_data.clone() { | ||||
|         Some(recurring_payment_method_data) => { | ||||
|             match recurring_payment_method_data.payment_method_type { | ||||
|                 Some(payment_method_type) => StripePaymentMethodType::try_from(payment_method_type), | ||||
|                 None => Err(errors::ConnectorError::MissingRequiredField { | ||||
|                     field_name: "payment_method_type", | ||||
|                 } | ||||
|                 .into()), | ||||
|             } | ||||
|         } | ||||
|         None => Err(errors::ConnectorError::MissingRequiredField { | ||||
|             field_name: "recurring_mandate_payment_data", | ||||
|         } | ||||
|         .into()), | ||||
|     }?; | ||||
|     match stripe_payment_method_type { | ||||
|         //Stripe converts Ideal, Bancontact & Sofort Bank redirect methods to Sepa direct debit and attaches to the customer for future usage | ||||
|         StripePaymentMethodType::Ideal | ||||
|         | StripePaymentMethodType::Bancontact | ||||
|         | StripePaymentMethodType::Sofort => Ok(StripePaymentMethodType::Sepa), | ||||
|         _ => Ok(stripe_payment_method_type), | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl TryFrom<&types::VerifyRouterData> for SetupIntentRequest { | ||||
|     type Error = error_stack::Report<errors::ConnectorError>; | ||||
|     fn try_from(item: &types::VerifyRouterData) -> Result<Self, Self::Error> { | ||||
| @ -1552,6 +1678,19 @@ pub struct PaymentIntentSyncResponse { | ||||
|     #[serde(flatten)] | ||||
|     payment_intent_fields: PaymentIntentResponse, | ||||
|     pub last_payment_error: Option<LastPaymentError>, | ||||
|     pub latest_charge: Option<StripeCharge>, | ||||
| } | ||||
|  | ||||
| #[derive(Deserialize, Clone, Debug)] | ||||
| pub struct StripeCharge { | ||||
|     pub id: String, | ||||
|     pub payment_method_details: Option<StripePaymentMethodDetailsResponse>, | ||||
| } | ||||
|  | ||||
| #[derive(Deserialize, Clone, Debug)] | ||||
| pub struct StripeBankRedirectDetails { | ||||
|     #[serde(rename = "generated_sepa_debit")] | ||||
|     attached_payment_method: Option<String>, | ||||
| } | ||||
|  | ||||
| impl Deref for PaymentIntentSyncResponse { | ||||
| @ -1562,6 +1701,45 @@ impl Deref for PaymentIntentSyncResponse { | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[derive(Deserialize, Clone, Debug)] | ||||
| #[serde(rename_all = "snake_case", tag = "type")] | ||||
| pub enum StripePaymentMethodDetailsResponse { | ||||
|     //only ideal, sofort and bancontact is supported by stripe for recurring payment in bank redirect | ||||
|     Ideal { | ||||
|         ideal: StripeBankRedirectDetails, | ||||
|     }, | ||||
|     Sofort { | ||||
|         sofort: StripeBankRedirectDetails, | ||||
|     }, | ||||
|     Bancontact { | ||||
|         bancontact: StripeBankRedirectDetails, | ||||
|     }, | ||||
|  | ||||
|     //other payment method types supported by stripe. To avoid deserialization error. | ||||
|     Blik, | ||||
|     Eps, | ||||
|     Fpx, | ||||
|     Giropay, | ||||
|     #[serde(rename = "p24")] | ||||
|     Przelewy24, | ||||
|     Card, | ||||
|     Klarna, | ||||
|     Affirm, | ||||
|     AfterpayClearpay, | ||||
|     ApplePay, | ||||
|     #[serde(rename = "us_bank_account")] | ||||
|     Ach, | ||||
|     #[serde(rename = "sepa_debit")] | ||||
|     Sepa, | ||||
|     #[serde(rename = "au_becs_debit")] | ||||
|     Becs, | ||||
|     #[serde(rename = "bacs_debit")] | ||||
|     Bacs, | ||||
|     #[serde(rename = "wechat_pay")] | ||||
|     Wechatpay, | ||||
|     Alipay, | ||||
| } | ||||
|  | ||||
| #[derive(Deserialize)] | ||||
| pub struct SetupIntentSyncResponse { | ||||
|     #[serde(flatten)] | ||||
| @ -1582,6 +1760,7 @@ impl From<SetupIntentSyncResponse> for PaymentIntentSyncResponse { | ||||
|         Self { | ||||
|             payment_intent_fields: value.setup_intent_fields.into(), | ||||
|             last_payment_error: value.last_payment_error, | ||||
|             latest_charge: None, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -1772,7 +1951,21 @@ impl<F, T> | ||||
|         let mandate_reference = item.response.payment_method.clone().map(|pm| { | ||||
|             types::MandateReference::foreign_from(( | ||||
|                 item.response.payment_method_options.clone(), | ||||
|                 pm, | ||||
|                 match item.response.latest_charge.clone() { | ||||
|                     Some(charge) => match charge.payment_method_details { | ||||
|                         Some(StripePaymentMethodDetailsResponse::Bancontact { bancontact }) => { | ||||
|                             bancontact.attached_payment_method.unwrap_or(pm) | ||||
|                         } | ||||
|                         Some(StripePaymentMethodDetailsResponse::Ideal { ideal }) => { | ||||
|                             ideal.attached_payment_method.unwrap_or(pm) | ||||
|                         } | ||||
|                         Some(StripePaymentMethodDetailsResponse::Sofort { sofort }) => { | ||||
|                             sofort.attached_payment_method.unwrap_or(pm) | ||||
|                         } | ||||
|                         _ => pm, | ||||
|                     }, | ||||
|                     None => pm, | ||||
|                 }, | ||||
|             )) | ||||
|         }); | ||||
|         let error_res = | ||||
| @ -2583,7 +2776,6 @@ impl | ||||
|                     enums::AuthenticationType::NoThreeDs => Auth3ds::Automatic, | ||||
|                 }; | ||||
|                 StripeCardData { | ||||
|                     payment_method_types: StripePaymentMethodType::Card, | ||||
|                     payment_method_data_type: StripePaymentMethodType::Card, | ||||
|                     payment_method_data_card_number: ccard.card_number.clone(), | ||||
|                     payment_method_data_card_exp_month: ccard.card_exp_month.clone(), | ||||
| @ -2593,12 +2785,10 @@ impl | ||||
|                 } | ||||
|             })), | ||||
|             api::PaymentMethodData::PayLater(_) => Ok(Self::PayLater(StripePayLaterData { | ||||
|                 payment_method_types: pm_type, | ||||
|                 payment_method_data_type: pm_type, | ||||
|             })), | ||||
|             api::PaymentMethodData::BankRedirect(_) => { | ||||
|                 Ok(Self::BankRedirect(StripeBankRedirectData { | ||||
|                     payment_method_types: pm_type, | ||||
|                     payment_method_data_type: pm_type, | ||||
|                     bank_name: None, | ||||
|                     bank_specific_data: None, | ||||
| @ -2620,14 +2810,12 @@ impl | ||||
|                 payments::WalletData::WeChatPayRedirect(_) => { | ||||
|                     let wallet_info = StripeWallet::WechatpayPayment(WechatpayPayment { | ||||
|                         client: WechatClient::Web, | ||||
|                         payment_method_types: StripePaymentMethodType::Wechatpay, | ||||
|                         payment_method_data_type: StripePaymentMethodType::Wechatpay, | ||||
|                     }); | ||||
|                     Ok(Self::Wallet(wallet_info)) | ||||
|                 } | ||||
|                 payments::WalletData::AliPayRedirect(_) => { | ||||
|                     let wallet_info = StripeWallet::AlipayPayment(AlipayPayment { | ||||
|                         payment_method_types: StripePaymentMethodType::Alipay, | ||||
|                         payment_method_data_type: StripePaymentMethodType::Alipay, | ||||
|                     }); | ||||
|                     Ok(Self::Wallet(wallet_info)) | ||||
| @ -2636,10 +2824,9 @@ impl | ||||
|                 _ => Err(errors::ConnectorError::InvalidWallet.into()), | ||||
|             }, | ||||
|             api::PaymentMethodData::BankDebit(bank_debit_data) => { | ||||
|                 let (pm_type, bank_data, _) = get_bank_debit_data(&bank_debit_data); | ||||
|                 let (_pm_type, bank_data, _) = get_bank_debit_data(&bank_debit_data); | ||||
|  | ||||
|                 Ok(Self::BankDebit(StripeBankDebitData { | ||||
|                     payment_method_types: pm_type, | ||||
|                     bank_specific_data: bank_data, | ||||
|                 })) | ||||
|             } | ||||
|  | ||||
| @ -1,3 +1,4 @@ | ||||
| use api_models::payments; | ||||
| use common_utils::{ext_traits::Encode, pii}; | ||||
| use diesel_models::enums as storage_enums; | ||||
| use error_stack::{report, ResultExt}; | ||||
| @ -123,6 +124,18 @@ pub async fn get_customer_mandates( | ||||
|     } | ||||
| } | ||||
|  | ||||
| fn get_insensitive_payment_method_data_if_exists<F, FData>( | ||||
|     router_data: &types::RouterData<F, FData, types::PaymentsResponseData>, | ||||
| ) -> Option<payments::PaymentMethodData> | ||||
| where | ||||
|     FData: MandateBehaviour, | ||||
| { | ||||
|     match &router_data.request.get_payment_method_data() { | ||||
|         api_models::payments::PaymentMethodData::Card(_) => None, | ||||
|         _ => Some(router_data.request.get_payment_method_data()), | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub async fn mandate_procedure<F, FData>( | ||||
|     state: &AppState, | ||||
|     mut resp: types::RouterData<F, FData, types::PaymentsResponseData>, | ||||
| @ -209,6 +222,7 @@ where | ||||
|                         pm_id.get_required_value("payment_method_id")?, | ||||
|                         mandate_ids, | ||||
|                         network_txn_id, | ||||
|                         get_insensitive_payment_method_data_if_exists(&resp), | ||||
|                     )? { | ||||
|                         let connector = new_mandate_data.connector.clone(); | ||||
|                         logger::debug!("{:?}", new_mandate_data); | ||||
|  | ||||
| @ -1006,7 +1006,6 @@ where | ||||
|                         .to_domain()? | ||||
|                         .make_pm_data(state, &mut payment_data, validate_result.storage_scheme) | ||||
|                         .await?; | ||||
|  | ||||
|                     payment_data.payment_method_data = payment_method_data; | ||||
|                     TokenizationAction::SkipConnectorTokenization | ||||
|                 } | ||||
| @ -1036,7 +1035,6 @@ where | ||||
|                 .to_domain()? | ||||
|                 .make_pm_data(state, &mut payment_data, validate_result.storage_scheme) | ||||
|                 .await?; | ||||
|  | ||||
|             payment_data.payment_method_data = payment_method_data; | ||||
|             (payment_data, TokenizationAction::SkipConnectorTokenization) | ||||
|         } | ||||
| @ -1091,10 +1089,16 @@ where | ||||
|     pub creds_identifier: Option<String>, | ||||
|     pub pm_token: Option<String>, | ||||
|     pub connector_customer_id: Option<String>, | ||||
|     pub recurring_mandate_payment_data: Option<RecurringMandatePaymentData>, | ||||
|     pub ephemeral_key: Option<ephemeral_key::EphemeralKey>, | ||||
|     pub redirect_response: Option<api_models::payments::RedirectResponse>, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Default, Clone)] | ||||
| pub struct RecurringMandatePaymentData { | ||||
|     pub payment_method_type: Option<storage_enums::PaymentMethodType>, //required for making recurring payment using saved payment method through stripe | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Default)] | ||||
| pub struct CustomerDetails { | ||||
|     pub customer_id: Option<String>, | ||||
|  | ||||
| @ -273,6 +273,7 @@ pub async fn get_token_pm_type_mandate_details( | ||||
|     Option<storage_enums::PaymentMethod>, | ||||
|     Option<storage_enums::PaymentMethodType>, | ||||
|     Option<api::MandateData>, | ||||
|     Option<payments::RecurringMandatePaymentData>, | ||||
|     Option<String>, | ||||
| )> { | ||||
|     match mandate_type { | ||||
| @ -287,16 +288,23 @@ pub async fn get_token_pm_type_mandate_details( | ||||
|                 request.payment_method_type, | ||||
|                 Some(setup_mandate), | ||||
|                 None, | ||||
|                 None, | ||||
|             )) | ||||
|         } | ||||
|         Some(api::MandateTransactionType::RecurringMandateTransaction) => { | ||||
|             let (token_, payment_method_, payment_method_type_, mandate_connector) = | ||||
|                 get_token_for_recurring_mandate(state, request, merchant_account).await?; | ||||
|             let ( | ||||
|                 token_, | ||||
|                 payment_method_, | ||||
|                 recurring_mandate_payment_data, | ||||
|                 payment_method_type_, | ||||
|                 mandate_connector, | ||||
|             ) = get_token_for_recurring_mandate(state, request, merchant_account).await?; | ||||
|             Ok(( | ||||
|                 token_, | ||||
|                 payment_method_, | ||||
|                 payment_method_type_.or(request.payment_method_type), | ||||
|                 None, | ||||
|                 recurring_mandate_payment_data, | ||||
|                 mandate_connector, | ||||
|             )) | ||||
|         } | ||||
| @ -306,6 +314,7 @@ pub async fn get_token_pm_type_mandate_details( | ||||
|             request.payment_method_type, | ||||
|             request.mandate_data.clone(), | ||||
|             None, | ||||
|             None, | ||||
|         )), | ||||
|     } | ||||
| } | ||||
| @ -317,6 +326,7 @@ pub async fn get_token_for_recurring_mandate( | ||||
| ) -> RouterResult<( | ||||
|     Option<String>, | ||||
|     Option<storage_enums::PaymentMethod>, | ||||
|     Option<payments::RecurringMandatePaymentData>, | ||||
|     Option<storage_enums::PaymentMethodType>, | ||||
|     Option<String>, | ||||
| )> { | ||||
| @ -355,6 +365,7 @@ pub async fn get_token_for_recurring_mandate( | ||||
|         .to_not_found_response(errors::ApiErrorResponse::PaymentMethodNotFound)?; | ||||
|  | ||||
|     let token = Uuid::new_v4().to_string(); | ||||
|     let payment_method_type = payment_method.payment_method_type; | ||||
|     if let diesel_models::enums::PaymentMethod::Card = payment_method.payment_method { | ||||
|         let _ = cards::get_lookup_key_from_locker(state, &token, &payment_method).await?; | ||||
|         if let Some(payment_method_from_request) = req.payment_method { | ||||
| @ -372,6 +383,9 @@ pub async fn get_token_for_recurring_mandate( | ||||
|         Ok(( | ||||
|             Some(token), | ||||
|             Some(payment_method.payment_method), | ||||
|             Some(payments::RecurringMandatePaymentData { | ||||
|                 payment_method_type, | ||||
|             }), | ||||
|             payment_method.payment_method_type, | ||||
|             Some(mandate.connector), | ||||
|         )) | ||||
| @ -379,6 +393,9 @@ pub async fn get_token_for_recurring_mandate( | ||||
|         Ok(( | ||||
|             None, | ||||
|             Some(payment_method.payment_method), | ||||
|             Some(payments::RecurringMandatePaymentData { | ||||
|                 payment_method_type, | ||||
|             }), | ||||
|             payment_method.payment_method_type, | ||||
|             Some(mandate.connector), | ||||
|         )) | ||||
| @ -1612,6 +1629,7 @@ pub fn check_if_operation_confirm<Op: std::fmt::Debug>(operations: Op) -> bool { | ||||
|     format!("{operations:?}") == "PaymentConfirm" | ||||
| } | ||||
|  | ||||
| #[allow(clippy::too_many_arguments)] | ||||
| pub fn generate_mandate( | ||||
|     merchant_id: String, | ||||
|     connector: String, | ||||
| @ -1620,6 +1638,7 @@ pub fn generate_mandate( | ||||
|     payment_method_id: String, | ||||
|     connector_mandate_id: Option<pii::SecretSerdeValue>, | ||||
|     network_txn_id: Option<String>, | ||||
|     payment_method_data_option: Option<api_models::payments::PaymentMethodData>, | ||||
| ) -> CustomResult<Option<storage::MandateNew>, errors::ApiErrorResponse> { | ||||
|     match (setup_mandate_details, customer) { | ||||
|         (Some(data), Some(cus)) => { | ||||
| @ -1646,7 +1665,12 @@ pub fn generate_mandate( | ||||
|                         .map(masking::Secret::new), | ||||
|                 ) | ||||
|                 .set_customer_user_agent(customer_acceptance.get_user_agent()) | ||||
|                 .set_customer_accepted_at(Some(customer_acceptance.get_accepted_at())); | ||||
|                 .set_customer_accepted_at(Some(customer_acceptance.get_accepted_at())) | ||||
|                 .set_metadata(payment_method_data_option.map(|payment_method_data| { | ||||
|                     pii::SecretSerdeValue::new( | ||||
|                         serde_json::to_value(payment_method_data).unwrap_or_default(), | ||||
|                     ) | ||||
|                 })); | ||||
|  | ||||
|             Ok(Some( | ||||
|                 match data.mandate_type.get_required_value("mandate_type")? { | ||||
| @ -1661,8 +1685,9 @@ pub fn generate_mandate( | ||||
|                             .set_mandate_amount(Some(data.amount)) | ||||
|                             .set_mandate_currency(Some(data.currency)) | ||||
|                             .set_start_date(data.start_date) | ||||
|                             .set_end_date(data.end_date) | ||||
|                             .set_metadata(data.metadata), | ||||
|                             .set_end_date(data.end_date), | ||||
|                         // .set_metadata(data.metadata), | ||||
|                         // we are storing PaymentMethodData in metadata of mandate | ||||
|                         None => &mut new_mandate, | ||||
|                     } | ||||
|                     .set_mandate_type(storage_enums::MandateType::MultiUse) | ||||
| @ -2160,6 +2185,7 @@ pub fn router_data_type_conversion<F1, F2, Req1, Req2, Res1, Res2>( | ||||
|         customer_id: router_data.customer_id, | ||||
|         connector_customer: router_data.connector_customer, | ||||
|         preprocessing_id: router_data.preprocessing_id, | ||||
|         recurring_mandate_payment_data: router_data.recurring_mandate_payment_data, | ||||
|         connector_request_reference_id: router_data.connector_request_reference_id, | ||||
|         test_mode: router_data.test_mode, | ||||
|     } | ||||
|  | ||||
| @ -159,6 +159,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsCancelRequest> | ||||
|                 creds_identifier, | ||||
|                 pm_token: None, | ||||
|                 connector_customer_id: None, | ||||
|                 recurring_mandate_payment_data: None, | ||||
|                 ephemeral_key: None, | ||||
|                 redirect_response: None, | ||||
|             }, | ||||
|  | ||||
| @ -164,6 +164,7 @@ impl<F: Send + Clone> GetTracker<F, payments::PaymentData<F>, api::PaymentsCaptu | ||||
|                 creds_identifier, | ||||
|                 pm_token: None, | ||||
|                 connector_customer_id: None, | ||||
|                 recurring_mandate_payment_data: None, | ||||
|                 ephemeral_key: None, | ||||
|                 redirect_response: None, | ||||
|             }, | ||||
|  | ||||
| @ -72,14 +72,20 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Co | ||||
|             "confirm", | ||||
|         )?; | ||||
|  | ||||
|         let (token, payment_method, payment_method_type, setup_mandate, mandate_connector) = | ||||
|             helpers::get_token_pm_type_mandate_details( | ||||
|                 state, | ||||
|                 request, | ||||
|                 mandate_type.clone(), | ||||
|                 merchant_account, | ||||
|             ) | ||||
|             .await?; | ||||
|         let ( | ||||
|             token, | ||||
|             payment_method, | ||||
|             payment_method_type, | ||||
|             setup_mandate, | ||||
|             recurring_mandate_payment_data, | ||||
|             mandate_connector, | ||||
|         ) = helpers::get_token_pm_type_mandate_details( | ||||
|             state, | ||||
|             request, | ||||
|             mandate_type.clone(), | ||||
|             merchant_account, | ||||
|         ) | ||||
|         .await?; | ||||
|  | ||||
|         let browser_info = request | ||||
|             .browser_info | ||||
| @ -225,6 +231,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Co | ||||
|                 creds_identifier: None, | ||||
|                 pm_token: None, | ||||
|                 connector_customer_id: None, | ||||
|                 recurring_mandate_payment_data, | ||||
|                 ephemeral_key: None, | ||||
|                 redirect_response, | ||||
|             }, | ||||
|  | ||||
| @ -107,14 +107,20 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa | ||||
|             .setup_future_usage | ||||
|             .or(payment_intent.setup_future_usage); | ||||
|  | ||||
|         let (token, payment_method, payment_method_type, setup_mandate, mandate_connector) = | ||||
|             helpers::get_token_pm_type_mandate_details( | ||||
|                 state, | ||||
|                 request, | ||||
|                 mandate_type.clone(), | ||||
|                 merchant_account, | ||||
|             ) | ||||
|             .await?; | ||||
|         let ( | ||||
|             token, | ||||
|             payment_method, | ||||
|             payment_method_type, | ||||
|             setup_mandate, | ||||
|             recurring_mandate_payment_data, | ||||
|             mandate_connector, | ||||
|         ) = helpers::get_token_pm_type_mandate_details( | ||||
|             state, | ||||
|             request, | ||||
|             mandate_type.clone(), | ||||
|             merchant_account, | ||||
|         ) | ||||
|         .await?; | ||||
|  | ||||
|         let browser_info = request | ||||
|             .browser_info | ||||
| @ -281,6 +287,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa | ||||
|                 creds_identifier, | ||||
|                 pm_token: None, | ||||
|                 connector_customer_id: None, | ||||
|                 recurring_mandate_payment_data, | ||||
|                 ephemeral_key: None, | ||||
|                 redirect_response: None, | ||||
|             }, | ||||
|  | ||||
| @ -64,14 +64,20 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa | ||||
|             .get_payment_intent_id() | ||||
|             .change_context(errors::ApiErrorResponse::PaymentNotFound)?; | ||||
|  | ||||
|         let (token, payment_method, payment_method_type, setup_mandate, mandate_connector) = | ||||
|             helpers::get_token_pm_type_mandate_details( | ||||
|                 state, | ||||
|                 request, | ||||
|                 mandate_type, | ||||
|                 merchant_account, | ||||
|             ) | ||||
|             .await?; | ||||
|         let ( | ||||
|             token, | ||||
|             payment_method, | ||||
|             payment_method_type, | ||||
|             setup_mandate, | ||||
|             recurring_mandate_payment_data, | ||||
|             mandate_connector, | ||||
|         ) = helpers::get_token_pm_type_mandate_details( | ||||
|             state, | ||||
|             request, | ||||
|             mandate_type, | ||||
|             merchant_account, | ||||
|         ) | ||||
|         .await?; | ||||
|  | ||||
|         let customer_details = helpers::get_customer_details_from_request(request); | ||||
|  | ||||
| @ -260,6 +266,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa | ||||
|                 creds_identifier, | ||||
|                 pm_token: None, | ||||
|                 connector_customer_id: None, | ||||
|                 recurring_mandate_payment_data, | ||||
|                 ephemeral_key, | ||||
|                 redirect_response: None, | ||||
|             }, | ||||
|  | ||||
| @ -185,6 +185,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::VerifyRequest> for Paym | ||||
|                 creds_identifier, | ||||
|                 pm_token: None, | ||||
|                 connector_customer_id: None, | ||||
|                 recurring_mandate_payment_data: None, | ||||
|                 ephemeral_key: None, | ||||
|                 redirect_response: None, | ||||
|             }, | ||||
|  | ||||
| @ -177,6 +177,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsSessionRequest> | ||||
|                 creds_identifier, | ||||
|                 pm_token: None, | ||||
|                 connector_customer_id: None, | ||||
|                 recurring_mandate_payment_data: None, | ||||
|                 ephemeral_key: None, | ||||
|                 redirect_response: None, | ||||
|             }, | ||||
|  | ||||
| @ -149,6 +149,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsStartRequest> f | ||||
|                 creds_identifier: None, | ||||
|                 pm_token: None, | ||||
|                 connector_customer_id: None, | ||||
|                 recurring_mandate_payment_data: None, | ||||
|                 ephemeral_key: None, | ||||
|                 redirect_response: None, | ||||
|             }, | ||||
|  | ||||
| @ -321,6 +321,7 @@ async fn get_tracker_for_sync< | ||||
|             creds_identifier, | ||||
|             pm_token: None, | ||||
|             connector_customer_id: None, | ||||
|             recurring_mandate_payment_data: None, | ||||
|             ephemeral_key: None, | ||||
|             redirect_response: None, | ||||
|         }, | ||||
|  | ||||
| @ -79,14 +79,20 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa | ||||
|             "update", | ||||
|         )?; | ||||
|  | ||||
|         let (token, payment_method, payment_method_type, setup_mandate, mandate_connector) = | ||||
|             helpers::get_token_pm_type_mandate_details( | ||||
|                 state, | ||||
|                 request, | ||||
|                 mandate_type.clone(), | ||||
|                 merchant_account, | ||||
|             ) | ||||
|             .await?; | ||||
|         let ( | ||||
|             token, | ||||
|             payment_method, | ||||
|             payment_method_type, | ||||
|             setup_mandate, | ||||
|             recurring_mandate_payment_data, | ||||
|             mandate_connector, | ||||
|         ) = helpers::get_token_pm_type_mandate_details( | ||||
|             state, | ||||
|             request, | ||||
|             mandate_type.clone(), | ||||
|             merchant_account, | ||||
|         ) | ||||
|         .await?; | ||||
|  | ||||
|         payment_intent = db | ||||
|             .find_payment_intent_by_payment_id_merchant_id(&payment_id, merchant_id, storage_scheme) | ||||
| @ -329,6 +335,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa | ||||
|                 creds_identifier, | ||||
|                 pm_token: None, | ||||
|                 connector_customer_id: None, | ||||
|                 recurring_mandate_payment_data, | ||||
|                 ephemeral_key: None, | ||||
|                 redirect_response: None, | ||||
|             }, | ||||
|  | ||||
| @ -126,6 +126,7 @@ where | ||||
|         reference_id: None, | ||||
|         payment_method_token: payment_data.pm_token, | ||||
|         connector_customer: payment_data.connector_customer_id, | ||||
|         recurring_mandate_payment_data: payment_data.recurring_mandate_payment_data, | ||||
|         connector_request_reference_id: core_utils::get_connector_request_reference_id( | ||||
|             &state.conf, | ||||
|             &merchant_account.merchant_id, | ||||
|  | ||||
| @ -113,6 +113,7 @@ pub async fn construct_refund_router_data<'a, F>( | ||||
|         reference_id: None, | ||||
|         payment_method_token: None, | ||||
|         connector_customer: None, | ||||
|         recurring_mandate_payment_data: None, | ||||
|         preprocessing_id: None, | ||||
|         connector_request_reference_id: get_connector_request_reference_id( | ||||
|             &state.conf, | ||||
| @ -307,6 +308,7 @@ pub async fn construct_accept_dispute_router_data<'a>( | ||||
|         payment_method_token: None, | ||||
|         connector_customer: None, | ||||
|         customer_id: None, | ||||
|         recurring_mandate_payment_data: None, | ||||
|         preprocessing_id: None, | ||||
|         connector_request_reference_id: get_connector_request_reference_id( | ||||
|             &state.conf, | ||||
| @ -375,6 +377,7 @@ pub async fn construct_submit_evidence_router_data<'a>( | ||||
|         payment_method_token: None, | ||||
|         connector_customer: None, | ||||
|         customer_id: None, | ||||
|         recurring_mandate_payment_data: None, | ||||
|         preprocessing_id: None, | ||||
|         connector_request_reference_id: get_connector_request_reference_id( | ||||
|             &state.conf, | ||||
| @ -444,6 +447,7 @@ pub async fn construct_upload_file_router_data<'a>( | ||||
|         payment_method_token: None, | ||||
|         connector_customer: None, | ||||
|         customer_id: None, | ||||
|         recurring_mandate_payment_data: None, | ||||
|         preprocessing_id: None, | ||||
|         connector_request_reference_id: get_connector_request_reference_id( | ||||
|             &state.conf, | ||||
| @ -515,6 +519,7 @@ pub async fn construct_defend_dispute_router_data<'a>( | ||||
|         payment_method_token: None, | ||||
|         customer_id: None, | ||||
|         connector_customer: None, | ||||
|         recurring_mandate_payment_data: None, | ||||
|         preprocessing_id: None, | ||||
|         connector_request_reference_id: get_connector_request_reference_id( | ||||
|             &state.conf, | ||||
| @ -584,6 +589,7 @@ pub async fn construct_retrieve_file_router_data<'a>( | ||||
|         session_token: None, | ||||
|         reference_id: None, | ||||
|         payment_method_token: None, | ||||
|         recurring_mandate_payment_data: None, | ||||
|         preprocessing_id: None, | ||||
|         connector_request_reference_id: IRRELEVANT_CONNECTOR_REQUEST_REFERENCE_ID_IN_DISPUTE_FLOW | ||||
|             .to_string(), | ||||
|  | ||||
| @ -20,7 +20,10 @@ use masking::Secret; | ||||
|  | ||||
| use self::{api::payments, storage::enums as storage_enums}; | ||||
| pub use crate::core::payments::PaymentAddress; | ||||
| use crate::{core::errors, services}; | ||||
| use crate::{ | ||||
|     core::{errors, payments::RecurringMandatePaymentData}, | ||||
|     services, | ||||
| }; | ||||
|  | ||||
| pub type PaymentsAuthorizeRouterData = | ||||
|     RouterData<api::Authorize, PaymentsAuthorizeData, PaymentsResponseData>; | ||||
| @ -194,6 +197,7 @@ pub struct RouterData<Flow, Request, Response> { | ||||
|     pub session_token: Option<String>, | ||||
|     pub reference_id: Option<String>, | ||||
|     pub payment_method_token: Option<String>, | ||||
|     pub recurring_mandate_payment_data: Option<RecurringMandatePaymentData>, | ||||
|     pub preprocessing_id: Option<String>, | ||||
|  | ||||
|     /// Contains flow-specific data required to construct a request and send it to the connector. | ||||
| @ -820,6 +824,7 @@ impl<F1, F2, T1, T2> From<(&RouterData<F1, T1, PaymentsResponseData>, T2)> | ||||
|             payment_method_token: None, | ||||
|             preprocessing_id: None, | ||||
|             connector_customer: data.connector_customer.clone(), | ||||
|             recurring_mandate_payment_data: data.recurring_mandate_payment_data.clone(), | ||||
|             connector_request_reference_id: data.connector_request_reference_id.clone(), | ||||
|             test_mode: data.test_mode, | ||||
|         } | ||||
|  | ||||
| @ -79,6 +79,7 @@ fn construct_payment_router_data() -> types::PaymentsAuthorizeRouterData { | ||||
|         reference_id: None, | ||||
|         payment_method_token: None, | ||||
|         connector_customer: None, | ||||
|         recurring_mandate_payment_data: None, | ||||
|         preprocessing_id: None, | ||||
|         connector_request_reference_id: uuid::Uuid::new_v4().to_string(), | ||||
|         test_mode: None, | ||||
| @ -125,6 +126,7 @@ fn construct_refund_router_data<F>() -> types::RefundsRouterData<F> { | ||||
|         reference_id: None, | ||||
|         payment_method_token: None, | ||||
|         connector_customer: None, | ||||
|         recurring_mandate_payment_data: None, | ||||
|         preprocessing_id: None, | ||||
|         connector_request_reference_id: uuid::Uuid::new_v4().to_string(), | ||||
|         test_mode: None, | ||||
|  | ||||
| @ -402,6 +402,7 @@ pub trait ConnectorActions: Connector { | ||||
|             reference_id: None, | ||||
|             payment_method_token: None, | ||||
|             connector_customer: None, | ||||
|             recurring_mandate_payment_data: None, | ||||
|             preprocessing_id: None, | ||||
|             connector_request_reference_id: uuid::Uuid::new_v4().to_string(), | ||||
|             test_mode: None, | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Hrithikesh
					Hrithikesh