Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 153 additions & 2 deletions backend/connector-integration/src/connectors/adyen/transformers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ use domain_types::{
errors,
payment_method_data::{
BankDebitData, BankRedirectData, BankTransferData, Card, CardRedirectData,
DefaultPCIHolder, PaymentMethodData, PaymentMethodDataTypes, RawCardNumber, WalletData,
DefaultPCIHolder, GiftCardData, PaymentMethodData, PaymentMethodDataTypes, RawCardNumber,
WalletData,
},
router_data::{
ConnectorAuthType, ConnectorResponseData, ErrorResponse, ExtendedAuthorizationResponseData,
Expand Down Expand Up @@ -103,6 +104,22 @@ impl TryFrom<&domain_utils::CardIssuer> for CardBrand {
}
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum GiftCardBrand {
Givex,
Auriga,
Babygiftcard,
}

#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct AdyenGiftCardData {
brand: GiftCardBrand,
number: Secret<String>,
cvc: Secret<String>,
}

#[derive(Debug, Serialize, PartialEq)]
pub enum ConnectorError {
ParsingFailed,
Expand Down Expand Up @@ -169,6 +186,10 @@ pub enum AdyenPaymentMethod<
OnlineBankingThailand(Box<OnlineBankingThailandData>),
#[serde(rename = "paybybank")]
OpenBankingUK(Box<OpenBankingUKData>),
#[serde(rename = "giftcard")]
AdyenGiftCard(Box<AdyenGiftCardData>),
#[serde(rename = "paysafecard")]
PaySafeCard,
#[serde(rename = "trustly")]
Trustly,
// Bank transfer payment methods (Indonesian banks via Doku)
Expand Down Expand Up @@ -1032,6 +1053,8 @@ impl TryFrom<&common_enums::PaymentMethodType> for PaymentType {

common_enums::PaymentMethodType::Paypal => Ok(Self::Paypal),
common_enums::PaymentMethodType::Pix => Ok(Self::Pix),
common_enums::PaymentMethodType::Givex => Ok(Self::Giftcard),
common_enums::PaymentMethodType::PaySafeCard => Ok(Self::PaySafeCard),
_ => Err(errors::ConnectorError::NotImplemented(
utils::get_unimplemented_payment_method_error_message("Adyen"),
))?,
Expand Down Expand Up @@ -1350,6 +1373,25 @@ impl<T: PaymentMethodDataTypes + std::fmt::Debug + Sync + Send + 'static + Seria
}
}

impl<T: PaymentMethodDataTypes + std::fmt::Debug + Sync + Send + 'static + Serialize>
TryFrom<&GiftCardData> for AdyenPaymentMethod<T>
{
type Error = Error;
fn try_from(gift_card_data: &GiftCardData) -> Result<Self, Self::Error> {
match gift_card_data {
GiftCardData::PaySafeCard {} => Ok(Self::PaySafeCard),
GiftCardData::Givex(givex_data) => {
let gift_card_pm = AdyenGiftCardData {
brand: GiftCardBrand::Givex,
number: givex_data.number.clone(),
cvc: givex_data.cvc.clone(),
};
Ok(Self::AdyenGiftCard(Box::new(gift_card_pm)))
}
}
}
}

impl<T: PaymentMethodDataTypes + std::fmt::Debug + Sync + Send + 'static + Serialize>
TryFrom<(
&BankRedirectData,
Expand Down Expand Up @@ -2453,6 +2495,113 @@ impl<T: PaymentMethodDataTypes + std::fmt::Debug + Sync + Send + 'static + Seria
}
}

