refactor(connector): [STRIPE] Bank Transfer Api Refactor (#7599)

Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
Sagnik Mitra
2025-03-27 16:47:11 +05:30
committed by GitHub
parent ce3f2493d6
commit e9433d98e1
4 changed files with 183 additions and 409 deletions

View File

@ -1,6 +1,6 @@
pub mod transformers;
use std::{collections::HashMap, ops::Deref};
use std::collections::HashMap;
use common_utils::{
request::RequestContent,
@ -19,7 +19,6 @@ use super::utils::{self as connector_utils, PaymentMethodDataType, RefundsReques
use super::utils::{PayoutsData, RouterData};
use crate::{
configs::settings,
connector::utils::PaymentsPreProcessingData,
consts,
core::{
errors::{self, CustomResult},
@ -203,142 +202,6 @@ impl
// Not Implemented (R)
}
impl api::PaymentsPreProcessing for Stripe {}
impl
services::ConnectorIntegration<
api::PreProcessing,
types::PaymentsPreProcessingData,
types::PaymentsResponseData,
> for Stripe
{
fn get_headers(
&self,
req: &types::PaymentsPreProcessingRouterData,
_connectors: &settings::Connectors,
) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
let mut header = vec![(
headers::CONTENT_TYPE.to_string(),
types::PaymentsPreProcessingType::get_content_type(self)
.to_string()
.into(),
)];
let mut api_key = self.get_auth_header(&req.connector_auth_type)?;
header.append(&mut api_key);
Ok(header)
}
fn get_content_type(&self) -> &'static str {
self.common_get_content_type()
}
fn get_url(
&self,
_req: &types::PaymentsPreProcessingRouterData,
connectors: &settings::Connectors,
) -> CustomResult<String, errors::ConnectorError> {
Ok(format!("{}{}", self.base_url(connectors), "v1/sources"))
}
fn get_request_body(
&self,
req: &types::PaymentsPreProcessingRouterData,
_connectors: &settings::Connectors,
) -> CustomResult<RequestContent, errors::ConnectorError> {
let req_currency = req.request.get_currency()?;
let req_amount = req.request.get_minor_amount()?;
let amount =
connector_utils::convert_amount(self.amount_converter, req_amount, req_currency)?;
let connector_req =
stripe::StripeCreditTransferSourceRequest::try_from((req, amount, req_currency))?;
Ok(RequestContent::FormUrlEncoded(Box::new(connector_req)))
}
fn build_request(
&self,
req: &types::PaymentsPreProcessingRouterData,
connectors: &settings::Connectors,
) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
Ok(Some(
services::RequestBuilder::new()
.method(services::Method::Post)
.url(&types::PaymentsPreProcessingType::get_url(
self, req, connectors,
)?)
.attach_default_headers()
.headers(types::PaymentsPreProcessingType::get_headers(
self, req, connectors,
)?)
.set_body(types::PaymentsPreProcessingType::get_request_body(
self, req, connectors,
)?)
.build(),
))
}
fn handle_response(
&self,
data: &types::PaymentsPreProcessingRouterData,
event_builder: Option<&mut ConnectorEvent>,
res: types::Response,
) -> CustomResult<types::PaymentsPreProcessingRouterData, errors::ConnectorError> {
let response: stripe::StripeSourceResponse = res
.response
.parse_struct("StripeSourceResponse")
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
event_builder.map(|i| i.set_response_body(&response));
router_env::logger::info!(connector_response=?response);
types::RouterData::try_from(types::ResponseRouterData {
response,
data: data.clone(),
http_code: res.status_code,
})
.change_context(errors::ConnectorError::ResponseHandlingFailed)
}
fn get_error_response(
&self,
res: types::Response,
event_builder: Option<&mut ConnectorEvent>,
) -> CustomResult<types::ErrorResponse, errors::ConnectorError> {
let response: stripe::ErrorResponse = res
.response
.parse_struct("ErrorResponse")
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
event_builder.map(|i| i.set_error_response_body(&response));
router_env::logger::info!(connector_response=?response);
Ok(types::ErrorResponse {
status_code: res.status_code,
code: response
.error
.code
.clone()
.unwrap_or_else(|| consts::NO_ERROR_CODE.to_string()),
message: response
.error
.code
.unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()),
reason: response.error.message.map(|message| {
response
.error
.decline_code
.map(|decline_code| {
format!("message - {}, decline_code - {}", message, decline_code)
})
.unwrap_or(message)
}),
attempt_status: None,
connector_transaction_id: response.error.payment_intent.map(|pi| pi.id),
issuer_error_code: None,
issuer_error_message: None,
})
}
}
impl api::ConnectorCustomer for Stripe {}
impl
@ -978,29 +841,14 @@ impl
fn get_url(
&self,
req: &types::PaymentsAuthorizeRouterData,
_req: &types::PaymentsAuthorizeRouterData,
connectors: &settings::Connectors,
) -> CustomResult<String, errors::ConnectorError> {
match &req.request.payment_method_data {
domain::PaymentMethodData::BankTransfer(bank_transfer_data) => {
match bank_transfer_data.deref() {
domain::BankTransferData::AchBankTransfer { .. }
| domain::BankTransferData::MultibancoBankTransfer { .. } => {
Ok(format!("{}{}", self.base_url(connectors), "v1/charges"))
}
_ => Ok(format!(
"{}{}",
self.base_url(connectors),
"v1/payment_intents"
)),
}
}
_ => Ok(format!(
"{}{}",
self.base_url(connectors),
"v1/payment_intents"
)),
}
Ok(format!(
"{}{}",
self.base_url(connectors),
"v1/payment_intents"
))
}
fn get_request_body(
@ -1013,16 +861,9 @@ impl
req.request.minor_amount,
req.request.currency,
)?;
match &req.request.payment_method_data {
domain::PaymentMethodData::BankTransfer(bank_transfer_data) => {
stripe::get_bank_transfer_request_data(req, bank_transfer_data.deref(), amount)
}
_ => {
let connector_req = stripe::PaymentIntentRequest::try_from((req, amount))?;
let connector_req = stripe::PaymentIntentRequest::try_from((req, amount))?;
Ok(RequestContent::FormUrlEncoded(Box::new(connector_req)))
}
}
Ok(RequestContent::FormUrlEncoded(Box::new(connector_req)))
}
fn build_request(
@ -1053,94 +894,31 @@ impl
event_builder: Option<&mut ConnectorEvent>,
res: types::Response,
) -> CustomResult<types::PaymentsAuthorizeRouterData, errors::ConnectorError> {
match &data.request.payment_method_data {
domain::PaymentMethodData::BankTransfer(bank_transfer_data) => match bank_transfer_data
.deref()
{
domain::BankTransferData::AchBankTransfer { .. }
| domain::BankTransferData::MultibancoBankTransfer { .. } => {
let response: stripe::ChargesResponse = res
.response
.parse_struct("ChargesResponse")
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
let response: stripe::PaymentIntentResponse = res
.response
.parse_struct("PaymentIntentResponse")
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
let response_integrity_object =
connector_utils::get_authorise_integrity_object(
self.amount_converter,
response.amount,
response.currency.clone(),
)?;
let response_integrity_object = connector_utils::get_authorise_integrity_object(
self.amount_converter,
response.amount,
response.currency.clone(),
)?;
event_builder.map(|i| i.set_response_body(&response));
router_env::logger::info!(connector_response=?response);
event_builder.map(|i| i.set_response_body(&response));
router_env::logger::info!(connector_response=?response);
let new_router_data = types::RouterData::try_from(types::ResponseRouterData {
response,
data: data.clone(),
http_code: res.status_code,
});
let new_router_data = types::RouterData::try_from(types::ResponseRouterData {
response,
data: data.clone(),
http_code: res.status_code,
})
.change_context(errors::ConnectorError::ResponseHandlingFailed);
new_router_data.map(|mut router_data| {
router_data.request.integrity_object = Some(response_integrity_object);
router_data
})
}
_ => {
let response: stripe::PaymentIntentResponse = res
.response
.parse_struct("PaymentIntentResponse")
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
let response_integrity_object =
connector_utils::get_authorise_integrity_object(
self.amount_converter,
response.amount,
response.currency.clone(),
)?;
event_builder.map(|i| i.set_response_body(&response));
router_env::logger::info!(connector_response=?response);
let new_router_data = types::RouterData::try_from(types::ResponseRouterData {
response,
data: data.clone(),
http_code: res.status_code,
});
new_router_data.map(|mut router_data| {
router_data.request.integrity_object = Some(response_integrity_object);
router_data
})
}
},
_ => {
let response: stripe::PaymentIntentResponse = res
.response
.parse_struct("PaymentIntentResponse")
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
let response_integrity_object = connector_utils::get_authorise_integrity_object(
self.amount_converter,
response.amount,
response.currency.clone(),
)?;
event_builder.map(|i| i.set_response_body(&response));
router_env::logger::info!(connector_response=?response);
let new_router_data = types::RouterData::try_from(types::ResponseRouterData {
response,
data: data.clone(),
http_code: res.status_code,
})
.change_context(errors::ConnectorError::ResponseHandlingFailed);
new_router_data.map(|mut router_data| {
router_data.request.integrity_object = Some(response_integrity_object);
router_data
})
}
}
new_router_data.map(|mut router_data| {
router_data.request.integrity_object = Some(response_integrity_object);
router_data
})
}
fn get_error_response(

View File

@ -1,6 +1,6 @@
use std::{collections::HashMap, ops::Deref};
use api_models::{self, enums as api_enums};
use api_models::{self, enums as api_enums, payments};
use common_utils::{
errors::CustomResult,
ext_traits::{ByteSliceExt, Encode},
@ -8,7 +8,6 @@ use common_utils::{
request::RequestContent,
types::MinorUnit,
};
use diesel_models::enums as storage_enums;
use error_stack::ResultExt;
use hyperswitch_domain_models::mandates::AcceptanceType;
use masking::{ExposeInterface, ExposeOptionInterface, Mask, PeekInterface, Secret};
@ -22,9 +21,7 @@ pub mod connect;
pub use self::connect::*;
use crate::{
collect_missing_value_keys,
connector::utils::{
self as connector_util, ApplePay, ApplePayDecrypt, PaymentsPreProcessingData, RouterData,
},
connector::utils::{self as connector_util, ApplePay, ApplePayDecrypt, RouterData},
consts,
core::errors,
headers, services,
@ -394,13 +391,23 @@ pub struct StripeOnlineBankingFpx {
#[derive(Debug, Eq, PartialEq, Serialize)]
pub struct AchTransferData {
#[serde(rename = "owner[email]")]
pub email: Email,
#[serde(rename = "payment_method_data[type]")]
pub payment_method_data_type: StripePaymentMethodType,
#[serde(rename = "payment_method_options[customer_balance][bank_transfer][type]")]
pub bank_transfer_type: StripeCreditTransferTypes,
#[serde(rename = "payment_method_types[0]")]
pub payment_method_type: StripePaymentMethodType,
#[serde(rename = "payment_method_options[customer_balance][funding_type]")]
pub balance_funding_type: BankTransferType,
}
#[derive(Debug, Eq, PartialEq, Serialize)]
pub struct MultibancoTransferData {
#[serde(rename = "owner[email]")]
#[serde(rename = "payment_method_data[type]")]
pub payment_method_data_type: StripeCreditTransferTypes,
#[serde(rename = "payment_method_types[0]")]
pub payment_method_type: StripeCreditTransferTypes,
#[serde(rename = "payment_method_data[billing_details][email]")]
pub email: Email,
}
@ -658,6 +665,7 @@ pub enum StripePaymentMethodType {
#[serde(rename_all = "snake_case")]
#[allow(dead_code)]
pub enum StripeCreditTransferTypes {
#[serde(rename = "us_bank_transfer")]
AchCreditTransfer,
Multibanco,
Blik,
@ -1233,11 +1241,10 @@ fn create_stripe_payment_method(
domain::BankTransferData::AchBankTransfer {} => Ok((
StripePaymentMethodData::BankTransfer(StripeBankTransferData::AchBankTransfer(
Box::new(AchTransferData {
email: billing_address.email.ok_or(
errors::ConnectorError::MissingRequiredField {
field_name: "billing_address.email",
},
)?,
payment_method_data_type: StripePaymentMethodType::CustomerBalance,
bank_transfer_type: StripeCreditTransferTypes::AchCreditTransfer,
payment_method_type: StripePaymentMethodType::CustomerBalance,
balance_funding_type: BankTransferType::BankTransfers,
}),
)),
None,
@ -1247,6 +1254,8 @@ fn create_stripe_payment_method(
StripePaymentMethodData::BankTransfer(
StripeBankTransferData::MultibancoBankTransfers(Box::new(
MultibancoTransferData {
payment_method_data_type: StripeCreditTransferTypes::Multibanco,
payment_method_type: StripeCreditTransferTypes::Multibanco,
email: billing_address.email.ok_or(
errors::ConnectorError::MissingRequiredField {
field_name: "billing_address.email",
@ -1739,18 +1748,14 @@ impl TryFrom<(&types::PaymentsAuthorizeRouterData, MinorUnit)> for PaymentIntent
.clone()
.and_then(|mandate_ids| mandate_ids.mandate_reference_id)
{
Some(api_models::payments::MandateReferenceId::ConnectorMandateId(
connector_mandate_ids,
)) => (
Some(payments::MandateReferenceId::ConnectorMandateId(connector_mandate_ids)) => (
None,
connector_mandate_ids.get_connector_mandate_id(),
StripeBillingAddress::default(),
get_payment_method_type_for_saved_payment_method_payment(item)?,
None,
),
Some(api_models::payments::MandateReferenceId::NetworkMandateId(
network_transaction_id,
)) => {
Some(payments::MandateReferenceId::NetworkMandateId(network_transaction_id)) => {
payment_method_options = Some(StripePaymentMethodOptions::Card {
mandate_options: None,
network_transaction_id: None,
@ -1815,7 +1820,7 @@ impl TryFrom<(&types::PaymentsAuthorizeRouterData, MinorUnit)> for PaymentIntent
None,
)
}
Some(api_models::payments::MandateReferenceId::NetworkTokenWithNTI(_)) | None => {
Some(payments::MandateReferenceId::NetworkTokenWithNTI(_)) | None => {
let (payment_method_data, payment_method_type, billing_address) =
create_stripe_payment_method(
&item.request.payment_method_data,
@ -2589,34 +2594,75 @@ pub fn get_connector_metadata(
let next_action_response = next_action
.and_then(|next_action_response| match next_action_response {
StripeNextActionResponse::DisplayBankTransferInstructions(response) => {
let bank_instructions = response.financial_addresses.first();
let (sepa_bank_instructions, bacs_bank_instructions) =
bank_instructions.map_or((None, None), |financial_address| {
(
financial_address
.iban
.to_owned()
.map(|sepa_financial_details| SepaFinancialDetails {
account_holder_name: sepa_financial_details.account_holder_name,
bic: sepa_financial_details.bic,
country: sepa_financial_details.country,
iban: sepa_financial_details.iban,
reference: response.reference.to_owned(),
}),
financial_address.sort_code.to_owned(),
)
});
match response.financial_addresses.clone() {
FinancialInformation::StripeFinancialInformation(financial_addresses) => {
let bank_instructions = financial_addresses.first();
let (sepa_bank_instructions, bacs_bank_instructions) = bank_instructions
.map_or((None, None), |financial_address| {
(
financial_address.iban.to_owned().map(
|sepa_financial_details| SepaFinancialDetails {
account_holder_name: sepa_financial_details
.account_holder_name,
bic: sepa_financial_details.bic,
country: sepa_financial_details.country,
iban: sepa_financial_details.iban,
reference: response.reference.to_owned(),
},
),
financial_address.sort_code.to_owned(),
)
});
let bank_transfer_instructions = SepaAndBacsBankTransferInstructions {
sepa_bank_instructions,
bacs_bank_instructions,
receiver: SepaAndBacsReceiver {
amount_received: amount - response.amount_remaining,
amount_remaining: response.amount_remaining,
},
};
let bank_transfer_instructions = SepaAndBacsBankTransferInstructions {
sepa_bank_instructions,
bacs_bank_instructions,
receiver: SepaAndBacsReceiver {
amount_received: amount - response.amount_remaining,
amount_remaining: response.amount_remaining,
},
};
Some(bank_transfer_instructions.encode_to_value())
}
FinancialInformation::AchFinancialInformation(financial_addresses) => {
let mut ach_financial_information = HashMap::new();
for address in financial_addresses {
match address.financial_details {
AchFinancialDetails::Aba(aba_details) => {
ach_financial_information
.insert("account_number", aba_details.account_number);
ach_financial_information
.insert("bank_name", aba_details.bank_name);
ach_financial_information
.insert("routing_number", aba_details.routing_number);
}
AchFinancialDetails::Swift(swift_details) => {
ach_financial_information
.insert("swift_code", swift_details.swift_code);
}
}
}
Some(bank_transfer_instructions.encode_to_value())
let ach_financial_information_value =
serde_json::to_value(ach_financial_information).ok()?;
let ach_transfer_instruction =
serde_json::from_value::<payments::AchTransfer>(
ach_financial_information_value,
)
.ok()?;
let bank_transfer_instructions = payments::BankTransferNextStepsData {
bank_transfer_instructions:
payments::BankTransferInstructions::AchCreditTransfer(Box::new(
ach_transfer_instruction,
)),
receiver: None,
};
Some(bank_transfer_instructions.encode_to_value())
}
}
}
StripeNextActionResponse::WechatPayDisplayQrCode(response) => {
let wechat_pay_instructions = QrCodeNextInstructions {
@ -2633,6 +2679,18 @@ pub fn get_connector_metadata(
};
Some(cashapp_qr_instructions.encode_to_value())
}
StripeNextActionResponse::MultibancoDisplayDetails(response) => {
let multibanco_bank_transfer_instructions = payments::BankTransferNextStepsData {
bank_transfer_instructions: payments::BankTransferInstructions::Multibanco(
Box::new(payments::MultibancoTransferInstructions {
reference: response.clone().reference,
entity: response.clone().entity.expose(),
}),
),
receiver: None,
};
Some(multibanco_bank_transfer_instructions.encode_to_value())
}
_ => None,
})
.transpose()
@ -2886,6 +2944,7 @@ pub enum StripeNextActionResponse {
VerifyWithMicrodeposits(StripeVerifyWithMicroDepositsResponse),
WechatPayDisplayQrCode(WechatPayRedirectToQr),
DisplayBankTransferInstructions(StripeBankTransferDetails),
MultibancoDisplayDetails(MultibancoCreditTansferResponse),
NoNextActionBody,
}
@ -2901,6 +2960,7 @@ impl StripeNextActionResponse {
}
Self::CashappHandleRedirectOrDisplayQrCode(_) => None,
Self::DisplayBankTransferInstructions(_) => None,
Self::MultibancoDisplayDetails(_) => None,
Self::NoNextActionBody => None,
}
}
@ -2950,6 +3010,7 @@ impl Serialize for StripeNextActionResponse {
Self::VerifyWithMicrodeposits(ref i) => Serialize::serialize(i, serializer),
Self::WechatPayDisplayQrCode(ref i) => Serialize::serialize(i, serializer),
Self::DisplayBankTransferInstructions(ref i) => Serialize::serialize(i, serializer),
Self::MultibancoDisplayDetails(ref i) => Serialize::serialize(i, serializer),
Self::NoNextActionBody => Serialize::serialize("NoNextActionBody", serializer),
}
}
@ -2975,11 +3036,18 @@ pub struct StripeVerifyWithMicroDepositsResponse {
hosted_verification_url: Url,
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(untagged)]
pub enum FinancialInformation {
AchFinancialInformation(Vec<AchFinancialInformation>),
StripeFinancialInformation(Vec<StripeFinancialInformation>),
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub struct StripeBankTransferDetails {
pub amount_remaining: MinorUnit,
pub currency: String,
pub financial_addresses: Vec<StripeFinancialInformation>,
pub financial_addresses: FinancialInformation,
pub hosted_instructions_url: Option<String>,
pub reference: Option<String>,
#[serde(rename = "type")]
@ -3000,6 +3068,27 @@ pub struct QrCodeResponse {
pub image_url_svg: Url,
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub struct AbaDetails {
pub account_number: Secret<String>,
pub bank_name: Secret<String>,
pub routing_number: Secret<String>,
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub struct SwiftDetails {
pub account_number: Secret<String>,
pub bank_name: Secret<String>,
pub swift_code: Secret<String>,
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum AchFinancialDetails {
Aba(AbaDetails),
Swift(SwiftDetails),
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub struct StripeFinancialInformation {
pub iban: Option<SepaFinancialDetails>,
@ -3009,6 +3098,15 @@ pub struct StripeFinancialInformation {
pub financial_info_type: String,
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub struct AchFinancialInformation {
#[serde(flatten)]
pub financial_details: AchFinancialDetails,
pub supported_networks: Vec<String>,
#[serde(rename = "type")]
pub financial_info_type: String,
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub struct SepaFinancialDetails {
pub account_holder_name: Secret<String>,
@ -3380,95 +3478,6 @@ impl TryFrom<MinorUnit> for CaptureRequest {
}
}
impl
TryFrom<(
&types::PaymentsPreProcessingRouterData,
MinorUnit,
storage_enums::Currency,
)> for StripeCreditTransferSourceRequest
{
type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(
data: (
&types::PaymentsPreProcessingRouterData,
MinorUnit,
storage_enums::Currency,
),
) -> Result<Self, Self::Error> {
let item = data.0;
let currency = data.2;
let amount = data.1;
match &item.request.payment_method_data {
Some(domain::PaymentMethodData::BankTransfer(bank_transfer_data)) => {
match **bank_transfer_data {
domain::BankTransferData::MultibancoBankTransfer { .. } => Ok(
Self::MultibancoBankTansfer(MultibancoCreditTransferSourceRequest {
transfer_type: StripeCreditTransferTypes::Multibanco,
currency,
payment_method_data: MultibancoTransferData {
email: item.get_billing_email().or(item.request.get_email())?,
},
amount: Some(amount),
return_url: Some(item.request.get_router_return_url()?),
}),
),
domain::BankTransferData::AchBankTransfer { .. } => {
Ok(Self::AchBankTansfer(AchCreditTransferSourceRequest {
transfer_type: StripeCreditTransferTypes::AchCreditTransfer,
payment_method_data: AchTransferData {
email: item.get_billing_email().or(item.request.get_email())?,
},
currency,
}))
}
domain::BankTransferData::SepaBankTransfer { .. }
| domain::BankTransferData::BacsBankTransfer { .. }
| domain::BankTransferData::PermataBankTransfer { .. }
| domain::BankTransferData::BcaBankTransfer { .. }
| domain::BankTransferData::BniVaBankTransfer { .. }
| domain::BankTransferData::BriVaBankTransfer { .. }
| domain::BankTransferData::CimbVaBankTransfer { .. }
| domain::BankTransferData::DanamonVaBankTransfer { .. }
| domain::BankTransferData::MandiriVaBankTransfer { .. }
| domain::BankTransferData::LocalBankTransfer { .. }
| domain::BankTransferData::InstantBankTransfer {}
| domain::BankTransferData::Pix { .. }
| domain::BankTransferData::Pse { .. } => {
Err(errors::ConnectorError::NotImplemented(
connector_util::get_unimplemented_payment_method_error_message(
"stripe",
),
)
.into())
}
}
}
Some(domain::PaymentMethodData::Card(..))
| Some(domain::PaymentMethodData::Wallet(..))
| Some(domain::PaymentMethodData::BankDebit(..))
| Some(domain::PaymentMethodData::BankRedirect(..))
| Some(domain::PaymentMethodData::PayLater(..))
| Some(domain::PaymentMethodData::Crypto(..))
| Some(domain::PaymentMethodData::Reward)
| Some(domain::PaymentMethodData::RealTimePayment(..))
| Some(domain::PaymentMethodData::MobilePayment(..))
| Some(domain::PaymentMethodData::MandatePayment)
| Some(domain::PaymentMethodData::Upi(..))
| Some(domain::PaymentMethodData::GiftCard(..))
| Some(domain::PaymentMethodData::CardRedirect(..))
| Some(domain::PaymentMethodData::Voucher(..))
| Some(domain::PaymentMethodData::OpenBanking(..))
| Some(domain::PaymentMethodData::CardToken(..))
| Some(domain::PaymentMethodData::NetworkToken(..))
| Some(domain::PaymentMethodData::CardDetailsForNetworkTransactionId(_))
| None => Err(errors::ConnectorError::NotImplemented(
connector_util::get_unimplemented_payment_method_error_message("stripe"),
)
.into()),
}
}
}
impl<F, T>
TryFrom<types::ResponseRouterData<F, StripeSourceResponse, T, types::PaymentsResponseData>>
for types::RouterData<F, T, types::PaymentsResponseData>
@ -3865,12 +3874,17 @@ impl
{
domain::BankTransferData::AchBankTransfer {} => Ok(Self::BankTransfer(
StripeBankTransferData::AchBankTransfer(Box::new(AchTransferData {
email: item.get_billing_email()?,
payment_method_data_type: StripePaymentMethodType::CustomerBalance,
bank_transfer_type: StripeCreditTransferTypes::AchCreditTransfer,
payment_method_type: StripePaymentMethodType::CustomerBalance,
balance_funding_type: BankTransferType::BankTransfers,
})),
)),
domain::BankTransferData::MultibancoBankTransfer {} => Ok(Self::BankTransfer(
StripeBankTransferData::MultibancoBankTransfers(Box::new(
MultibancoTransferData {
payment_method_data_type: StripeCreditTransferTypes::Multibanco,
payment_method_type: StripeCreditTransferTypes::Multibanco,
email: item.get_billing_email()?,
},
)),

View File

@ -4479,26 +4479,7 @@ where
}
//TODO: For ACH transfers, if preprocessing_step is not required for connectors encountered in future, add the check
let router_data_and_should_continue_payment = match payment_data.get_payment_method_data() {
Some(domain::PaymentMethodData::BankTransfer(data)) => match data.deref() {
domain::BankTransferData::AchBankTransfer { .. }
| domain::BankTransferData::MultibancoBankTransfer { .. }
if connector.connector_name == router_types::Connector::Stripe =>
{
if payment_data
.get_payment_attempt()
.preprocessing_step_id
.is_none()
{
(
router_data.preprocessing_steps(state, connector).await?,
false,
)
} else {
(router_data, should_continue_payment)
}
}
_ => (router_data, should_continue_payment),
},
Some(domain::PaymentMethodData::BankTransfer(_)) => (router_data, should_continue_payment),
Some(domain::PaymentMethodData::Wallet(_)) => {
if is_preprocessing_required_for_wallets(connector.connector_name.to_string()) {
(

View File

@ -632,6 +632,7 @@ default_imp_for_pre_processing_steps!(
connector::Plaid,
connector::Riskified,
connector::Signifyd,
connector::Stripe,
connector::Threedsecureio,
connector::Wellsfargopayout,
connector::Wise