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
billing_details: MultibancoBillingDetails,
},
Pix {},
}
#[derive(serde::Deserialize, serde::Serialize, Debug, Clone, ToSchema, Eq, PartialEq)]
@ -1331,8 +1332,12 @@ pub enum NextActionData {
ThirdPartySdkSessionToken { session_token: Option<SessionToken> },
/// Contains url for Qr code image, this qr code has to be shown in sdk
QrCodeInformation {
/// Hyperswitch generated image data source url
#[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)]
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)]

View File

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

View File

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

View File

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

View File

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

View File

@ -376,6 +376,7 @@ where
if payment_intent.status == enums::IntentStatus::RequiresCustomerAction
|| bank_transfer_next_steps.is_some()
|| next_action_containing_qr_code.is_some()
{
next_action_response = bank_transfer_next_steps
.map(|bank_transfer| {
@ -386,6 +387,7 @@ where
.or(next_action_containing_qr_code.map(|qr_code_data| {
api_models::payments::NextActionData::QrCodeInformation {
image_data_url: qr_code_data.image_data_url,
qr_code_url: qr_code_data.qr_code_url,
}
}))
.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(
payment_attempt: storage::PaymentAttempt,
) -> RouterResult<Option<api_models::payments::BankTransferNextStepsData>> {
let bank_transfer_next_step = if let Some(diesel_models::enums::PaymentMethod::BankTransfer) =
payment_attempt.payment_method
{
let bank_transfer_next_steps: Option<api_models::payments::BankTransferNextStepsData> =
payment_attempt
let bank_transfer_next_steps: Result<
Option<api_models::payments::BankTransferNextStepsData>,
_,
> = payment_attempt
.connector_metadata
.map(|metadata| {
metadata
.parse_value("NextStepsRequirements")
.parse_value("BankTransferNextStepsData")
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed to parse the Value to NextRequirements struct")
})
.transpose()?;
bank_transfer_next_steps
} else {
None
};
Ok(bank_transfer_next_step)
.transpose();
Ok(bank_transfer_next_steps.ok().flatten())
}
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::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",
"required": [
"image_data_url",
"qr_code_url",
"type"
],
"properties": {
"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": "string",
@ -7232,6 +7249,7 @@
"online_banking_slovakia",
"pay_bright",
"paypal",
"pix",
"przelewy24",
"samsung_pay",
"sepa",