impl<T: PaymentMethodDataTypes + std::fmt::Debug + Sync + Send + 'static + Serialize>
TryFrom<(
AdyenRouterData<
RouterDataV2<
Authorize,
PaymentFlowData,
PaymentsAuthorizeData<T>,
PaymentsResponseData,
>,
T,
>,
&GiftCardData,
)> for AdyenPaymentRequest<T>
{
type Error = Error;
fn try_from(
value: (
AdyenRouterData<
RouterDataV2<
Authorize,
PaymentFlowData,
PaymentsAuthorizeData<T>,
PaymentsResponseData,
>,
T,
>,
&GiftCardData,
),
) -> Result<Self, Self::Error> {
let (item, gift_card_data) = value;
let amount = get_amount_data(&item);
let auth_type = AdyenAuthType::try_from(&item.router_data.connector_auth_type)?;
let payment_method = PaymentMethod::AdyenPaymentMethod(Box::new(
AdyenPaymentMethod::try_from(gift_card_data)?,
));
let shopper_interaction = AdyenShopperInteraction::from(&item.router_data);
let return_url = item.router_data.request.get_router_return_url()?;

let adyen_metadata =
get_adyen_metadata(item.router_data.request.metadata.clone().expose_option());
let device_fingerprint = adyen_metadata.device_fingerprint.clone();
let platform_chargeback_logic = adyen_metadata.platform_chargeback_logic.clone();
let billing_address = get_address_info(
item.router_data
.resource_common_data
.address
.get_payment_billing(),
)
.and_then(Result::ok);
let delivery_address = get_address_info(
item.router_data
.resource_common_data
.get_optional_shipping(),
)
.and_then(Result::ok);

Ok(Self {
amount,
merchant_account: auth_type.merchant_account,
payment_method,
reference: item
.router_data
.resource_common_data
.connector_request_reference_id
.clone(),
return_url,
shopper_interaction,
recurring_processing_model: None,
browser_info: None,
additional_data: None,
mpi_data: None,
telephone_number: item
.router_data
.resource_common_data
.get_optional_billing_phone_number(),
shopper_name: None,
shopper_email: item
.router_data
.resource_common_data
.get_optional_billing_email(),
shopper_locale: item.router_data.request.locale.clone(),
social_security_number: None,
billing_address,
delivery_address,
country_code: None,
line_items: None,
shopper_reference: None,
store_payment_method: None,
channel: None,
shopper_statement: get_shopper_statement(&item.router_data),
shopper_ip: item.router_data.request.get_ip_address_as_optional(),
merchant_order_reference: item.router_data.request.merchant_order_reference_id.clone(),
store: None,
splits: None,
device_fingerprint,
metadata: item
.router_data
.request
.metadata
.clone()
.map(|value| Secret::new(filter_adyen_metadata(value.expose()))),
platform_chargeback_logic,
session_validity: None,
})
}
}

fn get_redirect_extra_details<
T: PaymentMethodDataTypes + std::fmt::Debug + Sync + Send + 'static + Serialize,
>(
Expand Down Expand Up @@ -2525,9 +2674,11 @@ impl<T: PaymentMethodDataTypes + std::fmt::Debug + Sync + Send + 'static + Seria
Self::try_from((item, bank_transfer.as_ref()))
}
PaymentMethodData::BankDebit(ref bank_debit) => Self::try_from((item, bank_debit)),
PaymentMethodData::GiftCard(ref gift_card) => {
Self::try_from((item, gift_card.as_ref()))
}
PaymentMethodData::PayLater(_)
| PaymentMethodData::Voucher(_)
| PaymentMethodData::GiftCard(_)
| PaymentMethodData::Crypto(_)
| PaymentMethodData::MandatePayment
| PaymentMethodData::Reward
Expand Down
34 changes: 34 additions & 0 deletions backend/domain_types/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1218,6 +1218,31 @@ impl<
)))
}

grpc_api_types::payments::payment_method::PaymentMethod::Givex(givex_data) => {
Ok(Self::GiftCard(Box::new(
payment_method_data::GiftCardData::Givex(payment_method_data::GiftCardDetails {
number: givex_data.number.ok_or_else(|| ApplicationErrorResponse::BadRequest(ApiError {
sub_code: "MISSING_GIVEX_NUMBER".to_owned(),
error_identifier: 400,
error_message: "Missing Givex gift card number".to_owned(),
error_object: None,
}))?,
cvc: givex_data.cvc.ok_or_else(|| ApplicationErrorResponse::BadRequest(ApiError {
sub_code: "MISSING_GIVEX_CVC".to_owned(),
error_identifier: 400,
error_message: "Missing Givex gift card CVC".to_owned(),
error_object: None,
}))?,
}),
)))
}

