mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-28 04:04:55 +08:00
feat(connector): [ADYENPLATFORM] add card payouts (#8504)
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
@ -1,6 +1,4 @@
|
|||||||
use api_models::payouts;
|
use api_models::{payouts, webhooks};
|
||||||
#[cfg(feature = "payouts")]
|
|
||||||
use api_models::webhooks;
|
|
||||||
use common_enums::enums;
|
use common_enums::enums;
|
||||||
use common_utils::pii;
|
use common_utils::pii;
|
||||||
use error_stack::{report, ResultExt};
|
use error_stack::{report, ResultExt};
|
||||||
@ -13,7 +11,7 @@ use super::{AdyenPlatformRouterData, Error};
|
|||||||
use crate::{
|
use crate::{
|
||||||
connectors::adyen::transformers as adyen,
|
connectors::adyen::transformers as adyen,
|
||||||
types::PayoutsResponseRouterData,
|
types::PayoutsResponseRouterData,
|
||||||
utils::{self, PayoutsData as _, RouterData as _},
|
utils::{self, AddressDetailsData, PayoutsData as _, RouterData as _},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Default, Serialize, Deserialize)]
|
#[derive(Debug, Default, Serialize, Deserialize)]
|
||||||
@ -38,7 +36,7 @@ pub struct AdyenTransferRequest {
|
|||||||
balance_account_id: Secret<String>,
|
balance_account_id: Secret<String>,
|
||||||
category: AdyenPayoutMethod,
|
category: AdyenPayoutMethod,
|
||||||
counterparty: AdyenPayoutMethodDetails,
|
counterparty: AdyenPayoutMethodDetails,
|
||||||
priority: AdyenPayoutPriority,
|
priority: Option<AdyenPayoutPriority>,
|
||||||
reference: String,
|
reference: String,
|
||||||
reference_for_beneficiary: String,
|
reference_for_beneficiary: String,
|
||||||
description: Option<String>,
|
description: Option<String>,
|
||||||
@ -48,32 +46,50 @@ pub struct AdyenTransferRequest {
|
|||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub enum AdyenPayoutMethod {
|
pub enum AdyenPayoutMethod {
|
||||||
Bank,
|
Bank,
|
||||||
|
Card,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct AdyenPayoutMethodDetails {
|
pub enum AdyenPayoutMethodDetails {
|
||||||
bank_account: AdyenBankAccountDetails,
|
BankAccount(AdyenBankAccountDetails),
|
||||||
|
Card(AdyenCardDetails),
|
||||||
|
#[serde(rename = "card")]
|
||||||
|
CardToken(AdyenCardTokenDetails),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct AdyenBankAccountDetails {
|
pub struct AdyenBankAccountDetails {
|
||||||
account_holder: AdyenBankAccountHolder,
|
account_holder: AdyenAccountHolder,
|
||||||
account_identification: AdyenBankAccountIdentification,
|
account_identification: AdyenBankAccountIdentification,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct AdyenBankAccountHolder {
|
pub struct AdyenAccountHolder {
|
||||||
address: Option<adyen::Address>,
|
address: AdyenAddress,
|
||||||
full_name: Secret<String>,
|
first_name: Option<Secret<String>>,
|
||||||
|
last_name: Option<Secret<String>>,
|
||||||
|
full_name: Option<Secret<String>>,
|
||||||
#[serde(rename = "reference")]
|
#[serde(rename = "reference")]
|
||||||
customer_id: Option<String>,
|
customer_id: Option<String>,
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
entity_type: Option<EntityType>,
|
entity_type: Option<EntityType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[serde_with::skip_serializing_none]
|
||||||
|
#[derive(Default, Debug, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct AdyenAddress {
|
||||||
|
line1: Secret<String>,
|
||||||
|
line2: Secret<String>,
|
||||||
|
postal_code: Option<Secret<String>>,
|
||||||
|
state_or_province: Option<Secret<String>>,
|
||||||
|
city: String,
|
||||||
|
country: enums::CountryAlpha2,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct AdyenBankAccountIdentification {
|
pub struct AdyenBankAccountIdentification {
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
@ -93,6 +109,38 @@ pub struct SepaDetails {
|
|||||||
iban: Secret<String>,
|
iban: Secret<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct AdyenCardDetails {
|
||||||
|
card_holder: AdyenAccountHolder,
|
||||||
|
card_identification: AdyenCardIdentification,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct AdyenCardIdentification {
|
||||||
|
#[serde(rename = "number")]
|
||||||
|
card_number: cards::CardNumber,
|
||||||
|
expiry_month: Secret<String>,
|
||||||
|
expiry_year: Secret<String>,
|
||||||
|
issue_number: Option<String>,
|
||||||
|
start_month: Option<String>,
|
||||||
|
start_year: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct AdyenCardTokenDetails {
|
||||||
|
card_holder: AdyenAccountHolder,
|
||||||
|
card_identification: AdyenCardTokenIdentification,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct AdyenCardTokenIdentification {
|
||||||
|
stored_payment_method_id: Secret<String>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub enum AdyenPayoutPriority {
|
pub enum AdyenPayoutPriority {
|
||||||
@ -120,7 +168,7 @@ pub struct AdyenTransferResponse {
|
|||||||
amount: adyen::Amount,
|
amount: adyen::Amount,
|
||||||
balance_account: AdyenBalanceAccount,
|
balance_account: AdyenBalanceAccount,
|
||||||
category: AdyenPayoutMethod,
|
category: AdyenPayoutMethod,
|
||||||
category_data: AdyenCategoryData,
|
category_data: Option<AdyenCategoryData>,
|
||||||
direction: AdyenTransactionDirection,
|
direction: AdyenTransactionDirection,
|
||||||
reference: String,
|
reference: String,
|
||||||
reference_for_beneficiary: String,
|
reference_for_beneficiary: String,
|
||||||
@ -168,25 +216,101 @@ pub enum AdyenTransferStatus {
|
|||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub enum AdyenTransactionType {
|
pub enum AdyenTransactionType {
|
||||||
BankTransfer,
|
BankTransfer,
|
||||||
|
CardTransfer,
|
||||||
InternalTransfer,
|
InternalTransfer,
|
||||||
Payment,
|
Payment,
|
||||||
Refund,
|
Refund,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TryFrom<&hyperswitch_domain_models::address::AddressDetails> for AdyenAddress {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn try_from(
|
||||||
|
address: &hyperswitch_domain_models::address::AddressDetails,
|
||||||
|
) -> Result<Self, Self::Error> {
|
||||||
|
let line1 = address
|
||||||
|
.get_line1()
|
||||||
|
.change_context(ConnectorError::MissingRequiredField {
|
||||||
|
field_name: "billing.address.line1",
|
||||||
|
})?
|
||||||
|
.clone();
|
||||||
|
let line2 = address
|
||||||
|
.get_line2()
|
||||||
|
.change_context(ConnectorError::MissingRequiredField {
|
||||||
|
field_name: "billing.address.line2",
|
||||||
|
})?
|
||||||
|
.clone();
|
||||||
|
Ok(Self {
|
||||||
|
line1,
|
||||||
|
line2,
|
||||||
|
postal_code: address.get_optional_zip(),
|
||||||
|
state_or_province: address.get_optional_state(),
|
||||||
|
city: address.get_city()?.to_owned(),
|
||||||
|
country: address.get_country()?.to_owned(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F> TryFrom<(&types::PayoutsRouterData<F>, enums::PayoutType)> for AdyenAccountHolder {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn try_from(
|
||||||
|
(router_data, payout_type): (&types::PayoutsRouterData<F>, enums::PayoutType),
|
||||||
|
) -> Result<Self, Self::Error> {
|
||||||
|
let billing_address = router_data.get_billing_address()?;
|
||||||
|
let (first_name, last_name, full_name) = match payout_type {
|
||||||
|
enums::PayoutType::Card => (
|
||||||
|
Some(router_data.get_billing_first_name()?),
|
||||||
|
Some(router_data.get_billing_last_name()?),
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
enums::PayoutType::Bank => (None, None, Some(router_data.get_billing_full_name()?)),
|
||||||
|
_ => Err(ConnectorError::NotSupported {
|
||||||
|
message: "Payout method not supported".to_string(),
|
||||||
|
connector: "Adyen",
|
||||||
|
})?,
|
||||||
|
};
|
||||||
|
Ok(Self {
|
||||||
|
address: billing_address.try_into()?,
|
||||||
|
first_name,
|
||||||
|
last_name,
|
||||||
|
full_name,
|
||||||
|
customer_id: Some(router_data.get_customer_id()?.get_string_repr().to_owned()),
|
||||||
|
entity_type: Some(EntityType::from(router_data.request.entity_type)),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<F> TryFrom<&AdyenPlatformRouterData<&types::PayoutsRouterData<F>>> for AdyenTransferRequest {
|
impl<F> TryFrom<&AdyenPlatformRouterData<&types::PayoutsRouterData<F>>> for AdyenTransferRequest {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
fn try_from(
|
fn try_from(
|
||||||
item: &AdyenPlatformRouterData<&types::PayoutsRouterData<F>>,
|
item: &AdyenPlatformRouterData<&types::PayoutsRouterData<F>>,
|
||||||
) -> Result<Self, Self::Error> {
|
) -> Result<Self, Self::Error> {
|
||||||
let request = item.router_data.request.to_owned();
|
let request = &item.router_data.request;
|
||||||
match item.router_data.get_payout_method_data()? {
|
let (counterparty, priority) = match item.router_data.get_payout_method_data()? {
|
||||||
payouts::PayoutMethodData::Card(_) | payouts::PayoutMethodData::Wallet(_) => {
|
payouts::PayoutMethodData::Wallet(_) => Err(ConnectorError::NotImplemented(
|
||||||
Err(ConnectorError::NotImplemented(
|
utils::get_unimplemented_payment_method_error_message("Adyenplatform"),
|
||||||
utils::get_unimplemented_payment_method_error_message("Adyenplatform"),
|
))?,
|
||||||
))?
|
payouts::PayoutMethodData::Card(c) => {
|
||||||
|
let card_holder: AdyenAccountHolder =
|
||||||
|
(item.router_data, enums::PayoutType::Card).try_into()?;
|
||||||
|
let card_identification = AdyenCardIdentification {
|
||||||
|
card_number: c.card_number,
|
||||||
|
expiry_month: c.expiry_month,
|
||||||
|
expiry_year: c.expiry_year,
|
||||||
|
issue_number: None,
|
||||||
|
start_month: None,
|
||||||
|
start_year: None,
|
||||||
|
};
|
||||||
|
let counterparty = AdyenPayoutMethodDetails::Card(AdyenCardDetails {
|
||||||
|
card_holder,
|
||||||
|
card_identification,
|
||||||
|
});
|
||||||
|
(counterparty, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
payouts::PayoutMethodData::Bank(bd) => {
|
payouts::PayoutMethodData::Bank(bd) => {
|
||||||
|
let account_holder: AdyenAccountHolder =
|
||||||
|
(item.router_data, enums::PayoutType::Bank).try_into()?;
|
||||||
let bank_details = match bd {
|
let bank_details = match bd {
|
||||||
payouts::Bank::Sepa(b) => AdyenBankAccountIdentification {
|
payouts::Bank::Sepa(b) => AdyenBankAccountIdentification {
|
||||||
bank_type: "iban".to_string(),
|
bank_type: "iban".to_string(),
|
||||||
@ -207,56 +331,39 @@ impl<F> TryFrom<&AdyenPlatformRouterData<&types::PayoutsRouterData<F>>> for Adye
|
|||||||
connector: "Adyenplatform",
|
connector: "Adyenplatform",
|
||||||
})?,
|
})?,
|
||||||
};
|
};
|
||||||
let billing_address = item.router_data.get_optional_billing();
|
let counterparty = AdyenPayoutMethodDetails::BankAccount(AdyenBankAccountDetails {
|
||||||
let address = adyen::get_address_info(billing_address).transpose()?;
|
account_holder,
|
||||||
let account_holder = AdyenBankAccountHolder {
|
account_identification: bank_details,
|
||||||
address,
|
});
|
||||||
full_name: item.router_data.get_billing_full_name()?,
|
|
||||||
customer_id: Some(
|
|
||||||
item.router_data
|
|
||||||
.get_customer_id()?
|
|
||||||
.get_string_repr()
|
|
||||||
.to_owned(),
|
|
||||||
),
|
|
||||||
entity_type: Some(EntityType::from(request.entity_type)),
|
|
||||||
};
|
|
||||||
let counterparty = AdyenPayoutMethodDetails {
|
|
||||||
bank_account: AdyenBankAccountDetails {
|
|
||||||
account_holder,
|
|
||||||
account_identification: bank_details,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let adyen_connector_metadata_object =
|
|
||||||
AdyenPlatformConnectorMetadataObject::try_from(
|
|
||||||
&item.router_data.connector_meta_data,
|
|
||||||
)?;
|
|
||||||
let balance_account_id = adyen_connector_metadata_object
|
|
||||||
.source_balance_account
|
|
||||||
.ok_or(ConnectorError::InvalidConnectorConfig {
|
|
||||||
config: "metadata.source_balance_account",
|
|
||||||
})?;
|
|
||||||
let priority = request
|
let priority = request
|
||||||
.priority
|
.priority
|
||||||
.ok_or(ConnectorError::MissingRequiredField {
|
.ok_or(ConnectorError::MissingRequiredField {
|
||||||
field_name: "priority",
|
field_name: "priority",
|
||||||
})?;
|
})?;
|
||||||
let payout_type = request.get_payout_type()?;
|
(counterparty, Some(AdyenPayoutPriority::from(priority)))
|
||||||
Ok(Self {
|
|
||||||
amount: adyen::Amount {
|
|
||||||
value: item.amount,
|
|
||||||
currency: request.destination_currency,
|
|
||||||
},
|
|
||||||
balance_account_id,
|
|
||||||
category: AdyenPayoutMethod::try_from(payout_type)?,
|
|
||||||
counterparty,
|
|
||||||
priority: AdyenPayoutPriority::from(priority),
|
|
||||||
reference: item.router_data.connector_request_reference_id.clone(),
|
|
||||||
reference_for_beneficiary: request.payout_id,
|
|
||||||
description: item.router_data.description.clone(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
let adyen_connector_metadata_object =
|
||||||
|
AdyenPlatformConnectorMetadataObject::try_from(&item.router_data.connector_meta_data)?;
|
||||||
|
let balance_account_id = adyen_connector_metadata_object
|
||||||
|
.source_balance_account
|
||||||
|
.ok_or(ConnectorError::InvalidConnectorConfig {
|
||||||
|
config: "metadata.source_balance_account",
|
||||||
|
})?;
|
||||||
|
let payout_type = request.get_payout_type()?;
|
||||||
|
Ok(Self {
|
||||||
|
amount: adyen::Amount {
|
||||||
|
value: item.amount,
|
||||||
|
currency: request.destination_currency,
|
||||||
|
},
|
||||||
|
balance_account_id,
|
||||||
|
category: AdyenPayoutMethod::try_from(payout_type)?,
|
||||||
|
counterparty,
|
||||||
|
priority,
|
||||||
|
reference: item.router_data.connector_request_reference_id.clone(),
|
||||||
|
reference_for_beneficiary: request.payout_id.clone(),
|
||||||
|
description: item.router_data.description.clone(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -332,17 +439,15 @@ impl TryFrom<enums::PayoutType> for AdyenPayoutMethod {
|
|||||||
fn try_from(payout_type: enums::PayoutType) -> Result<Self, Self::Error> {
|
fn try_from(payout_type: enums::PayoutType) -> Result<Self, Self::Error> {
|
||||||
match payout_type {
|
match payout_type {
|
||||||
enums::PayoutType::Bank => Ok(Self::Bank),
|
enums::PayoutType::Bank => Ok(Self::Bank),
|
||||||
enums::PayoutType::Card | enums::PayoutType::Wallet => {
|
enums::PayoutType::Card => Ok(Self::Card),
|
||||||
Err(report!(ConnectorError::NotSupported {
|
enums::PayoutType::Wallet => Err(report!(ConnectorError::NotSupported {
|
||||||
message: "Card or wallet payouts".to_string(),
|
message: "Card or wallet payouts".to_string(),
|
||||||
connector: "Adyenplatform",
|
connector: "Adyenplatform",
|
||||||
}))
|
})),
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "payouts")]
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct AdyenplatformIncomingWebhook {
|
pub struct AdyenplatformIncomingWebhook {
|
||||||
@ -351,7 +456,6 @@ pub struct AdyenplatformIncomingWebhook {
|
|||||||
pub webhook_type: AdyenplatformWebhookEventType,
|
pub webhook_type: AdyenplatformWebhookEventType,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "payouts")]
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct AdyenplatformIncomingWebhookData {
|
pub struct AdyenplatformIncomingWebhookData {
|
||||||
@ -360,7 +464,6 @@ pub struct AdyenplatformIncomingWebhookData {
|
|||||||
pub tracking: Option<AdyenplatformInstantStatus>,
|
pub tracking: Option<AdyenplatformInstantStatus>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "payouts")]
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct AdyenplatformInstantStatus {
|
pub struct AdyenplatformInstantStatus {
|
||||||
@ -368,7 +471,6 @@ pub struct AdyenplatformInstantStatus {
|
|||||||
estimated_arrival_time: Option<String>,
|
estimated_arrival_time: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "payouts")]
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub enum InstantPriorityStatus {
|
pub enum InstantPriorityStatus {
|
||||||
@ -376,7 +478,6 @@ pub enum InstantPriorityStatus {
|
|||||||
Credited,
|
Credited,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "payouts")]
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub enum AdyenplatformWebhookEventType {
|
pub enum AdyenplatformWebhookEventType {
|
||||||
#[serde(rename = "balancePlatform.transfer.created")]
|
#[serde(rename = "balancePlatform.transfer.created")]
|
||||||
@ -385,7 +486,6 @@ pub enum AdyenplatformWebhookEventType {
|
|||||||
PayoutUpdated,
|
PayoutUpdated,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "payouts")]
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub enum AdyenplatformWebhookStatus {
|
pub enum AdyenplatformWebhookStatus {
|
||||||
@ -396,7 +496,6 @@ pub enum AdyenplatformWebhookStatus {
|
|||||||
Returned,
|
Returned,
|
||||||
Received,
|
Received,
|
||||||
}
|
}
|
||||||
#[cfg(feature = "payouts")]
|
|
||||||
pub fn get_adyen_webhook_event(
|
pub fn get_adyen_webhook_event(
|
||||||
event_type: AdyenplatformWebhookEventType,
|
event_type: AdyenplatformWebhookEventType,
|
||||||
status: AdyenplatformWebhookStatus,
|
status: AdyenplatformWebhookStatus,
|
||||||
@ -434,4 +533,13 @@ pub struct AdyenTransferErrorResponse {
|
|||||||
pub title: String,
|
pub title: String,
|
||||||
pub detail: Option<String>,
|
pub detail: Option<String>,
|
||||||
pub request_id: Option<String>,
|
pub request_id: Option<String>,
|
||||||
|
pub invalid_fields: Option<Vec<AdyenInvalidField>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct AdyenInvalidField {
|
||||||
|
pub name: Option<String>,
|
||||||
|
pub value: Option<String>,
|
||||||
|
pub message: Option<String>,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -437,15 +437,6 @@ fn get_billing_details(connector: PayoutConnectors) -> HashMap<String, RequiredF
|
|||||||
value: None,
|
value: None,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
(
|
|
||||||
"billing.address.zip".to_string(),
|
|
||||||
RequiredFieldInfo {
|
|
||||||
required_field: "billing.address.zip".to_string(),
|
|
||||||
display_name: "billing_address_zip".to_string(),
|
|
||||||
field_type: FieldType::Text,
|
|
||||||
value: None,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
(
|
(
|
||||||
"billing.address.country".to_string(),
|
"billing.address.country".to_string(),
|
||||||
RequiredFieldInfo {
|
RequiredFieldInfo {
|
||||||
@ -469,6 +460,15 @@ fn get_billing_details(connector: PayoutConnectors) -> HashMap<String, RequiredF
|
|||||||
value: None,
|
value: None,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"billing.address.last_name".to_string(),
|
||||||
|
RequiredFieldInfo {
|
||||||
|
required_field: "billing.address.last_name".to_string(),
|
||||||
|
display_name: "billing_address_last_name".to_string(),
|
||||||
|
field_type: FieldType::Text,
|
||||||
|
value: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
]),
|
]),
|
||||||
PayoutConnectors::Wise => HashMap::from([
|
PayoutConnectors::Wise => HashMap::from([
|
||||||
(
|
(
|
||||||
|
|||||||
Reference in New Issue
Block a user