feat(connector): [Adyen] Add pix support for adyen (#1703)

Co-authored-by: Abhishek Marrivagu <68317979+Abhicodes-crypto@users.noreply.github.com>
This commit is contained in:
Sangamesh Kulkarni
2023-07-25 19:40:45 +05:30
committed by GitHub
parent 1f8e790b14
commit 33a1368e8a
10 changed files with 280 additions and 181 deletions

View File

@ -952,6 +952,7 @@ pub enum BankTransferData {
/// The billing details for Multibanco /// The billing details for Multibanco
billing_details: MultibancoBillingDetails, billing_details: MultibancoBillingDetails,
}, },
Pix {},
} }
#[derive(serde::Deserialize, serde::Serialize, Debug, Clone, ToSchema, Eq, PartialEq)] #[derive(serde::Deserialize, serde::Serialize, Debug, Clone, ToSchema, Eq, PartialEq)]
@ -1331,8 +1332,12 @@ pub enum NextActionData {
ThirdPartySdkSessionToken { session_token: Option<SessionToken> }, ThirdPartySdkSessionToken { session_token: Option<SessionToken> },
/// Contains url for Qr code image, this qr code has to be shown in sdk /// Contains url for Qr code image, this qr code has to be shown in sdk
QrCodeInformation { QrCodeInformation {
/// Hyperswitch generated image data source url
#[schema(value_type = String)] #[schema(value_type = String)]
image_data_url: Url, image_data_url: Option<Url>,
/// The url for Qr code given by the connector
#[schema(value_type = String)]
qr_code_url: Option<Url>,
}, },
} }
@ -1347,7 +1352,10 @@ pub struct BankTransferNextStepsData {
#[derive(Clone, Debug, serde::Deserialize)] #[derive(Clone, Debug, serde::Deserialize)]
pub struct QrCodeNextStepsInstruction { pub struct QrCodeNextStepsInstruction {
pub image_data_url: Url, /// Hyperswitch generated image data source url
pub image_data_url: Option<Url>,
/// The url for Qr code given by the connector
pub qr_code_url: Option<Url>,
} }
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)] #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]

View File

@ -813,6 +813,7 @@ pub enum PaymentMethodType {
OnlineBankingSlovakia, OnlineBankingSlovakia,
PayBright, PayBright,
Paypal, Paypal,
Pix,
Przelewy24, Przelewy24,
SamsungPay, SamsungPay,
Sepa, Sepa,

View File

@ -1572,6 +1572,7 @@ impl From<PaymentMethodType> for PaymentMethod {
PaymentMethodType::OnlineBankingThailand => Self::BankRedirect, PaymentMethodType::OnlineBankingThailand => Self::BankRedirect,
PaymentMethodType::OnlineBankingPoland => Self::BankRedirect, PaymentMethodType::OnlineBankingPoland => Self::BankRedirect,
PaymentMethodType::OnlineBankingSlovakia => Self::BankRedirect, PaymentMethodType::OnlineBankingSlovakia => Self::BankRedirect,
PaymentMethodType::Pix => Self::BankTransfer,
PaymentMethodType::PayBright => Self::PayLater, PaymentMethodType::PayBright => Self::PayLater,
PaymentMethodType::Paypal => Self::Wallet, PaymentMethodType::Paypal => Self::Wallet,
PaymentMethodType::Przelewy24 => Self::BankRedirect, PaymentMethodType::Przelewy24 => Self::BankRedirect,

View File

@ -768,7 +768,10 @@ pub enum StripeNextAction {
session_token: Option<payments::SessionToken>, session_token: Option<payments::SessionToken>,
}, },
QrCodeInformation { QrCodeInformation {
image_data_url: url::Url, /// Hyperswitch generated image data source url
image_data_url: Option<url::Url>,
/// The url for Qr code given by the connector
qr_code_url: Option<url::Url>,
}, },
} }
@ -793,9 +796,13 @@ pub(crate) fn into_stripe_next_action(
payments::NextActionData::ThirdPartySdkSessionToken { session_token } => { payments::NextActionData::ThirdPartySdkSessionToken { session_token } => {
StripeNextAction::ThirdPartySdkSessionToken { session_token } StripeNextAction::ThirdPartySdkSessionToken { session_token }
} }
payments::NextActionData::QrCodeInformation { image_data_url } => { payments::NextActionData::QrCodeInformation {
StripeNextAction::QrCodeInformation { image_data_url } image_data_url,
} qr_code_url,
} => StripeNextAction::QrCodeInformation {
image_data_url,
qr_code_url,
},
}) })
} }

View File

@ -369,7 +369,10 @@ pub enum StripeNextAction {
session_token: Option<payments::SessionToken>, session_token: Option<payments::SessionToken>,
}, },
QrCodeInformation { QrCodeInformation {
image_data_url: url::Url, /// Hyperswitch generated image data source url
image_data_url: Option<url::Url>,
/// The url for Qr code given by the connector
qr_code_url: Option<url::Url>,
}, },
} }
@ -394,9 +397,13 @@ pub(crate) fn into_stripe_next_action(
payments::NextActionData::ThirdPartySdkSessionToken { session_token } => { payments::NextActionData::ThirdPartySdkSessionToken { session_token } => {
StripeNextAction::ThirdPartySdkSessionToken { session_token } StripeNextAction::ThirdPartySdkSessionToken { session_token }
} }
payments::NextActionData::QrCodeInformation { image_data_url } => { payments::NextActionData::QrCodeInformation {
StripeNextAction::QrCodeInformation { image_data_url } image_data_url,
} qr_code_url,
} => StripeNextAction::QrCodeInformation {
image_data_url,
qr_code_url,
},
}) })
} }

