mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-28 20:23:43 +08:00
fix(connector): [STRIPE] Retrieving Connect Account Id from Mandate Metadata in MITs (#8326)
Co-authored-by: Sayak Bhattacharya <sayak.b@Sayak-Bhattacharya-G092THXJ34.local>
This commit is contained in:
committed by
GitHub
parent
aee3f6441f
commit
17c30b6105
@ -79,6 +79,8 @@ pub struct Extra {
|
|||||||
pub reason: Option<String>,
|
pub reason: Option<String>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub connector_transaction_id: Option<String>,
|
pub connector_transaction_id: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub fields: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Debug, Clone)]
|
#[derive(Serialize, Debug, Clone)]
|
||||||
|
|||||||
@ -13,7 +13,6 @@ use serde::{Deserialize, Serialize};
|
|||||||
use utoipa::ToSchema;
|
use utoipa::ToSchema;
|
||||||
|
|
||||||
use crate::domain::{AdyenSplitData, XenditSplitSubMerchantData};
|
use crate::domain::{AdyenSplitData, XenditSplitSubMerchantData};
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Serialize, Deserialize, Debug, Clone, PartialEq, Eq, FromSqlRow, AsExpression, ToSchema,
|
Serialize, Deserialize, Debug, Clone, PartialEq, Eq, FromSqlRow, AsExpression, ToSchema,
|
||||||
)]
|
)]
|
||||||
@ -44,7 +43,7 @@ pub struct StripeSplitPaymentRequest {
|
|||||||
|
|
||||||
/// Platform fees to be collected on the payment
|
/// Platform fees to be collected on the payment
|
||||||
#[schema(value_type = i64, example = 6540)]
|
#[schema(value_type = i64, example = 6540)]
|
||||||
pub application_fees: MinorUnit,
|
pub application_fees: Option<MinorUnit>,
|
||||||
|
|
||||||
/// Identifier for the reseller's account where the funds were transferred
|
/// Identifier for the reseller's account where the funds were transferred
|
||||||
pub transfer_account_id: String,
|
pub transfer_account_id: String,
|
||||||
@ -139,7 +138,7 @@ pub struct StripeChargeResponseData {
|
|||||||
|
|
||||||
/// Platform fees collected on the payment
|
/// Platform fees collected on the payment
|
||||||
#[schema(value_type = i64, example = 6540)]
|
#[schema(value_type = i64, example = 6540)]
|
||||||
pub application_fees: MinorUnit,
|
pub application_fees: Option<MinorUnit>,
|
||||||
|
|
||||||
/// Identifier for the reseller's account where the funds were transferred
|
/// Identifier for the reseller's account where the funds were transferred
|
||||||
pub transfer_account_id: String,
|
pub transfer_account_id: String,
|
||||||
|
|||||||
@ -13,6 +13,7 @@ use std::{
|
|||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
fmt::Display,
|
fmt::Display,
|
||||||
iter::Sum,
|
iter::Sum,
|
||||||
|
num::NonZeroI64,
|
||||||
ops::{Add, Mul, Sub},
|
ops::{Add, Mul, Sub},
|
||||||
primitive::i64,
|
primitive::i64,
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
@ -452,6 +453,12 @@ impl MinorUnit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<NonZeroI64> for MinorUnit {
|
||||||
|
fn from(val: NonZeroI64) -> Self {
|
||||||
|
Self::new(val.get())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Display for MinorUnit {
|
impl Display for MinorUnit {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "{}", self.0)
|
write!(f, "{}", self.0)
|
||||||
|
|||||||
@ -870,9 +870,13 @@ impl ConnectorIntegration<Authorize, PaymentsAuthorizeData, PaymentsResponseData
|
|||||||
.to_string()
|
.to_string()
|
||||||
.into(),
|
.into(),
|
||||||
)];
|
)];
|
||||||
|
|
||||||
let mut api_key = self.get_auth_header(&req.connector_auth_type)?;
|
let mut api_key = self.get_auth_header(&req.connector_auth_type)?;
|
||||||
header.append(&mut api_key);
|
header.append(&mut api_key);
|
||||||
|
|
||||||
|
let stripe_split_payment_metadata = stripe::StripeSplitPaymentRequest::try_from(req)?;
|
||||||
|
|
||||||
|
// if the request has split payment object, then append the transfer account id in headers in charge_type is Direct
|
||||||
if let Some(common_types::payments::SplitPaymentsRequest::StripeSplitPayment(
|
if let Some(common_types::payments::SplitPaymentsRequest::StripeSplitPayment(
|
||||||
stripe_split_payment,
|
stripe_split_payment,
|
||||||
)) = &req.request.split_payments
|
)) = &req.request.split_payments
|
||||||
@ -890,6 +894,16 @@ impl ConnectorIntegration<Authorize, PaymentsAuthorizeData, PaymentsResponseData
|
|||||||
header.append(&mut customer_account_header);
|
header.append(&mut customer_account_header);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// if request doesn't have transfer_account_id, but stripe_split_payment_metadata has it, append it
|
||||||
|
else if let Some(transfer_account_id) =
|
||||||
|
stripe_split_payment_metadata.transfer_account_id.clone()
|
||||||
|
{
|
||||||
|
let mut customer_account_header = vec![(
|
||||||
|
STRIPE_COMPATIBLE_CONNECT_ACCOUNT.to_string(),
|
||||||
|
transfer_account_id.into_masked(),
|
||||||
|
)];
|
||||||
|
header.append(&mut customer_account_header);
|
||||||
|
}
|
||||||
Ok(header)
|
Ok(header)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@ use std::{collections::HashMap, ops::Deref};
|
|||||||
|
|
||||||
use api_models::{self, enums as api_enums, payments};
|
use api_models::{self, enums as api_enums, payments};
|
||||||
use common_enums::{enums, AttemptStatus, PaymentChargeType, StripeChargeType};
|
use common_enums::{enums, AttemptStatus, PaymentChargeType, StripeChargeType};
|
||||||
|
use common_types::payments::SplitPaymentsRequest;
|
||||||
use common_utils::{
|
use common_utils::{
|
||||||
collect_missing_value_keys,
|
collect_missing_value_keys,
|
||||||
errors::CustomResult,
|
errors::CustomResult,
|
||||||
@ -198,7 +199,7 @@ pub struct PaymentIntentRequest {
|
|||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Serialize)]
|
#[derive(Debug, Eq, PartialEq, Serialize)]
|
||||||
pub struct IntentCharges {
|
pub struct IntentCharges {
|
||||||
pub application_fee_amount: MinorUnit,
|
pub application_fee_amount: Option<MinorUnit>,
|
||||||
#[serde(
|
#[serde(
|
||||||
rename = "transfer_data[destination]",
|
rename = "transfer_data[destination]",
|
||||||
skip_serializing_if = "Option::is_none"
|
skip_serializing_if = "Option::is_none"
|
||||||
@ -1668,8 +1669,39 @@ impl TryFrom<(&PaymentsAuthorizeRouterData, MinorUnit)> for PaymentIntentRequest
|
|||||||
fn try_from(data: (&PaymentsAuthorizeRouterData, MinorUnit)) -> Result<Self, Self::Error> {
|
fn try_from(data: (&PaymentsAuthorizeRouterData, MinorUnit)) -> Result<Self, Self::Error> {
|
||||||
let item = data.0;
|
let item = data.0;
|
||||||
|
|
||||||
|
let mandate_metadata = item
|
||||||
|
.request
|
||||||
|
.mandate_id
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|mandate_id| mandate_id.mandate_reference_id.as_ref())
|
||||||
|
.and_then(|reference_id| match reference_id {
|
||||||
|
payments::MandateReferenceId::ConnectorMandateId(mandate_data) => {
|
||||||
|
Some(mandate_data.get_mandate_metadata())
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
});
|
||||||
|
|
||||||
|
let (transfer_account_id, charge_type, application_fees) = if let Some(secret_value) =
|
||||||
|
mandate_metadata.as_ref().and_then(|s| s.as_ref())
|
||||||
|
{
|
||||||
|
let json_value = secret_value.clone().expose();
|
||||||
|
|
||||||
|
let parsed: Result<StripeSplitPaymentRequest, _> = serde_json::from_value(json_value);
|
||||||
|
|
||||||
|
match parsed {
|
||||||
|
Ok(data) => (
|
||||||
|
data.transfer_account_id,
|
||||||
|
data.charge_type,
|
||||||
|
data.application_fees,
|
||||||
|
),
|
||||||
|
Err(_) => (None, None, None),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
(None, None, None)
|
||||||
|
};
|
||||||
|
|
||||||
let payment_method_token = match &item.request.split_payments {
|
let payment_method_token = match &item.request.split_payments {
|
||||||
Some(common_types::payments::SplitPaymentsRequest::StripeSplitPayment(_)) => {
|
Some(SplitPaymentsRequest::StripeSplitPayment(_)) => {
|
||||||
match item.payment_method_token.clone() {
|
match item.payment_method_token.clone() {
|
||||||
Some(PaymentMethodToken::Token(secret)) => Some(secret),
|
Some(PaymentMethodToken::Token(secret)) => Some(secret),
|
||||||
_ => None,
|
_ => None,
|
||||||
@ -1948,27 +1980,45 @@ impl TryFrom<(&PaymentsAuthorizeRouterData, MinorUnit)> for PaymentIntentRequest
|
|||||||
};
|
};
|
||||||
|
|
||||||
let charges = match &item.request.split_payments {
|
let charges = match &item.request.split_payments {
|
||||||
Some(common_types::payments::SplitPaymentsRequest::StripeSplitPayment(
|
Some(SplitPaymentsRequest::StripeSplitPayment(stripe_split_payment)) => {
|
||||||
stripe_split_payment,
|
match &stripe_split_payment.charge_type {
|
||||||
)) => match &stripe_split_payment.charge_type {
|
PaymentChargeType::Stripe(charge_type) => match charge_type {
|
||||||
PaymentChargeType::Stripe(charge_type) => match charge_type {
|
StripeChargeType::Direct => Some(IntentCharges {
|
||||||
StripeChargeType::Direct => Some(IntentCharges {
|
application_fee_amount: stripe_split_payment.application_fees,
|
||||||
application_fee_amount: stripe_split_payment.application_fees,
|
destination_account_id: None,
|
||||||
destination_account_id: None,
|
}),
|
||||||
}),
|
StripeChargeType::Destination => Some(IntentCharges {
|
||||||
StripeChargeType::Destination => Some(IntentCharges {
|
application_fee_amount: stripe_split_payment.application_fees,
|
||||||
application_fee_amount: stripe_split_payment.application_fees,
|
destination_account_id: Some(
|
||||||
destination_account_id: Some(
|
stripe_split_payment.transfer_account_id.clone(),
|
||||||
stripe_split_payment.transfer_account_id.clone(),
|
),
|
||||||
),
|
}),
|
||||||
}),
|
},
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
Some(common_types::payments::SplitPaymentsRequest::AdyenSplitPayment(_))
|
Some(SplitPaymentsRequest::AdyenSplitPayment(_))
|
||||||
| Some(common_types::payments::SplitPaymentsRequest::XenditSplitPayment(_))
|
| Some(SplitPaymentsRequest::XenditSplitPayment(_))
|
||||||
| None => None,
|
| None => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let charges_in = if charges.is_none() {
|
||||||
|
match charge_type {
|
||||||
|
Some(PaymentChargeType::Stripe(StripeChargeType::Direct)) => Some(IntentCharges {
|
||||||
|
application_fee_amount: application_fees, // default to 0 if None
|
||||||
|
destination_account_id: None,
|
||||||
|
}),
|
||||||
|
Some(PaymentChargeType::Stripe(StripeChargeType::Destination)) => {
|
||||||
|
Some(IntentCharges {
|
||||||
|
application_fee_amount: application_fees,
|
||||||
|
destination_account_id: transfer_account_id,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
charges
|
||||||
|
};
|
||||||
|
|
||||||
let pm = match (payment_method, payment_method_token.clone()) {
|
let pm = match (payment_method, payment_method_token.clone()) {
|
||||||
(Some(method), _) => Some(Secret::new(method)),
|
(Some(method), _) => Some(Secret::new(method)),
|
||||||
(None, Some(token)) => Some(token),
|
(None, Some(token)) => Some(token),
|
||||||
@ -2009,7 +2059,7 @@ impl TryFrom<(&PaymentsAuthorizeRouterData, MinorUnit)> for PaymentIntentRequest
|
|||||||
payment_method_types,
|
payment_method_types,
|
||||||
expand: Some(ExpandableObjects::LatestCharge),
|
expand: Some(ExpandableObjects::LatestCharge),
|
||||||
browser_info,
|
browser_info,
|
||||||
charges,
|
charges: charges_in,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2146,6 +2196,95 @@ impl TryFrom<&ConnectorCustomerRouterData> for CustomerRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub struct StripeSplitPaymentRequest {
|
||||||
|
pub charge_type: Option<PaymentChargeType>,
|
||||||
|
pub application_fees: Option<MinorUnit>,
|
||||||
|
pub transfer_account_id: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<&PaymentsAuthorizeRouterData> for StripeSplitPaymentRequest {
|
||||||
|
type Error = error_stack::Report<ConnectorError>;
|
||||||
|
|
||||||
|
fn try_from(item: &PaymentsAuthorizeRouterData) -> Result<Self, Self::Error> {
|
||||||
|
//extracting mandate metadata from CIT call if CIT call was a Split Payment
|
||||||
|
let from_metadata = item
|
||||||
|
.request
|
||||||
|
.mandate_id
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|mandate_id| mandate_id.mandate_reference_id.as_ref())
|
||||||
|
.and_then(|reference_id| match reference_id {
|
||||||
|
payments::MandateReferenceId::ConnectorMandateId(mandate_data) => {
|
||||||
|
mandate_data.get_mandate_metadata()
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.and_then(|secret_value| {
|
||||||
|
let json_value = secret_value.clone().expose();
|
||||||
|
match serde_json::from_value::<Self>(json_value.clone()) {
|
||||||
|
Ok(val) => Some(val),
|
||||||
|
Err(err) => {
|
||||||
|
router_env::logger::info!(
|
||||||
|
"STRIPE: Picking merchant_account_id and merchant_config_currency from payments request: {:?}", err
|
||||||
|
);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// If the Split Payment Request in MIT mismatches with the metadata from CIT, throw an error
|
||||||
|
if from_metadata.is_some() && item.request.split_payments.is_some() {
|
||||||
|
let mut mit_charge_type = None;
|
||||||
|
let mut mit_application_fees = None;
|
||||||
|
let mut mit_transfer_account_id = None;
|
||||||
|
if let Some(SplitPaymentsRequest::StripeSplitPayment(stripe_split_payment)) =
|
||||||
|
item.request.split_payments.as_ref()
|
||||||
|
{
|
||||||
|
mit_charge_type = Some(stripe_split_payment.charge_type.clone());
|
||||||
|
mit_application_fees = stripe_split_payment.application_fees;
|
||||||
|
mit_transfer_account_id = Some(stripe_split_payment.transfer_account_id.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
if mit_charge_type != from_metadata.as_ref().and_then(|m| m.charge_type.clone())
|
||||||
|
|| mit_application_fees != from_metadata.as_ref().and_then(|m| m.application_fees)
|
||||||
|
|| mit_transfer_account_id
|
||||||
|
!= from_metadata
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|m| m.transfer_account_id.clone())
|
||||||
|
{
|
||||||
|
let mismatched_fields = ["transfer_account_id", "application_fees", "charge_type"];
|
||||||
|
|
||||||
|
let field_str = mismatched_fields.join(", ");
|
||||||
|
return Err(error_stack::Report::from(
|
||||||
|
ConnectorError::MandatePaymentDataMismatch { fields: field_str },
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If Mandate Metadata from CIT call has something, populate it
|
||||||
|
let (charge_type, mut transfer_account_id, application_fees) =
|
||||||
|
if let Some(ref metadata) = from_metadata {
|
||||||
|
(
|
||||||
|
metadata.charge_type.clone(),
|
||||||
|
metadata.transfer_account_id.clone(),
|
||||||
|
metadata.application_fees,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(None, None, None)
|
||||||
|
};
|
||||||
|
|
||||||
|
// If Charge Type is Destination, transfer_account_id need not be appended in headers
|
||||||
|
if charge_type == Some(PaymentChargeType::Stripe(StripeChargeType::Destination)) {
|
||||||
|
transfer_account_id = None;
|
||||||
|
}
|
||||||
|
Ok(Self {
|
||||||
|
charge_type,
|
||||||
|
transfer_account_id,
|
||||||
|
application_fees,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
#[derive(Clone, Default, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
pub enum StripePaymentStatus {
|
pub enum StripePaymentStatus {
|
||||||
@ -2524,10 +2663,23 @@ where
|
|||||||
// For backward compatibility payment_method_id & connector_mandate_id is being populated with the same value
|
// For backward compatibility payment_method_id & connector_mandate_id is being populated with the same value
|
||||||
let connector_mandate_id = Some(payment_method_id.clone().expose());
|
let connector_mandate_id = Some(payment_method_id.clone().expose());
|
||||||
let payment_method_id = Some(payment_method_id.expose());
|
let payment_method_id = Some(payment_method_id.expose());
|
||||||
|
|
||||||
|
let mandate_metadata: Option<Secret<Value>> =
|
||||||
|
match item.data.request.get_split_payment_data() {
|
||||||
|
Some(SplitPaymentsRequest::StripeSplitPayment(stripe_split_data)) => {
|
||||||
|
Some(Secret::new(serde_json::json!({
|
||||||
|
"transfer_account_id": stripe_split_data.transfer_account_id,
|
||||||
|
"charge_type": stripe_split_data.charge_type,
|
||||||
|
"application_fees": stripe_split_data.application_fees,
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
MandateReference {
|
MandateReference {
|
||||||
connector_mandate_id,
|
connector_mandate_id,
|
||||||
payment_method_id,
|
payment_method_id,
|
||||||
mandate_metadata: None,
|
mandate_metadata,
|
||||||
connector_mandate_request_reference_id: None,
|
connector_mandate_request_reference_id: None,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -4252,10 +4404,7 @@ where
|
|||||||
T: SplitPaymentData,
|
T: SplitPaymentData,
|
||||||
{
|
{
|
||||||
let charge_request = request.get_split_payment_data();
|
let charge_request = request.get_split_payment_data();
|
||||||
if let Some(common_types::payments::SplitPaymentsRequest::StripeSplitPayment(
|
if let Some(SplitPaymentsRequest::StripeSplitPayment(stripe_split_payment)) = charge_request {
|
||||||
stripe_split_payment,
|
|
||||||
)) = charge_request
|
|
||||||
{
|
|
||||||
let stripe_charge_response = common_types::payments::StripeChargeResponseData {
|
let stripe_charge_response = common_types::payments::StripeChargeResponseData {
|
||||||
charge_id: Some(charge_id),
|
charge_id: Some(charge_id),
|
||||||
charge_type: stripe_split_payment.charge_type,
|
charge_type: stripe_split_payment.charge_type,
|
||||||
|
|||||||
@ -290,6 +290,8 @@ pub enum ApiErrorResponse {
|
|||||||
InvalidPlatformOperation,
|
InvalidPlatformOperation,
|
||||||
#[error(error_type = ErrorType::InvalidRequestError, code = "IR_45", message = "External vault failed during processing with connector")]
|
#[error(error_type = ErrorType::InvalidRequestError, code = "IR_45", message = "External vault failed during processing with connector")]
|
||||||
ExternalVaultFailed,
|
ExternalVaultFailed,
|
||||||
|
#[error(error_type = ErrorType::InvalidRequestError, code = "IR_46", message = "Field {fields} doesn't match with the ones used during mandate creation")]
|
||||||
|
MandatePaymentDataMismatch { fields: String },
|
||||||
#[error(error_type = ErrorType::InvalidRequestError, code = "WE_01", message = "Failed to authenticate the webhook")]
|
#[error(error_type = ErrorType::InvalidRequestError, code = "WE_01", message = "Failed to authenticate the webhook")]
|
||||||
WebhookAuthenticationFailed,
|
WebhookAuthenticationFailed,
|
||||||
#[error(error_type = ErrorType::InvalidRequestError, code = "WE_02", message = "Bad request received in webhook")]
|
#[error(error_type = ErrorType::InvalidRequestError, code = "WE_02", message = "Bad request received in webhook")]
|
||||||
@ -651,6 +653,9 @@ impl ErrorSwitch<api_models::errors::types::ApiErrorResponse> for ApiErrorRespon
|
|||||||
Self::ExternalVaultFailed => {
|
Self::ExternalVaultFailed => {
|
||||||
AER::BadRequest(ApiError::new("IR", 45, "External Vault failed while processing with connector.", None))
|
AER::BadRequest(ApiError::new("IR", 45, "External Vault failed while processing with connector.", None))
|
||||||
},
|
},
|
||||||
|
Self::MandatePaymentDataMismatch { fields} => {
|
||||||
|
AER::BadRequest(ApiError::new("IR", 46, format!("Field {fields} doesn't match with the ones used during mandate creation"), Some(Extra {fields: Some(fields.to_owned()), ..Default::default()}))) //FIXME: error message
|
||||||
|
}
|
||||||
|
|
||||||
Self::WebhookAuthenticationFailed => {
|
Self::WebhookAuthenticationFailed => {
|
||||||
AER::Unauthorized(ApiError::new("WE", 1, "Webhook authentication failed", None))
|
AER::Unauthorized(ApiError::new("WE", 1, "Webhook authentication failed", None))
|
||||||
|
|||||||
@ -125,6 +125,8 @@ pub enum ConnectorError {
|
|||||||
error_message: String,
|
error_message: String,
|
||||||
error_object: serde_json::Value,
|
error_object: serde_json::Value,
|
||||||
},
|
},
|
||||||
|
#[error("Field {fields} doesn't match with the ones used during mandate creation")]
|
||||||
|
MandatePaymentDataMismatch { fields: String },
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConnectorError {
|
impl ConnectorError {
|
||||||
|
|||||||
@ -600,6 +600,7 @@ impl From<errors::ApiErrorResponse> for StripeErrorCode {
|
|||||||
errors::ApiErrorResponse::AddressNotFound => Self::AddressNotFound,
|
errors::ApiErrorResponse::AddressNotFound => Self::AddressNotFound,
|
||||||
errors::ApiErrorResponse::NotImplemented { .. } => Self::Unauthorized,
|
errors::ApiErrorResponse::NotImplemented { .. } => Self::Unauthorized,
|
||||||
errors::ApiErrorResponse::FlowNotSupported { .. } => Self::InternalServerError,
|
errors::ApiErrorResponse::FlowNotSupported { .. } => Self::InternalServerError,
|
||||||
|
errors::ApiErrorResponse::MandatePaymentDataMismatch { .. } => Self::PlatformBadRequest,
|
||||||
errors::ApiErrorResponse::PaymentUnexpectedState {
|
errors::ApiErrorResponse::PaymentUnexpectedState {
|
||||||
current_flow,
|
current_flow,
|
||||||
field_name,
|
field_name,
|
||||||
|
|||||||
@ -176,6 +176,7 @@ impl<T> ConnectorErrorExt<T> for error_stack::Result<T, errors::ConnectorError>
|
|||||||
| errors::ConnectorError::DateFormattingFailed
|
| errors::ConnectorError::DateFormattingFailed
|
||||||
| errors::ConnectorError::InvalidDataFormat { .. }
|
| errors::ConnectorError::InvalidDataFormat { .. }
|
||||||
| errors::ConnectorError::MismatchedPaymentData
|
| errors::ConnectorError::MismatchedPaymentData
|
||||||
|
| errors::ConnectorError::MandatePaymentDataMismatch { .. }
|
||||||
| errors::ConnectorError::InvalidWalletToken { .. }
|
| errors::ConnectorError::InvalidWalletToken { .. }
|
||||||
| errors::ConnectorError::MissingConnectorRelatedTransactionID { .. }
|
| errors::ConnectorError::MissingConnectorRelatedTransactionID { .. }
|
||||||
| errors::ConnectorError::FileValidationFailed { .. }
|
| errors::ConnectorError::FileValidationFailed { .. }
|
||||||
@ -230,6 +231,11 @@ impl<T> ConnectorErrorExt<T> for error_stack::Result<T, errors::ConnectorError>
|
|||||||
"payment_method_data, payment_method_type and payment_experience does not match",
|
"payment_method_data, payment_method_type and payment_experience does not match",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
errors::ConnectorError::MandatePaymentDataMismatch {fields}=> {
|
||||||
|
errors::ApiErrorResponse::MandatePaymentDataMismatch {
|
||||||
|
fields: fields.to_owned(),
|
||||||
|
}
|
||||||
|
},
|
||||||
errors::ConnectorError::NotSupported { message, connector } => {
|
errors::ConnectorError::NotSupported { message, connector } => {
|
||||||
errors::ApiErrorResponse::NotSupported { message: format!("{message} is not supported by {connector}") }
|
errors::ApiErrorResponse::NotSupported { message: format!("{message} is not supported by {connector}") }
|
||||||
},
|
},
|
||||||
@ -376,6 +382,7 @@ impl<T> ConnectorErrorExt<T> for error_stack::Result<T, errors::ConnectorError>
|
|||||||
| errors::ConnectorError::DateFormattingFailed
|
| errors::ConnectorError::DateFormattingFailed
|
||||||
| errors::ConnectorError::InvalidDataFormat { .. }
|
| errors::ConnectorError::InvalidDataFormat { .. }
|
||||||
| errors::ConnectorError::MismatchedPaymentData
|
| errors::ConnectorError::MismatchedPaymentData
|
||||||
|
| errors::ConnectorError::MandatePaymentDataMismatch { .. }
|
||||||
| errors::ConnectorError::MissingConnectorRelatedTransactionID { .. }
|
| errors::ConnectorError::MissingConnectorRelatedTransactionID { .. }
|
||||||
| errors::ConnectorError::FileValidationFailed { .. }
|
| errors::ConnectorError::FileValidationFailed { .. }
|
||||||
| errors::ConnectorError::MissingConnectorRedirectionPayload { .. }
|
| errors::ConnectorError::MissingConnectorRedirectionPayload { .. }
|
||||||
|
|||||||
@ -7017,14 +7017,24 @@ pub fn validate_platform_request_for_marketplace(
|
|||||||
stripe_split_payment,
|
stripe_split_payment,
|
||||||
)) => match amount {
|
)) => match amount {
|
||||||
api::Amount::Zero => {
|
api::Amount::Zero => {
|
||||||
if stripe_split_payment.application_fees.get_amount_as_i64() != 0 {
|
if stripe_split_payment
|
||||||
|
.application_fees
|
||||||
|
.as_ref()
|
||||||
|
.map_or(MinorUnit::zero(), |amount| *amount)
|
||||||
|
!= MinorUnit::zero()
|
||||||
|
{
|
||||||
return Err(errors::ApiErrorResponse::InvalidDataValue {
|
return Err(errors::ApiErrorResponse::InvalidDataValue {
|
||||||
field_name: "split_payments.stripe_split_payment.application_fees",
|
field_name: "split_payments.stripe_split_payment.application_fees",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
api::Amount::Value(amount) => {
|
api::Amount::Value(amount) => {
|
||||||
if stripe_split_payment.application_fees.get_amount_as_i64() > amount.into() {
|
if stripe_split_payment
|
||||||
|
.application_fees
|
||||||
|
.as_ref()
|
||||||
|
.map_or(MinorUnit::zero(), |amount| *amount)
|
||||||
|
> amount.into()
|
||||||
|
{
|
||||||
return Err(errors::ApiErrorResponse::InvalidDataValue {
|
return Err(errors::ApiErrorResponse::InvalidDataValue {
|
||||||
field_name: "split_payments.stripe_split_payment.application_fees",
|
field_name: "split_payments.stripe_split_payment.application_fees",
|
||||||
});
|
});
|
||||||
|
|||||||
@ -193,6 +193,8 @@ pub enum ConnectorError {
|
|||||||
InvalidDataFormat { field_name: &'static str },
|
InvalidDataFormat { field_name: &'static str },
|
||||||
#[error("Payment Method data / Payment Method Type / Payment Experience Mismatch ")]
|
#[error("Payment Method data / Payment Method Type / Payment Experience Mismatch ")]
|
||||||
MismatchedPaymentData,
|
MismatchedPaymentData,
|
||||||
|
#[error("Field {fields} doesn't match with the ones used during mandate creation")]
|
||||||
|
MandatePaymentDataMismatch { fields: String },
|
||||||
#[error("Failed to parse Wallet token")]
|
#[error("Failed to parse Wallet token")]
|
||||||
InvalidWalletToken { wallet_name: String },
|
InvalidWalletToken { wallet_name: String },
|
||||||
#[error("Missing Connector Related Transaction ID")]
|
#[error("Missing Connector Related Transaction ID")]
|
||||||
|
|||||||
Reference in New Issue
Block a user