grpc_api_types::payments::payment_method::PaymentMethod::PaySafeCard(_) => {
Ok(Self::GiftCard(Box::new(
payment_method_data::GiftCardData::PaySafeCard {},
)))
}

_ => Err(report!(ApplicationErrorResponse::BadRequest(ApiError {
sub_code: "UNSUPPORTED_PAYMENT_METHOD".to_owned(),
error_identifier: 400,
Expand Down Expand Up @@ -1474,6 +1499,15 @@ impl ForeignTryFrom<grpc_api_types::payments::PaymentMethod> for Option<PaymentM
grpc_api_types::payments::payment_method::PaymentMethod::CardDetailsForNetworkTransactionId(_) => Ok(Some(PaymentMethodType::Card)),
grpc_api_types::payments::payment_method::PaymentMethod::NetworkToken(_) => Ok(Some(PaymentMethodType::Card)),
// ============================================================================
// GIFT CARDS
// ============================================================================
grpc_api_types::payments::payment_method::PaymentMethod::Givex(_) => {
Ok(Some(PaymentMethodType::Givex))
}
grpc_api_types::payments::payment_method::PaymentMethod::PaySafeCard(_) => {
Ok(Some(PaymentMethodType::PaySafeCard))
}
// ============================================================================
// UNSUPPORTED ONLINE BANKING - Direct error generation
// ============================================================================
grpc_api_types::payments::payment_method::PaymentMethod::OnlineBankingThailand(_) => {
Expand Down
36 changes: 22 additions & 14 deletions backend/grpc-api-types/proto/payment_methods.proto
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ enum CardNetwork {
RUPAY = 10;
}

// Paysafecard - Prepaid payment method
message PaySafeCard {
// Fields will be added as needed for Paysafecard integration
}

// ============================================================================
// COMPOSITE MESSAGES
// ============================================================================
Expand Down Expand Up @@ -121,6 +126,10 @@ message PaymentMethod {
// NETWORK TRANSACTION METHODS (120-129) - For recurring payments with network transaction IDs
CardDetailsForNetworkTransactionId card_details_for_network_transaction_id = 120; // Card details with network transaction ID
NetworkTokenData network_token = 121; // Network token data

// GIFT CARDS (130-139)
Givex givex = 137; // Givex gift card
PaySafeCard pay_safe_card = 138; // Paysafecard - Prepaid payment method
}
}

Expand Down Expand Up @@ -988,15 +997,6 @@ message EVoucher {
// Fields will be added as needed for E-Voucher integration
}

// Givex - Gift card and loyalty program provider
message Givex {
// The gift card number
SecretString number = 1 [(validate.rules).string = {min_len: 1}];

// The card verification code
SecretString cvc = 2;
}

// Indomaret - Indonesian convenience store payment
message Indomaret {
// Fields will be added as needed for Indomaret integration
Expand All @@ -1012,11 +1012,6 @@ message PagoEfectivo {
// Fields will be added as needed for PagoEfectivo integration
}

// Paysafecard - Prepaid payment method
message PaySafeCard {
// Fields will be added as needed for Paysafecard integration
}

// 7-Eleven - Convenience store payment
message SevenEleven {
// Fields will be added as needed for 7-Eleven integration
Expand Down Expand Up @@ -1196,6 +1191,19 @@ message SecretString {
string value = 1;
}

// ============================================================================
// GIFT CARDS
// ============================================================================

// Givex - Gift card and loyalty program provider
message Givex {
// The gift card number
SecretString number = 1;

// The card verification code
SecretString cvc = 2;
}

enum BankNames {
BANK_NAMES_UNSPECIFIED = 0; // Default value must be first
AmericanExpress = 1;
Expand Down