View File

@ -2,6 +2,7 @@
use api_models::payouts::PayoutMethodData; use api_models::payouts::PayoutMethodData;
use api_models::{enums, payments, webhooks}; use api_models::{enums, payments, webhooks};
use cards::CardNumber; use cards::CardNumber;
use error_stack::ResultExt;
use masking::PeekInterface; use masking::PeekInterface;
use reqwest::Url; use reqwest::Url;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -27,6 +28,7 @@ use crate::{
transformers::ForeignFrom, transformers::ForeignFrom,
PaymentsAuthorizeData, PaymentsAuthorizeData,
}, },
utils as crate_utils,
}; };
type Error = error_stack::Report<errors::ConnectorError>; type Error = error_stack::Report<errors::ConnectorError>;
@ -234,7 +236,7 @@ pub struct AdyenThreeDS {
#[serde(untagged)] #[serde(untagged)]
pub enum AdyenPaymentResponse { pub enum AdyenPaymentResponse {
Response(Response), Response(Response),
RedirectResponse(RedirectionResponse), AdyenNextActionResponse(AdyenNextActionResponse),
RedirectionErrorResponse(RedirectionErrorResponse), RedirectionErrorResponse(RedirectionErrorResponse),
} }
@ -259,16 +261,16 @@ pub struct RedirectionErrorResponse {
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct RedirectionResponse { pub struct AdyenNextActionResponse {
result_code: AdyenStatus, result_code: AdyenStatus,
action: AdyenRedirectionAction, action: AdyenNextAction,
refusal_reason: Option<String>, refusal_reason: Option<String>,
refusal_reason_code: Option<String>, refusal_reason_code: Option<String>,
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct AdyenRedirectionAction { pub struct AdyenNextAction {
payment_method_type: String, payment_method_type: String,
url: Option<Url>, url: Option<Url>,
method: Option<services::Method>, method: Option<services::Method>,
@ -276,6 +278,7 @@ pub struct AdyenRedirectionAction {
type_of_response: ActionType, type_of_response: ActionType,
data: Option<std::collections::HashMap<String, String>>, data: Option<std::collections::HashMap<String, String>>,
payment_data: Option<String>, payment_data: Option<String>,
qr_code_data: Option<String>,
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
@ -283,6 +286,8 @@ pub struct AdyenRedirectionAction {
pub enum ActionType { pub enum ActionType {
Redirect, Redirect,
Await, Await,
#[serde(rename = "qrCode")]
QrCode,
} }
#[derive(Default, Debug, Clone, Serialize, Deserialize)] #[derive(Default, Debug, Clone, Serialize, Deserialize)]
@ -294,26 +299,26 @@ pub struct Amount {
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub enum AdyenPaymentMethod<'a> { pub enum AdyenPaymentMethod<'a> {
AdyenAffirm(Box<AdyenPayLaterData>), AdyenAffirm(Box<PmdForPaymentType>),
AdyenCard(Box<AdyenCard>), AdyenCard(Box<AdyenCard>),
AdyenKlarna(Box<AdyenPayLaterData>), AdyenKlarna(Box<PmdForPaymentType>),
AdyenPaypal(Box<AdyenPaypal>), AdyenPaypal(Box<PmdForPaymentType>),
AfterPay(Box<AdyenPayLaterData>), AfterPay(Box<PmdForPaymentType>),
AlmaPayLater(Box<AdyenPayLaterData>), AlmaPayLater(Box<PmdForPaymentType>),
AliPay(Box<AliPayData>), AliPay(Box<PmdForPaymentType>),
AliPayHk(Box<AliPayHkData>), AliPayHk(Box<PmdForPaymentType>),
ApplePay(Box<AdyenApplePay>), ApplePay(Box<AdyenApplePay>),
#[serde(rename = "atome")] #[serde(rename = "atome")]
Atome(Box<AtomeData>), Atome(Box<AtomeData>),
BancontactCard(Box<BancontactCardData>), BancontactCard(Box<BancontactCardData>),
Bizum(Box<BankRedirectionPMData>), Bizum(Box<PmdForPaymentType>),
Blik(Box<BlikRedirectionData>), Blik(Box<BlikRedirectionData>),
ClearPay(Box<AdyenPayLaterData>), ClearPay(Box<PmdForPaymentType>),
Dana(Box<DanaWalletData>), Dana(Box<PmdForPaymentType>),
Eps(Box<BankRedirectionWithIssuer<'a>>), Eps(Box<BankRedirectionWithIssuer<'a>>),
#[serde(rename = "gcash")] #[serde(rename = "gcash")]
Gcash(Box<GcashData>), Gcash(Box<GcashData>),
Giropay(Box<BankRedirectionPMData>), Giropay(Box<PmdForPaymentType>),
Gpay(Box<AdyenGPay>), Gpay(Box<AdyenGPay>),
#[serde(rename = "gopay_wallet")] #[serde(rename = "gopay_wallet")]
GoPay(Box<GoPayData>), GoPay(Box<GoPayData>),
@ -322,31 +327,32 @@ pub enum AdyenPaymentMethod<'a> {
Kakaopay(Box<KakaoPayData>), Kakaopay(Box<KakaoPayData>),
Mandate(Box<AdyenMandate>), Mandate(Box<AdyenMandate>),
Mbway(Box<MbwayData>), Mbway(Box<MbwayData>),
MobilePay(Box<MobilePayData>), MobilePay(Box<PmdForPaymentType>),
#[serde(rename = "momo_wallet")] #[serde(rename = "momo_wallet")]
Momo(Box<MomoData>), Momo(Box<MomoData>),
#[serde(rename = "touchngo")] #[serde(rename = "touchngo")]
TouchNGo(Box<TouchNGoData>), TouchNGo(Box<TouchNGoData>),
OnlineBankingCzechRepublic(Box<OnlineBankingCzechRepublicData>), OnlineBankingCzechRepublic(Box<OnlineBankingCzechRepublicData>),
OnlineBankingFinland(Box<OnlineBankingFinlandData>), OnlineBankingFinland(Box<PmdForPaymentType>),
OnlineBankingPoland(Box<OnlineBankingPolandData>), OnlineBankingPoland(Box<OnlineBankingPolandData>),
OnlineBankingSlovakia(Box<OnlineBankingSlovakiaData>), OnlineBankingSlovakia(Box<OnlineBankingSlovakiaData>),
#[serde(rename = "molpay_ebanking_fpx_MY")] #[serde(rename = "molpay_ebanking_fpx_MY")]
OnlineBankingFpx(Box<OnlineBankingFpxData>), OnlineBankingFpx(Box<OnlineBankingFpxData>),
#[serde(rename = "molpay_ebanking_TH")] #[serde(rename = "molpay_ebanking_TH")]
OnlineBankingThailand(Box<OnlineBankingThailandData>), OnlineBankingThailand(Box<OnlineBankingThailandData>),
PayBright(Box<PayBrightData>), PayBright(Box<PmdForPaymentType>),
Sofort(Box<BankRedirectionPMData>), Sofort(Box<PmdForPaymentType>),
Trustly(Box<BankRedirectionPMData>), Trustly(Box<PmdForPaymentType>),
Walley(Box<WalleyData>), Walley(Box<PmdForPaymentType>),
WeChatPayWeb(Box<WeChatPayWebData>), WeChatPayWeb(Box<PmdForPaymentType>),
AchDirectDebit(Box<AchDirectDebitData>), AchDirectDebit(Box<AchDirectDebitData>),
#[serde(rename = "sepadirectdebit")] #[serde(rename = "sepadirectdebit")]
SepaDirectDebit(Box<SepaDirectDebitData>), SepaDirectDebit(Box<SepaDirectDebitData>),
BacsDirectDebit(Box<BacsDirectDebitData>), BacsDirectDebit(Box<BacsDirectDebitData>),
SamsungPay(Box<SamsungPayPmData>), SamsungPay(Box<SamsungPayPmData>),
Twint(Box<TwintWalletData>), Twint(Box<PmdForPaymentType>),
Vipps(Box<VippsWalletData>), Vipps(Box<PmdForPaymentType>),
Pix(Box<PmdForPaymentType>),
} }
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
@ -386,11 +392,8 @@ pub struct MandateData {
stored_payment_method_id: String, stored_payment_method_id: String,
} }
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WeChatPayWebData { pub struct AtomeData {}
#[serde(rename = "type")]
payment_type: PaymentType,
}
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
@ -404,11 +407,6 @@ pub struct BancontactCardData {
holder_name: Secret<String>, holder_name: Secret<String>,
} }
#[derive(Debug, Clone, Serialize)]
pub struct MobilePayData {
#[serde(rename = "type")]
payment_type: PaymentType,
}
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct MbwayData { pub struct MbwayData {
@ -417,12 +415,6 @@ pub struct MbwayData {
telephone_number: Secret<String>, telephone_number: Secret<String>,
} }
#[derive(Debug, Clone, Serialize)]
pub struct WalleyData {
#[serde(rename = "type")]
payment_type: PaymentType,
}
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
pub struct SamsungPayPmData { pub struct SamsungPayPmData {
#[serde(rename = "type")] #[serde(rename = "type")]
@ -432,16 +424,11 @@ pub struct SamsungPayPmData {
} }
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
pub struct PayBrightData { pub struct PmdForPaymentType {
#[serde(rename = "type")] #[serde(rename = "type")]
payment_type: PaymentType, payment_type: PaymentType,
} }
#[derive(Debug, Clone, Serialize)]
pub struct OnlineBankingFinlandData {
#[serde(rename = "type")]
payment_type: PaymentType,
}
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
pub struct OnlineBankingCzechRepublicData { pub struct OnlineBankingCzechRepublicData {
#[serde(rename = "type")] #[serde(rename = "type")]
@ -659,13 +646,6 @@ pub struct BlikRedirectionData {
blik_code: String, blik_code: String,
} }
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct BankRedirectionPMData {
#[serde(rename = "type")]
payment_type: PaymentType,
}
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct BankRedirectionWithIssuer<'a> { pub struct BankRedirectionWithIssuer<'a> {
@ -724,23 +704,6 @@ pub enum CancelStatus {
#[default] #[default]
Processing, Processing,
} }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AdyenPaypal {
#[serde(rename = "type")]
payment_type: PaymentType,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AliPayData {
#[serde(rename = "type")]
payment_type: PaymentType,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AliPayHkData {
#[serde(rename = "type")]
payment_type: PaymentType,
}
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GoPayData {} pub struct GoPayData {}
@ -772,33 +735,6 @@ pub struct AdyenApplePay {
apple_pay_token: Secret<String>, apple_pay_token: Secret<String>,
} }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DanaWalletData {
#[serde(rename = "type")]
payment_type: PaymentType,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TwintWalletData {
#[serde(rename = "type")]
payment_type: PaymentType,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VippsWalletData {
#[serde(rename = "type")]
payment_type: PaymentType,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AtomeData {}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AdyenPayLaterData {
#[serde(rename = "type")]
payment_type: PaymentType,
}
// Refunds Request and Response // Refunds Request and Response
#[derive(Default, Debug, Serialize, Deserialize)] #[derive(Default, Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
@ -819,6 +755,12 @@ pub struct AdyenRefundResponse {
status: String, status: String,
} }
#[derive(Clone, Debug, Serialize)]
pub struct QrCodeNextInstructions {
pub image_data_url: Option<Url>,
pub qr_code_url: Option<Url>,
}
pub struct AdyenAuthType { pub struct AdyenAuthType {
pub(super) api_key: String, pub(super) api_key: String,
pub(super) merchant_account: String, pub(super) merchant_account: String,
@ -885,6 +827,7 @@ pub enum PaymentType {
#[serde(rename = "directdebit_GB")] #[serde(rename = "directdebit_GB")]
BacsDirectDebit, BacsDirectDebit,
Samsungpay, Samsungpay,
Pix,
Twint, Twint,
Vipps, Vipps,
} }
@ -1039,6 +982,9 @@ impl<'a> TryFrom<&types::PaymentsAuthorizeRouterData> for AdyenPaymentRequest<'a
api_models::payments::PaymentMethodData::BankDebit(ref bank_debit) => { api_models::payments::PaymentMethodData::BankDebit(ref bank_debit) => {
AdyenPaymentRequest::try_from((item, bank_debit)) AdyenPaymentRequest::try_from((item, bank_debit))
} }
api_models::payments::PaymentMethodData::BankTransfer(ref bank_transfer) => {
AdyenPaymentRequest::try_from((item, bank_transfer.as_ref()))
}
_ => Err(errors::ConnectorError::NotSupported { _ => Err(errors::ConnectorError::NotSupported {
message: format!("{:?}", item.request.payment_method_type), message: format!("{:?}", item.request.payment_method_type),
connector: "Adyen", connector: "Adyen",
@ -1370,19 +1316,19 @@ impl<'a> TryFrom<&api::WalletData> for AdyenPaymentMethod<'a> {
Ok(AdyenPaymentMethod::ApplePay(Box::new(apple_pay_data))) Ok(AdyenPaymentMethod::ApplePay(Box::new(apple_pay_data)))
} }
api_models::payments::WalletData::PaypalRedirect(_) => { api_models::payments::WalletData::PaypalRedirect(_) => {
let wallet = AdyenPaypal { let wallet = PmdForPaymentType {
payment_type: PaymentType::Paypal, payment_type: PaymentType::Paypal,
}; };
Ok(AdyenPaymentMethod::AdyenPaypal(Box::new(wallet))) Ok(AdyenPaymentMethod::AdyenPaypal(Box::new(wallet)))
} }
api_models::payments::WalletData::AliPayRedirect(_) => { api_models::payments::WalletData::AliPayRedirect(_) => {
let alipay_data = AliPayData { let alipay_data = PmdForPaymentType {
payment_type: PaymentType::Alipay, payment_type: PaymentType::Alipay,
}; };
Ok(AdyenPaymentMethod::AliPay(Box::new(alipay_data))) Ok(AdyenPaymentMethod::AliPay(Box::new(alipay_data)))
} }
api_models::payments::WalletData::AliPayHkRedirect(_) => { api_models::payments::WalletData::AliPayHkRedirect(_) => {
let alipay_hk_data = AliPayHkData { let alipay_hk_data = PmdForPaymentType {
payment_type: PaymentType::AlipayHk, payment_type: PaymentType::AlipayHk,
}; };
Ok(AdyenPaymentMethod::AliPayHk(Box::new(alipay_hk_data))) Ok(AdyenPaymentMethod::AliPayHk(Box::new(alipay_hk_data)))
@ -1415,13 +1361,13 @@ impl<'a> TryFrom<&api::WalletData> for AdyenPaymentMethod<'a> {
Ok(AdyenPaymentMethod::Mbway(Box::new(mbway_data))) Ok(AdyenPaymentMethod::Mbway(Box::new(mbway_data)))
} }
api_models::payments::WalletData::MobilePayRedirect(_) => { api_models::payments::WalletData::MobilePayRedirect(_) => {
let data = MobilePayData { let data = PmdForPaymentType {
payment_type: PaymentType::MobilePay, payment_type: PaymentType::MobilePay,
}; };
Ok(AdyenPaymentMethod::MobilePay(Box::new(data))) Ok(AdyenPaymentMethod::MobilePay(Box::new(data)))
} }
api_models::payments::WalletData::WeChatPayRedirect(_) => { api_models::payments::WalletData::WeChatPayRedirect(_) => {
let data = WeChatPayWebData { let data = PmdForPaymentType {
payment_type: PaymentType::WeChatPayWeb, payment_type: PaymentType::WeChatPayWeb,
}; };
Ok(AdyenPaymentMethod::WeChatPayWeb(Box::new(data))) Ok(AdyenPaymentMethod::WeChatPayWeb(Box::new(data)))
@ -1434,19 +1380,19 @@ impl<'a> TryFrom<&api::WalletData> for AdyenPaymentMethod<'a> {
Ok(AdyenPaymentMethod::SamsungPay(Box::new(data))) Ok(AdyenPaymentMethod::SamsungPay(Box::new(data)))
} }
api_models::payments::WalletData::TwintRedirect { .. } => { api_models::payments::WalletData::TwintRedirect { .. } => {
let data = TwintWalletData { let data = PmdForPaymentType {
payment_type: PaymentType::Twint, payment_type: PaymentType::Twint,
}; };
Ok(AdyenPaymentMethod::Twint(Box::new(data))) Ok(AdyenPaymentMethod::Twint(Box::new(data)))
} }
api_models::payments::WalletData::VippsRedirect { .. } => { api_models::payments::WalletData::VippsRedirect { .. } => {
let data = VippsWalletData { let data = PmdForPaymentType {
payment_type: PaymentType::Vipps, payment_type: PaymentType::Vipps,
}; };
Ok(AdyenPaymentMethod::Vipps(Box::new(data))) Ok(AdyenPaymentMethod::Vipps(Box::new(data)))
} }
api_models::payments::WalletData::DanaRedirect { .. } => { api_models::payments::WalletData::DanaRedirect { .. } => {
let data = DanaWalletData { let data = PmdForPaymentType {
payment_type: PaymentType::Dana, payment_type: PaymentType::Dana,
}; };
Ok(AdyenPaymentMethod::Dana(Box::new(data))) Ok(AdyenPaymentMethod::Dana(Box::new(data)))
@ -1466,13 +1412,13 @@ impl<'a> TryFrom<(&api::PayLaterData, Option<api_enums::CountryAlpha2>)>
let (pay_later_data, country_code) = value; let (pay_later_data, country_code) = value;
match pay_later_data { match pay_later_data {
api_models::payments::PayLaterData::KlarnaRedirect { .. } => { api_models::payments::PayLaterData::KlarnaRedirect { .. } => {
let klarna = AdyenPayLaterData { let klarna = PmdForPaymentType {
payment_type: PaymentType::Klarna, payment_type: PaymentType::Klarna,
}; };
Ok(AdyenPaymentMethod::AdyenKlarna(Box::new(klarna))) Ok(AdyenPaymentMethod::AdyenKlarna(Box::new(klarna)))
} }
api_models::payments::PayLaterData::AffirmRedirect { .. } => Ok( api_models::payments::PayLaterData::AffirmRedirect { .. } => Ok(
AdyenPaymentMethod::AdyenAffirm(Box::new(AdyenPayLaterData { AdyenPaymentMethod::AdyenAffirm(Box::new(PmdForPaymentType {
payment_type: PaymentType::Affirm, payment_type: PaymentType::Affirm,
})), })),
), ),
@ -1483,11 +1429,11 @@ impl<'a> TryFrom<(&api::PayLaterData, Option<api_enums::CountryAlpha2>)>
| api_enums::CountryAlpha2::FR | api_enums::CountryAlpha2::FR
| api_enums::CountryAlpha2::ES | api_enums::CountryAlpha2::ES
| api_enums::CountryAlpha2::GB => { | api_enums::CountryAlpha2::GB => {
Ok(AdyenPaymentMethod::ClearPay(Box::new(AdyenPayLaterData { Ok(AdyenPaymentMethod::ClearPay(Box::new(PmdForPaymentType {
payment_type: PaymentType::ClearPay, payment_type: PaymentType::ClearPay,
}))) })))
} }
_ => Ok(AdyenPaymentMethod::AfterPay(Box::new(AdyenPayLaterData { _ => Ok(AdyenPaymentMethod::AfterPay(Box::new(PmdForPaymentType {
payment_type: PaymentType::Afterpaytouch, payment_type: PaymentType::Afterpaytouch,
}))), }))),
} }
@ -1498,17 +1444,17 @@ impl<'a> TryFrom<(&api::PayLaterData, Option<api_enums::CountryAlpha2>)>
} }
} }
api_models::payments::PayLaterData::PayBrightRedirect { .. } => { api_models::payments::PayLaterData::PayBrightRedirect { .. } => {
Ok(AdyenPaymentMethod::PayBright(Box::new(PayBrightData { Ok(AdyenPaymentMethod::PayBright(Box::new(PmdForPaymentType {
payment_type: PaymentType::PayBright, payment_type: PaymentType::PayBright,
}))) })))
} }
api_models::payments::PayLaterData::WalleyRedirect { .. } => { api_models::payments::PayLaterData::WalleyRedirect { .. } => {
Ok(AdyenPaymentMethod::Walley(Box::new(WalleyData { Ok(AdyenPaymentMethod::Walley(Box::new(PmdForPaymentType {
payment_type: PaymentType::Walley, payment_type: PaymentType::Walley,
}))) })))
} }
api_models::payments::PayLaterData::AlmaRedirect { .. } => Ok( api_models::payments::PayLaterData::AlmaRedirect { .. } => Ok(
AdyenPaymentMethod::AlmaPayLater(Box::new(AdyenPayLaterData { AdyenPaymentMethod::AlmaPayLater(Box::new(PmdForPaymentType {
payment_type: PaymentType::Alma, payment_type: PaymentType::Alma,
})), })),
), ),
@ -1563,7 +1509,7 @@ impl<'a> TryFrom<&api_models::payments::BankRedirectData> for AdyenPaymentMethod
}, },
))), ))),
api_models::payments::BankRedirectData::Bizum { .. } => { api_models::payments::BankRedirectData::Bizum { .. } => {
Ok(AdyenPaymentMethod::Bizum(Box::new(BankRedirectionPMData { Ok(AdyenPaymentMethod::Bizum(Box::new(PmdForPaymentType {
payment_type: PaymentType::Bizum, payment_type: PaymentType::Bizum,
}))) })))
} }
@ -1582,11 +1528,11 @@ impl<'a> TryFrom<&api_models::payments::BankRedirectData> for AdyenPaymentMethod
.map(|adyen_bank_name| adyen_bank_name.0), .map(|adyen_bank_name| adyen_bank_name.0),
})), })),
), ),
api_models::payments::BankRedirectData::Giropay { .. } => Ok( api_models::payments::BankRedirectData::Giropay { .. } => {
AdyenPaymentMethod::Giropay(Box::new(BankRedirectionPMData { Ok(AdyenPaymentMethod::Giropay(Box::new(PmdForPaymentType {
payment_type: PaymentType::Giropay, payment_type: PaymentType::Giropay,
})), })))
), }
api_models::payments::BankRedirectData::Ideal { bank_name, .. } => Ok( api_models::payments::BankRedirectData::Ideal { bank_name, .. } => Ok(
AdyenPaymentMethod::Ideal(Box::new(BankRedirectionWithIssuer { AdyenPaymentMethod::Ideal(Box::new(BankRedirectionWithIssuer {
payment_type: PaymentType::Ideal, payment_type: PaymentType::Ideal,
@ -1605,7 +1551,7 @@ impl<'a> TryFrom<&api_models::payments::BankRedirectData> for AdyenPaymentMethod
))) )))
} }
api_models::payments::BankRedirectData::OnlineBankingFinland { .. } => Ok( api_models::payments::BankRedirectData::OnlineBankingFinland { .. } => Ok(
AdyenPaymentMethod::OnlineBankingFinland(Box::new(OnlineBankingFinlandData { AdyenPaymentMethod::OnlineBankingFinland(Box::new(PmdForPaymentType {
payment_type: PaymentType::OnlineBankingFinland, payment_type: PaymentType::OnlineBankingFinland,
})), })),
), ),
@ -1631,21 +1577,42 @@ impl<'a> TryFrom<&api_models::payments::BankRedirectData> for AdyenPaymentMethod
issuer: OnlineBankingThailandIssuer::try_from(issuer)?, issuer: OnlineBankingThailandIssuer::try_from(issuer)?,
})), })),
), ),
api_models::payments::BankRedirectData::Sofort { .. } => Ok( api_models::payments::BankRedirectData::Sofort { .. } => {
AdyenPaymentMethod::Sofort(Box::new(BankRedirectionPMData { Ok(AdyenPaymentMethod::Sofort(Box::new(PmdForPaymentType {
payment_type: PaymentType::Sofort, payment_type: PaymentType::Sofort,
})), })))
), }
api_models::payments::BankRedirectData::Trustly { .. } => Ok( api_models::payments::BankRedirectData::Trustly { .. } => {
AdyenPaymentMethod::Trustly(Box::new(BankRedirectionPMData { Ok(AdyenPaymentMethod::Trustly(Box::new(PmdForPaymentType {
payment_type: PaymentType::Trustly, payment_type: PaymentType::Trustly,
})), })))
), }
_ => Err(errors::ConnectorError::NotImplemented("Payment method".to_string()).into()), _ => Err(errors::ConnectorError::NotImplemented("Payment method".to_string()).into()),
} }
} }
} }
impl<'a> TryFrom<&api_models::payments::BankTransferData> for AdyenPaymentMethod<'a> {
type Error = Error;
fn try_from(
bank_transfer_data: &api_models::payments::BankTransferData,
) -> Result<Self, Self::Error> {
match bank_transfer_data {
api_models::payments::BankTransferData::Pix {} => {
Ok(AdyenPaymentMethod::Pix(Box::new(PmdForPaymentType {
payment_type: PaymentType::Pix,
})))
}
api_models::payments::BankTransferData::AchBankTransfer { .. }
| api_models::payments::BankTransferData::SepaBankTransfer { .. }
| api_models::payments::BankTransferData::BacsBankTransfer { .. }
| api_models::payments::BankTransferData::MultibancoBankTransfer { .. } => {
Err(errors::ConnectorError::NotImplemented("Payment method".to_string()).into())
}
}
}
}
impl<'a> impl<'a>
TryFrom<( TryFrom<(
&types::PaymentsAuthorizeRouterData, &types::PaymentsAuthorizeRouterData,
@ -1822,6 +1789,52 @@ impl<'a>
} }
} }
impl<'a>
TryFrom<(
&types::PaymentsAuthorizeRouterData,
&api_models::payments::BankTransferData,
)> for AdyenPaymentRequest<'a>
{
type Error = Error;
fn try_from(
value: (
&types::PaymentsAuthorizeRouterData,
&api_models::payments::BankTransferData,
),
) -> Result<Self, Self::Error> {
let (item, bank_transfer_data) = value;
let amount = get_amount_data(item);
let auth_type = AdyenAuthType::try_from(&item.connector_auth_type)?;
let shopper_interaction = AdyenShopperInteraction::from(item);
let return_url = item.request.get_return_url()?;
let payment_method = AdyenPaymentMethod::try_from(bank_transfer_data)?;
let request = AdyenPaymentRequest {
amount,
merchant_account: auth_type.merchant_account,
payment_method,
reference: item.payment_id.to_string(),
return_url,
browser_info: None,
shopper_interaction,
recurring_processing_model: None,
additional_data: None,
shopper_name: None,
shopper_locale: None,
shopper_email: item.request.email.clone(),
telephone_number: None,
billing_address: None,
delivery_address: None,
country_code: None,
line_items: None,
shopper_reference: None,
store_payment_method: None,
channel: None,
};
Ok(request)
}
}
impl<'a> impl<'a>
TryFrom<( TryFrom<(
&types::PaymentsAuthorizeRouterData, &types::PaymentsAuthorizeRouterData,
@ -2101,8 +2114,8 @@ pub fn get_adyen_response(
Ok((status, error, payments_response_data)) Ok((status, error, payments_response_data))
} }
pub fn get_redirection_response( pub fn get_next_action_response(
response: RedirectionResponse, response: AdyenNextActionResponse,
is_manual_capture: bool, is_manual_capture: bool,
status_code: u16, status_code: u16,
) -> errors::CustomResult< ) -> errors::CustomResult<
@ -2113,15 +2126,19 @@ pub fn get_redirection_response(
), ),
errors::ConnectorError, errors::ConnectorError,
> { > {
let status = let status = storage_enums::AttemptStatus::foreign_from((
storage_enums::AttemptStatus::foreign_from((is_manual_capture, response.result_code)); is_manual_capture,
response.result_code.to_owned(),
));
let error = if response.refusal_reason.is_some() || response.refusal_reason_code.is_some() { let error = if response.refusal_reason.is_some() || response.refusal_reason_code.is_some() {
Some(types::ErrorResponse { Some(types::ErrorResponse {
code: response code: response
.refusal_reason_code .refusal_reason_code
.to_owned()
.unwrap_or_else(|| consts::NO_ERROR_CODE.to_string()), .unwrap_or_else(|| consts::NO_ERROR_CODE.to_string()),
message: response message: response
.refusal_reason .refusal_reason
.to_owned()
.unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()), .unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()),
reason: None, reason: None,
status_code, status_code,
@ -2130,29 +2147,27 @@ pub fn get_redirection_response(
None None
}; };
let redirection_data = response.action.url.map(|url| { let redirection_data = match response.action.type_of_response {
let form_fields = response.action.data.unwrap_or_else(|| { ActionType::QrCode => None,
std::collections::HashMap::from_iter( _ => response
url.query_pairs() .action
.map(|(key, value)| (key.to_string(), value.to_string())), .url
) .to_owned()
}); .map(|url| services::RedirectForm::from((url, services::Method::Get))),
services::RedirectForm::Form { };
endpoint: url.to_string(),
method: response.action.method.unwrap_or(services::Method::Get), let connector_metadata = get_connector_metadata(response)?;
form_fields,
}
});
// We don't get connector transaction id for redirections in Adyen. // We don't get connector transaction id for redirections in Adyen.
let payments_response_data = types::PaymentsResponseData::TransactionResponse { let payments_response_data = types::PaymentsResponseData::TransactionResponse {
resource_id: types::ResponseId::NoResponseId, resource_id: types::ResponseId::NoResponseId,
redirection_data, redirection_data,
mandate_reference: None, mandate_reference: None,
connector_metadata: None, connector_metadata,
network_txn_id: None, network_txn_id: None,
connector_response_reference_id: None, connector_response_reference_id: None,
}; };
Ok((status, error, payments_response_data)) Ok((status, error, payments_response_data))
} }
@ -2188,6 +2203,46 @@ pub fn get_redirection_error_response(
Ok((status, error, payments_response_data)) Ok((status, error, payments_response_data))
} }
pub fn get_connector_metadata(
response: AdyenNextActionResponse,
) -> errors::CustomResult<Option<serde_json::Value>, errors::ConnectorError> {
let connector_metadata = match response.action.type_of_response {
ActionType::QrCode => {
let metadata = get_qr_code_metadata(response);
Some(metadata)
}
_ => None,
}
.transpose()
.change_context(errors::ConnectorError::ResponseHandlingFailed)?;
Ok(connector_metadata)
}
pub fn get_qr_code_metadata(
response: AdyenNextActionResponse,
) -> errors::CustomResult<serde_json::Value, errors::ConnectorError> {
let image_data = response
.action
.qr_code_data
.map(crate_utils::QrImage::new_from_data)
.transpose()
.change_context(errors::ConnectorError::ResponseHandlingFailed)?;
let image_data_url =
image_data.and_then(|image_data| Url::parse(image_data.data.as_str()).ok());
let qr_code_instructions = QrCodeNextInstructions {
image_data_url,
qr_code_url: response.action.url,
};
common_utils::ext_traits::Encode::<QrCodeNextInstructions>::encode_to_value(
&qr_code_instructions,
)
.change_context(errors::ConnectorError::ResponseHandlingFailed)
}
impl<F, Req> impl<F, Req>
TryFrom<( TryFrom<(
types::ResponseRouterData<F, AdyenPaymentResponse, Req, types::PaymentsResponseData>, types::ResponseRouterData<F, AdyenPaymentResponse, Req, types::PaymentsResponseData>,
@ -2207,8 +2262,8 @@ impl<F, Req>
AdyenPaymentResponse::Response(response) => { AdyenPaymentResponse::Response(response) => {
get_adyen_response(response, is_manual_capture, item.http_code)? get_adyen_response(response, is_manual_capture, item.http_code)?
} }
AdyenPaymentResponse::RedirectResponse(response) => { AdyenPaymentResponse::AdyenNextActionResponse(response) => {
get_redirection_response(response, is_manual_capture, item.http_code)? get_next_action_response(response, is_manual_capture, item.http_code)?
} }
AdyenPaymentResponse::RedirectionErrorResponse(response) => { AdyenPaymentResponse::RedirectionErrorResponse(response) => {
get_redirection_error_response(response, is_manual_capture, item.http_code)? get_redirection_error_response(response, is_manual_capture, item.http_code)?

View File

@ -1232,12 +1232,13 @@ fn create_stripe_payment_method(
billing_details, billing_details,
)) ))
} }
payments::BankTransferData::Pix {} => Err(errors::ConnectorError::NotImplemented(
"this payment method".to_string(),
)
.into()),
} }
} }
_ => Err(errors::ConnectorError::NotImplemented( _ => Err(errors::ConnectorError::NotImplemented("payment method".to_string()).into()),
"this payment method for stripe".to_string(),
)
.into()),
} }
} }
@ -1660,7 +1661,6 @@ pub struct SepaAndBacsBankTransferInstructions {
pub receiver: SepaAndBacsReceiver, pub receiver: SepaAndBacsReceiver,
} }
#[serde_with::skip_serializing_none]
#[derive(Clone, Debug, Serialize)] #[derive(Clone, Debug, Serialize)]
pub struct WechatPayNextInstructions { pub struct WechatPayNextInstructions {
pub image_data_url: Url, pub image_data_url: Url,
@ -2900,6 +2900,9 @@ impl
payment_method_type: StripePaymentMethodType::CustomerBalance, payment_method_type: StripePaymentMethodType::CustomerBalance,
})), })),
)), )),
payments::BankTransferData::Pix {} => Err(
errors::ConnectorError::NotImplemented("payment method".to_string()).into(),
),
} }
} }
api::PaymentMethodData::MandatePayment api::PaymentMethodData::MandatePayment

