feat(connector): [AMAZONPAY] add Payment flows for Amazon Pay Wallet (#7062)

Co-authored-by: Anurag Singh <anurag.singh.001@Anurag-Singh-WPMHJ5619X.local>
Co-authored-by: Anurag Singh <anurag.singh.001@AnuragSMHJ5619X.lan>
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
Co-authored-by: Anurag Singh <anurag.singh.001@MacBookPro.lan>
This commit is contained in:
Anurag
2025-08-29 14:00:32 +05:30
committed by GitHub
parent 9f0cd51cab
commit 23cf4376f5
70 changed files with 1954 additions and 278 deletions

View File

@ -1716,6 +1716,10 @@ pub struct ConnectorWalletDetails {
#[serde(skip_serializing_if = "Option::is_none")]
#[schema(value_type = Option<Object>)]
pub apple_pay: Option<pii::SecretSerdeValue>,
/// This field contains the Amazon Pay certificates and credentials
#[serde(skip_serializing_if = "Option::is_none")]
#[schema(value_type = Option<Object>)]
pub amazon_pay: Option<pii::SecretSerdeValue>,
/// This field contains the Samsung Pay certificates and credentials
#[serde(skip_serializing_if = "Option::is_none")]
#[schema(value_type = Option<Object>)]

View File

@ -24,7 +24,7 @@ use common_utils::{
id_type,
new_type::MaskedBankAccount,
pii::{self, Email},
types::{MinorUnit, StringMajorUnit},
types::{AmountConvertor, MinorUnit, StringMajorUnit},
};
use error_stack::ResultExt;
@ -2856,7 +2856,9 @@ impl GetPaymentMethodType for WalletData {
Self::BluecodeRedirect {} => api_enums::PaymentMethodType::Bluecode,
Self::AliPayQr(_) | Self::AliPayRedirect(_) => api_enums::PaymentMethodType::AliPay,
Self::AliPayHkRedirect(_) => api_enums::PaymentMethodType::AliPayHk,
Self::AmazonPayRedirect(_) => api_enums::PaymentMethodType::AmazonPay,
Self::AmazonPay(_) | Self::AmazonPayRedirect(_) => {
api_enums::PaymentMethodType::AmazonPay
}
Self::Skrill(_) => api_enums::PaymentMethodType::Skrill,
Self::Paysera(_) => api_enums::PaymentMethodType::Paysera,
Self::MomoRedirect(_) => api_enums::PaymentMethodType::Momo,
@ -3816,6 +3818,8 @@ pub enum WalletData {
AliPayRedirect(AliPayRedirection),
/// The wallet data for Ali Pay HK redirect
AliPayHkRedirect(AliPayHkRedirection),
/// The wallet data for Amazon Pay
AmazonPay(AmazonPayWalletData),
/// The wallet data for Amazon Pay redirect
AmazonPayRedirect(AmazonPayRedirectData),
/// The wallet data for Bluecode QR Code Redirect
@ -3909,6 +3913,7 @@ impl GetAddressFromPaymentMethodData for WalletData {
| Self::KakaoPayRedirect(_)
| Self::GoPayRedirect(_)
| Self::GcashRedirect(_)
| Self::AmazonPay(_)
| Self::AmazonPayRedirect(_)
| Self::Skrill(_)
| Self::Paysera(_)
@ -4069,6 +4074,20 @@ pub struct GooglePayWalletData {
pub tokenization_data: common_types::payments::GpayTokenizationData,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct AmazonPaySessionTokenData {
#[serde(rename = "amazon_pay")]
pub data: AmazonPayMerchantCredentials,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct AmazonPayMerchantCredentials {
/// Amazon Pay merchant account identifier
pub merchant_id: String,
/// Amazon Pay store ID
pub store_id: String,
}
#[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)]
pub struct ApplePayRedirectData {}
@ -4185,6 +4204,12 @@ pub struct MifinityData {
pub language_preference: Option<String>,
}
#[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)]
pub struct AmazonPayWalletData {
/// Checkout Session identifier
pub checkout_session_id: String,
}
#[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)]
pub struct ApplePayWalletData {
/// The payment data of Apple pay
@ -7445,6 +7470,8 @@ pub enum SessionToken {
Paze(Box<PazeSessionTokenResponse>),
/// The sessions response structure for ClickToPay
ClickToPay(Box<ClickToPaySessionResponse>),
/// The session response structure for Amazon Pay
AmazonPay(Box<AmazonPaySessionTokenResponse>),
/// Whenever there is no session token response or an error in session response
NoSessionTokenReceived,
}
@ -7848,6 +7875,135 @@ pub struct ApplepayErrorResponse {
pub status_message: String,
}
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, ToSchema)]
pub struct AmazonPaySessionTokenResponse {
/// Amazon Pay merchant account identifier
pub merchant_id: String,
/// Ledger currency provided during registration for the given merchant identifier
#[schema(example = "USD", value_type = Currency)]
pub ledger_currency: common_enums::Currency,
/// Amazon Pay store ID
pub store_id: String,
/// Payment flow for charging the buyer
pub payment_intent: AmazonPayPaymentIntent,
/// The total shipping costs
#[schema(value_type = String)]
pub total_shipping_amount: StringMajorUnit,
/// The total tax amount for the order
#[schema(value_type = String)]
pub total_tax_amount: StringMajorUnit,
/// The total amount for items in the cart
#[schema(value_type = String)]
pub total_base_amount: StringMajorUnit,
/// The delivery options available for the provided address
pub delivery_options: Vec<AmazonPayDeliveryOptions>,
}
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, ToSchema)]
pub enum AmazonPayPaymentIntent {
/// Create a Charge Permission to authorize and capture funds at a later time
Confirm,
/// Authorize funds immediately and capture at a later time
Authorize,
/// Authorize and capture funds immediately
AuthorizeWithCapture,
}
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct AmazonPayDeliveryOptions {
/// Delivery Option identifier
pub id: String,
/// Total delivery cost
pub price: AmazonPayDeliveryPrice,
/// Shipping method details
pub shipping_method: AmazonPayShippingMethod,
/// Specifies if this delivery option is the default
pub is_default: bool,
}
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct AmazonPayDeliveryPrice {
/// Transaction amount in MinorUnit
pub amount: MinorUnit,
#[serde(skip_deserializing)]
/// Transaction amount in StringMajorUnit
#[schema(value_type = String)]
pub display_amount: StringMajorUnit,
/// Transaction currency code in ISO 4217 format
#[schema(example = "USD", value_type = Currency)]
pub currency_code: common_enums::Currency,
}
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct AmazonPayShippingMethod {
/// Name of the shipping method
pub shipping_method_name: String,
/// Code of the shipping method
pub shipping_method_code: String,
}
impl AmazonPayDeliveryOptions {
pub fn parse_delivery_options_request(
delivery_options_request: &[serde_json::Value],
) -> Result<Vec<Self>, common_utils::errors::ParsingError> {
delivery_options_request
.iter()
.map(|option| {
serde_json::from_value(option.clone()).map_err(|_| {
common_utils::errors::ParsingError::StructParseFailure(
"AmazonPayDeliveryOptions",
)
})
})
.collect()
}
pub fn get_default_delivery_amount(
delivery_options: Vec<Self>,
) -> Result<MinorUnit, error_stack::Report<ValidationError>> {
let mut default_options = delivery_options
.into_iter()
.filter(|delivery_option| delivery_option.is_default);
match (default_options.next(), default_options.next()) {
(Some(default_option), None) => Ok(default_option.price.amount),
_ => Err(ValidationError::InvalidValue {
message: "Amazon Pay Delivery Option".to_string(),
})
.attach_printable("Expected exactly one default Amazon Pay Delivery Option"),
}
}
pub fn validate_currency(
currency_code: common_enums::Currency,
amazonpay_supported_currencies: HashSet<common_enums::Currency>,
) -> Result<(), ValidationError> {
if !amazonpay_supported_currencies.contains(&currency_code) {
return Err(ValidationError::InvalidValue {
message: format!("{currency_code:?} is not a supported currency."),
});
}
Ok(())
}
pub fn insert_display_amount(
delivery_options: &mut Vec<Self>,
currency_code: common_enums::Currency,
) -> Result<(), error_stack::Report<common_utils::errors::ParsingError>> {
let required_amount_type = common_utils::types::StringMajorUnitForCore;
for option in delivery_options {
let display_amount = required_amount_type
.convert(option.price.amount, currency_code)
.change_context(common_utils::errors::ParsingError::I64ToStringConversionFailure)?;
option.price.display_amount = display_amount;
}
Ok(())
}
}
#[cfg(feature = "v1")]
#[derive(Default, Debug, serde::Serialize, Clone, ToSchema)]
pub struct PaymentsSessionResponse {