View File

@ -376,6 +376,7 @@ where
if payment_intent.status == enums::IntentStatus::RequiresCustomerAction if payment_intent.status == enums::IntentStatus::RequiresCustomerAction
|| bank_transfer_next_steps.is_some() || bank_transfer_next_steps.is_some()
|| next_action_containing_qr_code.is_some()
{ {
next_action_response = bank_transfer_next_steps next_action_response = bank_transfer_next_steps
.map(|bank_transfer| { .map(|bank_transfer| {
@ -386,6 +387,7 @@ where
.or(next_action_containing_qr_code.map(|qr_code_data| { .or(next_action_containing_qr_code.map(|qr_code_data| {
api_models::payments::NextActionData::QrCodeInformation { api_models::payments::NextActionData::QrCodeInformation {
image_data_url: qr_code_data.image_data_url, image_data_url: qr_code_data.image_data_url,
qr_code_url: qr_code_data.qr_code_url,
} }
})) }))
.or(redirection_data.map(|_| { .or(redirection_data.map(|_| {
@ -661,24 +663,19 @@ impl ForeignFrom<ephemeral_key::EphemeralKey> for api::ephemeral_key::EphemeralK
pub fn bank_transfer_next_steps_check( pub fn bank_transfer_next_steps_check(
payment_attempt: storage::PaymentAttempt, payment_attempt: storage::PaymentAttempt,
) -> RouterResult<Option<api_models::payments::BankTransferNextStepsData>> { ) -> RouterResult<Option<api_models::payments::BankTransferNextStepsData>> {
let bank_transfer_next_step = if let Some(diesel_models::enums::PaymentMethod::BankTransfer) = let bank_transfer_next_steps: Result<
payment_attempt.payment_method Option<api_models::payments::BankTransferNextStepsData>,
{ _,
let bank_transfer_next_steps: Option<api_models::payments::BankTransferNextStepsData> = > = payment_attempt
payment_attempt .connector_metadata
.connector_metadata .map(|metadata| {
.map(|metadata| { metadata
metadata .parse_value("BankTransferNextStepsData")
.parse_value("NextStepsRequirements") .change_context(errors::ApiErrorResponse::InternalServerError)
.change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed to parse the Value to NextRequirements struct")
.attach_printable("Failed to parse the Value to NextRequirements struct") })
}) .transpose();
.transpose()?; Ok(bank_transfer_next_steps.ok().flatten())
bank_transfer_next_steps
} else {
None
};
Ok(bank_transfer_next_step)
} }
pub fn change_order_details_to_new_type( pub fn change_order_details_to_new_type(

View File

@ -218,7 +218,9 @@ impl ForeignFrom<api_enums::PaymentMethodType> for api_enums::PaymentMethod {
} }
api_enums::PaymentMethodType::Evoucher api_enums::PaymentMethodType::Evoucher
| api_enums::PaymentMethodType::ClassicReward => Self::Reward, | api_enums::PaymentMethodType::ClassicReward => Self::Reward,
api_enums::PaymentMethodType::Multibanco => Self::BankTransfer, api_enums::PaymentMethodType::Multibanco | api_enums::PaymentMethodType::Pix => {
Self::BankTransfer
}
} }
} }
} }

View File

@ -3197,6 +3197,17 @@
} }
} }
} }
},
{
"type": "object",
"required": [
"pix"
],
"properties": {
"pix": {
"type": "object"
}
}
} }
] ]
}, },
@ -6249,11 +6260,17 @@
"description": "Contains url for Qr code image, this qr code has to be shown in sdk", "description": "Contains url for Qr code image, this qr code has to be shown in sdk",
"required": [ "required": [
"image_data_url", "image_data_url",
"qr_code_url",
"type" "type"
], ],
"properties": { "properties": {
"image_data_url": { "image_data_url": {
"type": "string" "type": "string",
"description": "Hyperswitch generated image data source url"
},
"qr_code_url": {
"type": "string",
"description": "The url for Qr code given by the connector"
}, },
"type": { "type": {
"type": "string", "type": "string",
@ -7232,6 +7249,7 @@
"online_banking_slovakia", "online_banking_slovakia",
"pay_bright", "pay_bright",
"paypal", "paypal",
"pix",
"przelewy24", "przelewy24",
"samsung_pay", "samsung_pay",
"sepa", "sepa",