diff --git a/api-reference-v2/openapi_spec.json b/api-reference-v2/openapi_spec.json index 58a81caeed3a..c8a87f1a6174 100644 --- a/api-reference-v2/openapi_spec.json +++ b/api-reference-v2/openapi_spec.json @@ -11854,70 +11854,6 @@ } } }, - "OrderDetails": { - "type": "object", - "required": [ - "product_name", - "quantity" - ], - "properties": { - "product_name": { - "type": "string", - "description": "Name of the product that is being purchased", - "example": "shirt", - "maxLength": 255 - }, - "quantity": { - "type": "integer", - "format": "int32", - "description": "The quantity of the product to be purchased", - "example": 1, - "minimum": 0 - }, - "requires_shipping": { - "type": "boolean", - "nullable": true - }, - "product_img_link": { - "type": "string", - "description": "The image URL of the product", - "nullable": true - }, - "product_id": { - "type": "string", - "description": "ID of the product that is being purchased", - "nullable": true - }, - "category": { - "type": "string", - "description": "Category of the product that is being purchased", - "nullable": true - }, - "sub_category": { - "type": "string", - "description": "Sub category of the product that is being purchased", - "nullable": true - }, - "brand": { - "type": "string", - "description": "Brand of the product that is being purchased", - "nullable": true - }, - "product_type": { - "allOf": [ - { - "$ref": "#/components/schemas/ProductType" - } - ], - "nullable": true - }, - "product_tax_code": { - "type": "string", - "description": "The tax code for the product", - "nullable": true - } - } - }, "OrderDetailsWithAmount": { "type": "object", "required": [ @@ -11940,7 +11876,21 @@ "minimum": 0 }, "amount": { - "$ref": "#/components/schemas/MinorUnit" + "type": "integer", + "format": "int64", + "description": "the amount per quantity of product" + }, + "tax_rate": { + "type": "number", + "format": "double", + "description": "tax rate applicable to the product", + "nullable": true + }, + "total_tax_amount": { + "type": "integer", + "format": "int64", + "description": "total tax amount applicable to the product", + "nullable": true }, "requires_shipping": { "type": "boolean", @@ -12353,6 +12303,17 @@ } } }, + { + "type": "object", + "required": [ + "klarna_checkout" + ], + "properties": { + "klarna_checkout": { + "type": "object" + } + } + }, { "type": "object", "required": [ @@ -12486,6 +12447,13 @@ "description": "The payment attempt amount. Amount for the payment in lowest denomination of the currency. (i.e) in cents for USD denomination, in paisa for INR denomination etc.,", "example": 6540 }, + "order_tax_amount": { + "type": "integer", + "format": "int64", + "description": "The payment attempt tax_amount.", + "example": 6540, + "nullable": true + }, "currency": { "allOf": [ { diff --git a/api-reference/openapi_spec.json b/api-reference/openapi_spec.json index 33dd5d87a473..57e4ac1948a4 100644 --- a/api-reference/openapi_spec.json +++ b/api-reference/openapi_spec.json @@ -14732,70 +14732,6 @@ } } }, - "OrderDetails": { - "type": "object", - "required": [ - "product_name", - "quantity" - ], - "properties": { - "product_name": { - "type": "string", - "description": "Name of the product that is being purchased", - "example": "shirt", - "maxLength": 255 - }, - "quantity": { - "type": "integer", - "format": "int32", - "description": "The quantity of the product to be purchased", - "example": 1, - "minimum": 0 - }, - "requires_shipping": { - "type": "boolean", - "nullable": true - }, - "product_img_link": { - "type": "string", - "description": "The image URL of the product", - "nullable": true - }, - "product_id": { - "type": "string", - "description": "ID of the product that is being purchased", - "nullable": true - }, - "category": { - "type": "string", - "description": "Category of the product that is being purchased", - "nullable": true - }, - "sub_category": { - "type": "string", - "description": "Sub category of the product that is being purchased", - "nullable": true - }, - "brand": { - "type": "string", - "description": "Brand of the product that is being purchased", - "nullable": true - }, - "product_type": { - "allOf": [ - { - "$ref": "#/components/schemas/ProductType" - } - ], - "nullable": true - }, - "product_tax_code": { - "type": "string", - "description": "The tax code for the product", - "nullable": true - } - } - }, "OrderDetailsWithAmount": { "type": "object", "required": [ @@ -14818,7 +14754,21 @@ "minimum": 0 }, "amount": { - "$ref": "#/components/schemas/MinorUnit" + "type": "integer", + "format": "int64", + "description": "the amount per quantity of product" + }, + "tax_rate": { + "type": "number", + "format": "double", + "description": "tax rate applicable to the product", + "nullable": true + }, + "total_tax_amount": { + "type": "integer", + "format": "int64", + "description": "total tax amount applicable to the product", + "nullable": true }, "requires_shipping": { "type": "boolean", @@ -15224,6 +15174,17 @@ } } }, + { + "type": "object", + "required": [ + "klarna_checkout" + ], + "properties": { + "klarna_checkout": { + "type": "object" + } + } + }, { "type": "object", "required": [ @@ -15357,6 +15318,13 @@ "description": "The payment attempt amount. Amount for the payment in lowest denomination of the currency. (i.e) in cents for USD denomination, in paisa for INR denomination etc.,", "example": 6540 }, + "order_tax_amount": { + "type": "integer", + "format": "int64", + "description": "The payment attempt tax_amount.", + "example": 6540, + "nullable": true + }, "currency": { "allOf": [ { @@ -17155,6 +17123,13 @@ "nullable": true, "minimum": 0 }, + "order_tax_amount": { + "type": "integer", + "format": "int64", + "description": "Total tax amount applicable to the order", + "example": 6540, + "nullable": true + }, "currency": { "allOf": [ { @@ -17533,6 +17508,13 @@ "description": "The payment amount. Amount for the payment in the lowest denomination of the currency, (i.e) in cents for USD denomination, in yen for JPY denomination etc. E.g., Pass 100 to charge $1.00 and 1 for 1¥ since ¥ is a zero-decimal currency. Read more about [the Decimal and Non-Decimal Currencies](https://github.com/juspay/hyperswitch/wiki/Decimal-and-Non%E2%80%90Decimal-Currencies)", "minimum": 0 }, + "order_tax_amount": { + "type": "integer", + "format": "int64", + "description": "Total tax amount applicable to the order", + "example": 6540, + "nullable": true + }, "currency": { "$ref": "#/components/schemas/Currency" }, @@ -18659,6 +18641,13 @@ "nullable": true, "minimum": 0 }, + "order_tax_amount": { + "type": "integer", + "format": "int64", + "description": "Total tax amount applicable to the order", + "example": 6540, + "nullable": true + }, "currency": { "allOf": [ { @@ -19805,6 +19794,13 @@ "nullable": true, "minimum": 0 }, + "order_tax_amount": { + "type": "integer", + "format": "int64", + "description": "Total tax amount applicable to the order", + "example": 6540, + "nullable": true + }, "currency": { "allOf": [ { diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index 0381e347f4f1..632d40a09519 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -741,6 +741,10 @@ pub struct PaymentsRequest { // Makes the field mandatory in PaymentsCreateRequest pub amount: Option, + /// Total tax amount applicable to the order + #[schema(value_type = Option, example = 6540)] + pub order_tax_amount: Option, + /// The three letter ISO currency code in uppercase. Eg: 'USD' to charge US Dollars #[schema(example = "USD", value_type = Option)] #[mandatory_in(PaymentsCreateRequest = Currency)] @@ -1308,6 +1312,9 @@ pub struct PaymentAttemptResponse { /// The payment attempt amount. Amount for the payment in lowest denomination of the currency. (i.e) in cents for USD denomination, in paisa for INR denomination etc., #[schema(value_type = i64, example = 6540)] pub amount: MinorUnit, + /// The payment attempt tax_amount. + #[schema(value_type = Option, example = 6540)] + pub order_tax_amount: Option, /// The currency of the amount of the payment attempt #[schema(value_type = Option, example = "USD")] pub currency: Option, @@ -1858,6 +1865,7 @@ pub enum PayLaterData { /// The token for the sdk workflow token: String, }, + KlarnaCheckout {}, /// For Affirm redirect as PayLater Option AffirmRedirect {}, /// For AfterpayClearpay redirect as PayLater Option @@ -1915,6 +1923,7 @@ impl GetAddressFromPaymentMethodData for PayLaterData { | Self::WalleyRedirect {} | Self::AlmaRedirect {} | Self::KlarnaSdk { .. } + | Self::KlarnaCheckout {} | Self::AffirmRedirect {} | Self::AtomeRedirect {} => None, } @@ -2376,6 +2385,7 @@ impl GetPaymentMethodType for PayLaterData { match self { Self::KlarnaRedirect { .. } => api_enums::PaymentMethodType::Klarna, Self::KlarnaSdk { .. } => api_enums::PaymentMethodType::Klarna, + Self::KlarnaCheckout {} => api_enums::PaymentMethodType::Klarna, Self::AffirmRedirect {} => api_enums::PaymentMethodType::Affirm, Self::AfterpayClearpayRedirect { .. } => api_enums::PaymentMethodType::AfterpayClearpay, Self::PayBrightRedirect {} => api_enums::PaymentMethodType::PayBright, @@ -5471,7 +5481,7 @@ pub struct PaymentsRetrieveRequest { pub expand_attempts: Option, } -#[derive(Debug, Default, Eq, PartialEq, serde::Deserialize, serde::Serialize, Clone, ToSchema)] +#[derive(Debug, Default, PartialEq, serde::Deserialize, serde::Serialize, Clone, ToSchema)] pub struct OrderDetailsWithAmount { /// Name of the product that is being purchased #[schema(max_length = 255, example = "shirt")] @@ -5480,7 +5490,13 @@ pub struct OrderDetailsWithAmount { #[schema(example = 1)] pub quantity: u16, /// the amount per quantity of product + #[schema(value_type = i64)] pub amount: MinorUnit, + /// tax rate applicable to the product + pub tax_rate: Option, + /// total tax amount applicable to the product + #[schema(value_type = Option)] + pub total_tax_amount: Option, // Does the order includes shipping pub requires_shipping: Option, /// The image URL of the product @@ -5501,32 +5517,6 @@ pub struct OrderDetailsWithAmount { impl masking::SerializableSecret for OrderDetailsWithAmount {} -#[derive(Debug, Default, Eq, PartialEq, serde::Deserialize, serde::Serialize, Clone, ToSchema)] -pub struct OrderDetails { - /// Name of the product that is being purchased - #[schema(max_length = 255, example = "shirt")] - pub product_name: String, - /// The quantity of the product to be purchased - #[schema(example = 1)] - pub quantity: u16, - // Does the order include shipping - pub requires_shipping: Option, - /// The image URL of the product - pub product_img_link: Option, - /// ID of the product that is being purchased - pub product_id: Option, - /// Category of the product that is being purchased - pub category: Option, - /// Sub category of the product that is being purchased - pub sub_category: Option, - /// Brand of the product that is being purchased - pub brand: Option, - /// Type of the product that is being purchased - pub product_type: Option, - /// The tax code for the product - pub product_tax_code: Option, -} - #[derive(Default, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, Clone, ToSchema)] pub struct RedirectResponse { #[schema(value_type = Option)] diff --git a/crates/diesel_models/src/types.rs b/crates/diesel_models/src/types.rs index 94f1fa8d2664..6562abab4d6a 100644 --- a/crates/diesel_models/src/types.rs +++ b/crates/diesel_models/src/types.rs @@ -30,6 +30,10 @@ pub struct OrderDetailsWithAmount { pub product_type: Option, /// The tax code for the product pub product_tax_code: Option, + /// tax rate applicable to the product + pub tax_rate: Option, + /// total tax amount applicable to the product + pub total_tax_amount: Option, } impl masking::SerializableSecret for OrderDetailsWithAmount {} diff --git a/crates/hyperswitch_connectors/src/connectors/multisafepay/transformers.rs b/crates/hyperswitch_connectors/src/connectors/multisafepay/transformers.rs index 479abf13b13a..a60e8bdc79ed 100644 --- a/crates/hyperswitch_connectors/src/connectors/multisafepay/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/multisafepay/transformers.rs @@ -746,6 +746,7 @@ impl TryFrom<&MultisafepayRouterData<&types::PaymentsAuthorizeRouterData>> email: Some(match paylater { PayLaterData::KlarnaRedirect {} => item.router_data.get_billing_email()?, PayLaterData::KlarnaSdk { token: _ } + | PayLaterData::KlarnaCheckout {} | PayLaterData::AffirmRedirect {} | PayLaterData::AfterpayClearpayRedirect {} | PayLaterData::PayBrightRedirect {} diff --git a/crates/hyperswitch_connectors/src/connectors/square/transformers.rs b/crates/hyperswitch_connectors/src/connectors/square/transformers.rs index 08ca9a54fa41..5abc93b3f882 100644 --- a/crates/hyperswitch_connectors/src/connectors/square/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/square/transformers.rs @@ -85,6 +85,7 @@ impl TryFrom<(&types::TokenizationRouterData, PayLaterData)> for SquareTokenRequ PayLaterData::AfterpayClearpayRedirect { .. } | PayLaterData::KlarnaRedirect { .. } | PayLaterData::KlarnaSdk { .. } + | PayLaterData::KlarnaCheckout {} | PayLaterData::AffirmRedirect { .. } | PayLaterData::PayBrightRedirect { .. } | PayLaterData::WalleyRedirect { .. } diff --git a/crates/hyperswitch_connectors/src/connectors/zen/transformers.rs b/crates/hyperswitch_connectors/src/connectors/zen/transformers.rs index 7a30a434a5d7..41dc60f8248e 100644 --- a/crates/hyperswitch_connectors/src/connectors/zen/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/zen/transformers.rs @@ -751,6 +751,7 @@ impl TryFrom<&PayLaterData> for ZenPaymentsRequest { match value { PayLaterData::KlarnaRedirect { .. } | PayLaterData::KlarnaSdk { .. } + | PayLaterData::KlarnaCheckout {} | PayLaterData::AffirmRedirect {} | PayLaterData::AfterpayClearpayRedirect { .. } | PayLaterData::PayBrightRedirect {} diff --git a/crates/hyperswitch_connectors/src/utils.rs b/crates/hyperswitch_connectors/src/utils.rs index 6dce48e69965..cf32d966e056 100644 --- a/crates/hyperswitch_connectors/src/utils.rs +++ b/crates/hyperswitch_connectors/src/utils.rs @@ -2092,6 +2092,7 @@ pub enum PaymentMethodDataType { SwishQr, KlarnaRedirect, KlarnaSdk, + KlarnaCheckout, AffirmRedirect, AfterpayClearpayRedirect, PayBrightRedirect, @@ -2216,6 +2217,7 @@ impl From for PaymentMethodDataType { PaymentMethodData::PayLater(pay_later_data) => match pay_later_data { payment_method_data::PayLaterData::KlarnaRedirect { .. } => Self::KlarnaRedirect, payment_method_data::PayLaterData::KlarnaSdk { .. } => Self::KlarnaSdk, + payment_method_data::PayLaterData::KlarnaCheckout {} => Self::KlarnaCheckout, payment_method_data::PayLaterData::AffirmRedirect {} => Self::AffirmRedirect, payment_method_data::PayLaterData::AfterpayClearpayRedirect { .. } => { Self::AfterpayClearpayRedirect diff --git a/crates/hyperswitch_domain_models/src/lib.rs b/crates/hyperswitch_domain_models/src/lib.rs index 0e8722644bd4..6e353afd399e 100644 --- a/crates/hyperswitch_domain_models/src/lib.rs +++ b/crates/hyperswitch_domain_models/src/lib.rs @@ -133,6 +133,8 @@ impl ApiModelToDieselModelConvertor for OrderDetailsW brand, product_type, product_tax_code, + tax_rate, + total_tax_amount, } = from; Self { product_name, @@ -146,6 +148,8 @@ impl ApiModelToDieselModelConvertor for OrderDetailsW brand, product_type, product_tax_code, + tax_rate, + total_tax_amount, } } @@ -162,6 +166,8 @@ impl ApiModelToDieselModelConvertor for OrderDetailsW brand, product_type, product_tax_code, + tax_rate, + total_tax_amount, } = self; ApiOrderDetailsWithAmount { product_name, @@ -175,6 +181,8 @@ impl ApiModelToDieselModelConvertor for OrderDetailsW brand, product_type, product_tax_code, + tax_rate, + total_tax_amount, } } } diff --git a/crates/hyperswitch_domain_models/src/payment_method_data.rs b/crates/hyperswitch_domain_models/src/payment_method_data.rs index 169719cb5dad..8c19a20ef322 100644 --- a/crates/hyperswitch_domain_models/src/payment_method_data.rs +++ b/crates/hyperswitch_domain_models/src/payment_method_data.rs @@ -155,6 +155,7 @@ pub enum CardRedirectData { pub enum PayLaterData { KlarnaRedirect {}, KlarnaSdk { token: String }, + KlarnaCheckout {}, AffirmRedirect {}, AfterpayClearpayRedirect {}, PayBrightRedirect {}, @@ -897,6 +898,7 @@ impl From for PayLaterData { match value { api_models::payments::PayLaterData::KlarnaRedirect { .. } => Self::KlarnaRedirect {}, api_models::payments::PayLaterData::KlarnaSdk { token } => Self::KlarnaSdk { token }, + api_models::payments::PayLaterData::KlarnaCheckout {} => Self::KlarnaCheckout {}, api_models::payments::PayLaterData::AffirmRedirect {} => Self::AffirmRedirect {}, api_models::payments::PayLaterData::AfterpayClearpayRedirect { .. } => { Self::AfterpayClearpayRedirect {} @@ -1550,6 +1552,7 @@ impl GetPaymentMethodType for PayLaterData { match self { Self::KlarnaRedirect { .. } => api_enums::PaymentMethodType::Klarna, Self::KlarnaSdk { .. } => api_enums::PaymentMethodType::Klarna, + Self::KlarnaCheckout {} => api_enums::PaymentMethodType::Klarna, Self::AffirmRedirect {} => api_enums::PaymentMethodType::Affirm, Self::AfterpayClearpayRedirect { .. } => api_enums::PaymentMethodType::AfterpayClearpay, Self::PayBrightRedirect {} => api_enums::PaymentMethodType::PayBright, diff --git a/crates/hyperswitch_domain_models/src/router_request_types.rs b/crates/hyperswitch_domain_models/src/router_request_types.rs index 2f68b481d881..0e25e195c734 100644 --- a/crates/hyperswitch_domain_models/src/router_request_types.rs +++ b/crates/hyperswitch_domain_models/src/router_request_types.rs @@ -29,6 +29,7 @@ pub struct PaymentsAuthorizeData { /// get_total_surcharge_amount() // returns surcharge_amount + tax_on_surcharge_amount /// ``` pub amount: i64, + pub order_tax_amount: Option, pub email: Option, pub customer_name: Option>, pub currency: storage_enums::Currency, diff --git a/crates/openapi/src/openapi.rs b/crates/openapi/src/openapi.rs index 65c76f8929f2..03c280318691 100644 --- a/crates/openapi/src/openapi.rs +++ b/crates/openapi/src/openapi.rs @@ -381,7 +381,6 @@ Never share your secret api keys. Keep them guarded and secure. api_models::payments::SwishQrData, api_models::payments::AirwallexData, api_models::payments::NoonData, - api_models::payments::OrderDetails, api_models::payments::OrderDetailsWithAmount, api_models::payments::NextActionType, api_models::payments::WalletData, diff --git a/crates/openapi/src/openapi_v2.rs b/crates/openapi/src/openapi_v2.rs index b5de979b3aef..c9e4595ef492 100644 --- a/crates/openapi/src/openapi_v2.rs +++ b/crates/openapi/src/openapi_v2.rs @@ -341,7 +341,6 @@ Never share your secret api keys. Keep them guarded and secure. api_models::payments::SwishQrData, api_models::payments::AirwallexData, api_models::payments::NoonData, - api_models::payments::OrderDetails, api_models::payments::OrderDetailsWithAmount, api_models::payments::NextActionType, api_models::payments::WalletData, diff --git a/crates/router/src/connector/adyen/transformers.rs b/crates/router/src/connector/adyen/transformers.rs index d0dad91f7170..aece1df65463 100644 --- a/crates/router/src/connector/adyen/transformers.rs +++ b/crates/router/src/connector/adyen/transformers.rs @@ -2350,7 +2350,8 @@ impl check_required_field(billing_address, "billing")?; Ok(AdyenPaymentMethod::Atome) } - domain::payments::PayLaterData::KlarnaSdk { .. } => { + domain::payments::PayLaterData::KlarnaCheckout {} + | domain::payments::PayLaterData::KlarnaSdk { .. } => { Err(errors::ConnectorError::NotImplemented( utils::get_unimplemented_payment_method_error_message("Adyen"), ) diff --git a/crates/router/src/connector/klarna.rs b/crates/router/src/connector/klarna.rs index d2bdaae0493d..77e2a027d835 100644 --- a/crates/router/src/connector/klarna.rs +++ b/crates/router/src/connector/klarna.rs @@ -448,7 +448,24 @@ impl let endpoint = build_region_specific_endpoint(self.base_url(connectors), &req.connector_meta_data)?; - Ok(format!("{endpoint}ordermanagement/v1/orders/{order_id}")) + let payment_experience = req.request.payment_experience; + + match payment_experience { + Some(common_enums::PaymentExperience::InvokeSdkClient) => { + Ok(format!("{endpoint}ordermanagement/v1/orders/{order_id}")) + } + Some(common_enums::PaymentExperience::RedirectToUrl) => { + Ok(format!("{endpoint}checkout/v3/orders/{order_id}")) + } + None => Err(error_stack::report!(errors::ConnectorError::NotSupported { + message: "payment_experience not supported".to_string(), + connector: "klarna", + })), + _ => Err(error_stack::report!(errors::ConnectorError::NotSupported { + message: "payment_experience not supported".to_string(), + connector: "klarna", + })), + } } fn build_request( @@ -653,6 +670,122 @@ impl })), } } + domain::PaymentMethodData::PayLater(domain::PayLaterData::KlarnaCheckout {}) => { + match (payment_experience, payment_method_type) { + ( + common_enums::PaymentExperience::RedirectToUrl, + common_enums::PaymentMethodType::Klarna, + ) => Ok(format!("{endpoint}checkout/v3/orders",)), + ( + common_enums::PaymentExperience::DisplayQrCode + | common_enums::PaymentExperience::DisplayWaitScreen + | common_enums::PaymentExperience::InvokePaymentApp + | common_enums::PaymentExperience::InvokeSdkClient + | common_enums::PaymentExperience::LinkWallet + | common_enums::PaymentExperience::OneClick + | common_enums::PaymentExperience::RedirectToUrl + | common_enums::PaymentExperience::CollectOtp, + common_enums::PaymentMethodType::Ach + | common_enums::PaymentMethodType::Affirm + | common_enums::PaymentMethodType::AfterpayClearpay + | common_enums::PaymentMethodType::Alfamart + | common_enums::PaymentMethodType::AliPay + | common_enums::PaymentMethodType::AliPayHk + | common_enums::PaymentMethodType::Alma + | common_enums::PaymentMethodType::ApplePay + | common_enums::PaymentMethodType::Atome + | common_enums::PaymentMethodType::Bacs + | common_enums::PaymentMethodType::BancontactCard + | common_enums::PaymentMethodType::Becs + | common_enums::PaymentMethodType::Benefit + | common_enums::PaymentMethodType::Bizum + | common_enums::PaymentMethodType::Blik + | common_enums::PaymentMethodType::Boleto + | common_enums::PaymentMethodType::BcaBankTransfer + | common_enums::PaymentMethodType::BniVa + | common_enums::PaymentMethodType::BriVa + | common_enums::PaymentMethodType::CardRedirect + | common_enums::PaymentMethodType::CimbVa + | common_enums::PaymentMethodType::ClassicReward + | common_enums::PaymentMethodType::Credit + | common_enums::PaymentMethodType::CryptoCurrency + | common_enums::PaymentMethodType::Cashapp + | common_enums::PaymentMethodType::Dana + | common_enums::PaymentMethodType::DanamonVa + | common_enums::PaymentMethodType::Debit + | common_enums::PaymentMethodType::DirectCarrierBilling + | common_enums::PaymentMethodType::Efecty + | common_enums::PaymentMethodType::Eps + | common_enums::PaymentMethodType::Evoucher + | common_enums::PaymentMethodType::Giropay + | common_enums::PaymentMethodType::Givex + | common_enums::PaymentMethodType::GooglePay + | common_enums::PaymentMethodType::GoPay + | common_enums::PaymentMethodType::Gcash + | common_enums::PaymentMethodType::Ideal + | common_enums::PaymentMethodType::Interac + | common_enums::PaymentMethodType::Indomaret + | common_enums::PaymentMethodType::Klarna + | common_enums::PaymentMethodType::KakaoPay + | common_enums::PaymentMethodType::MandiriVa + | common_enums::PaymentMethodType::Knet + | common_enums::PaymentMethodType::MbWay + | common_enums::PaymentMethodType::MobilePay + | common_enums::PaymentMethodType::Momo + | common_enums::PaymentMethodType::MomoAtm + | common_enums::PaymentMethodType::Multibanco + | common_enums::PaymentMethodType::LocalBankRedirect + | common_enums::PaymentMethodType::OnlineBankingThailand + | common_enums::PaymentMethodType::OnlineBankingCzechRepublic + | common_enums::PaymentMethodType::OnlineBankingFinland + | common_enums::PaymentMethodType::OnlineBankingFpx + | common_enums::PaymentMethodType::OnlineBankingPoland + | common_enums::PaymentMethodType::OnlineBankingSlovakia + | common_enums::PaymentMethodType::Oxxo + | common_enums::PaymentMethodType::PagoEfectivo + | common_enums::PaymentMethodType::PermataBankTransfer + | common_enums::PaymentMethodType::OpenBankingUk + | common_enums::PaymentMethodType::PayBright + | common_enums::PaymentMethodType::Paypal + | common_enums::PaymentMethodType::Paze + | common_enums::PaymentMethodType::Pix + | common_enums::PaymentMethodType::PaySafeCard + | common_enums::PaymentMethodType::Przelewy24 + | common_enums::PaymentMethodType::Pse + | common_enums::PaymentMethodType::RedCompra + | common_enums::PaymentMethodType::RedPagos + | common_enums::PaymentMethodType::SamsungPay + | common_enums::PaymentMethodType::Sepa + | common_enums::PaymentMethodType::Sofort + | common_enums::PaymentMethodType::Swish + | common_enums::PaymentMethodType::TouchNGo + | common_enums::PaymentMethodType::Trustly + | common_enums::PaymentMethodType::Twint + | common_enums::PaymentMethodType::UpiCollect + | common_enums::PaymentMethodType::UpiIntent + | common_enums::PaymentMethodType::Venmo + | common_enums::PaymentMethodType::Vipps + | common_enums::PaymentMethodType::Walley + | common_enums::PaymentMethodType::WeChatPay + | common_enums::PaymentMethodType::SevenEleven + | common_enums::PaymentMethodType::Lawson + | common_enums::PaymentMethodType::LocalBankTransfer + | common_enums::PaymentMethodType::MiniStop + | common_enums::PaymentMethodType::FamilyMart + | common_enums::PaymentMethodType::Seicomart + | common_enums::PaymentMethodType::PayEasy + | common_enums::PaymentMethodType::Mifinity + | common_enums::PaymentMethodType::Fps + | common_enums::PaymentMethodType::DuitNow + | common_enums::PaymentMethodType::PromptPay + | common_enums::PaymentMethodType::VietQr + | common_enums::PaymentMethodType::OpenBankingPIS, + ) => Err(error_stack::report!(errors::ConnectorError::NotSupported { + message: payment_method_type.to_string(), + connector: "klarna", + })), + } + } domain::PaymentMethodData::Card(_) | domain::PaymentMethodData::CardRedirect(_) @@ -726,7 +859,7 @@ impl event_builder: Option<&mut ConnectorEvent>, res: Response, ) -> CustomResult { - let response: klarna::KlarnaPaymentsResponse = res + let response: klarna::KlarnaAuthResponse = res .response .parse_struct("KlarnaPaymentsResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; diff --git a/crates/router/src/connector/klarna/transformers.rs b/crates/router/src/connector/klarna/transformers.rs index 803dc4a428d2..0826b0f2665b 100644 --- a/crates/router/src/connector/klarna/transformers.rs +++ b/crates/router/src/connector/klarna/transformers.rs @@ -1,7 +1,9 @@ use api_models::payments; use common_utils::{pii, types::MinorUnit}; use error_stack::{report, ResultExt}; -use hyperswitch_domain_models::router_data::KlarnaSdkResponse; +use hyperswitch_domain_models::{ + router_data::KlarnaSdkResponse, router_response_types::RedirectForm, +}; use masking::{ExposeInterface, Secret}; use serde::{Deserialize, Serialize}; @@ -10,7 +12,7 @@ use crate::{ self, AddressData, AddressDetailsData, PaymentsAuthorizeRequestData, RouterData, }, core::errors, - types::{self, api, storage::enums, transformers::ForeignFrom}, + types::{self, api, domain, storage::enums, transformers::ForeignFrom}, }; #[derive(Debug, Serialize)] @@ -61,9 +63,29 @@ impl TryFrom<&Option> for KlarnaConnectorMetadataObject { } } -#[derive(Default, Debug, Serialize)] +#[derive(Debug, Serialize, Deserialize)] +#[serde(untagged)] +pub enum PaymentMethodSpecifics { + KlarnaCheckout(KlarnaCheckoutRequestData), + KlarnaSdk, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +pub struct MerchantURLs { + terms: String, + checkout: String, + confirmation: String, + push: String, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +pub struct KlarnaCheckoutRequestData { + merchant_urls: MerchantURLs, + options: CheckoutOptions, +} + +#[derive(Default, Debug, Deserialize, Serialize)] pub struct KlarnaPaymentsRequest { - auto_capture: bool, order_lines: Vec, order_amount: MinorUnit, purchase_country: enums::CountryAlpha2, @@ -71,15 +93,32 @@ pub struct KlarnaPaymentsRequest { merchant_reference1: Option, merchant_reference2: Option, shipping_address: Option, + auto_capture: Option, + order_tax_amount: Option, + #[serde(flatten)] + payment_method_specifics: Option, } #[derive(Debug, Deserialize, Serialize)] -pub struct KlarnaPaymentsResponse { +#[serde(untagged)] +pub enum KlarnaAuthResponse { + KlarnaPaymentsAuthResponse(PaymentsResponse), + KlarnaCheckoutAuthResponse(CheckoutResponse), +} + +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct PaymentsResponse { order_id: String, fraud_status: KlarnaFraudStatus, authorized_payment_method: Option, } +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct CheckoutResponse { + order_id: String, + status: KlarnaCheckoutStatus, + html_snippet: String, +} #[derive(Debug, Clone, Deserialize, Serialize)] pub struct AuthorizedPaymentMethod { #[serde(rename = "type")] @@ -106,7 +145,7 @@ pub struct KlarnaSessionRequest { shipping_address: Option, } -#[derive(Debug, Serialize)] +#[derive(Debug, Serialize, Deserialize)] pub struct KlarnaShippingAddress { city: String, country: enums::CountryAlpha2, @@ -120,6 +159,10 @@ pub struct KlarnaShippingAddress { street_address2: Option>, } +#[derive(Default, Debug, Serialize, Deserialize)] +pub struct CheckoutOptions { + auto_capture: bool, +} #[derive(Deserialize, Serialize, Debug)] pub struct KlarnaSessionResponse { pub client_token: Secret, @@ -149,6 +192,8 @@ impl TryFrom<&KlarnaRouterData<&types::PaymentsSessionRouterData>> for KlarnaSes quantity: data.quantity, unit_price: data.amount, total_amount: data.amount * data.quantity, + total_tax_amount: None, + tax_rate: None, }) .collect(), shipping_address: get_address_info(item.router_data.get_optional_shipping()) @@ -190,29 +235,100 @@ impl TryFrom<&KlarnaRouterData<&types::PaymentsAuthorizeRouterData>> for KlarnaP item: &KlarnaRouterData<&types::PaymentsAuthorizeRouterData>, ) -> Result { let request = &item.router_data.request; - match request.order_details.clone() { - Some(order_details) => Ok(Self { - purchase_country: item.router_data.get_billing_country()?, - purchase_currency: request.currency, - order_amount: item.amount, - order_lines: order_details - .iter() - .map(|data| OrderLines { - name: data.product_name.clone(), - quantity: data.quantity, - unit_price: data.amount, - total_amount: data.amount * data.quantity, - }) - .collect(), - merchant_reference1: Some(item.router_data.connector_request_reference_id.clone()), - merchant_reference2: item.router_data.request.merchant_order_reference_id.clone(), - auto_capture: request.is_auto_capture()?, - shipping_address: get_address_info(item.router_data.get_optional_shipping()) - .transpose()?, - }), - None => Err(report!(errors::ConnectorError::MissingRequiredField { - field_name: "order_details" - })), + let payment_method_data = request.payment_method_data.clone(); + let return_url = item.router_data.request.get_return_url()?; + let webhook_url = item.router_data.request.get_webhook_url()?; + match payment_method_data { + domain::PaymentMethodData::PayLater(domain::PayLaterData::KlarnaSdk { .. }) => { + match request.order_details.clone() { + Some(order_details) => Ok(Self { + purchase_country: item.router_data.get_billing_country()?, + purchase_currency: request.currency, + order_amount: item.amount, + order_lines: order_details + .iter() + .map(|data| OrderLines { + name: data.product_name.clone(), + quantity: data.quantity, + unit_price: data.amount, + total_amount: data.amount * data.quantity, + total_tax_amount: None, + tax_rate: None, + }) + .collect(), + merchant_reference1: Some( + item.router_data.connector_request_reference_id.clone(), + ), + merchant_reference2: item + .router_data + .request + .merchant_order_reference_id + .clone(), + auto_capture: Some(request.is_auto_capture()?), + shipping_address: get_address_info( + item.router_data.get_optional_shipping(), + ) + .transpose()?, + order_tax_amount: None, + payment_method_specifics: None, + }), + None => Err(report!(errors::ConnectorError::MissingRequiredField { + field_name: "order_details" + })), + } + } + domain::PaymentMethodData::PayLater(domain::PayLaterData::KlarnaCheckout {}) => { + match request.order_details.clone() { + Some(order_details) => Ok(Self { + purchase_country: item.router_data.get_billing_country()?, + purchase_currency: request.currency, + order_amount: item.amount + - request.order_tax_amount.unwrap_or(MinorUnit::zero()), + order_tax_amount: request.order_tax_amount, + order_lines: order_details + .iter() + .map(|data| OrderLines { + name: data.product_name.clone(), + quantity: data.quantity, + unit_price: data.amount, + total_amount: data.amount * data.quantity, + total_tax_amount: data.total_tax_amount, + tax_rate: data.tax_rate, + }) + .collect(), + payment_method_specifics: Some(PaymentMethodSpecifics::KlarnaCheckout( + KlarnaCheckoutRequestData { + merchant_urls: MerchantURLs { + terms: return_url.clone(), + checkout: return_url.clone(), + confirmation: return_url, + push: webhook_url, + }, + options: CheckoutOptions { + auto_capture: request.is_auto_capture()?, + }, + }, + )), + shipping_address: get_address_info( + item.router_data.get_optional_shipping(), + ) + .transpose()?, + merchant_reference1: Some( + item.router_data.connector_request_reference_id.clone(), + ), + merchant_reference2: item + .router_data + .request + .merchant_order_reference_id + .clone(), + auto_capture: None, + }), + None => Err(report!(errors::ConnectorError::MissingRequiredField { + field_name: "order_details" + })), + } + } + _ => Err(errors::ConnectorError::NotImplemented("Payment method".to_string()).into()), } } } @@ -240,53 +356,82 @@ fn get_address_info( }) } -impl TryFrom> +impl TryFrom> for types::PaymentsAuthorizeRouterData { type Error = error_stack::Report; + fn try_from( - item: types::PaymentsResponseRouterData, + item: types::PaymentsResponseRouterData, ) -> Result { - let connector_response = types::ConnectorResponseData::with_additional_payment_method_data( - match item.response.authorized_payment_method { - Some(authorized_payment_method) => { - types::AdditionalPaymentMethodConnectorResponse::from(authorized_payment_method) - } - None => { - types::AdditionalPaymentMethodConnectorResponse::PayLater { klarna_sdk: None } - } - }, - ); - - Ok(Self { - response: Ok(types::PaymentsResponseData::TransactionResponse { - resource_id: types::ResponseId::ConnectorTransactionId( - item.response.order_id.clone(), - ), - redirection_data: Box::new(None), - mandate_reference: Box::new(None), - connector_metadata: None, - network_txn_id: None, - connector_response_reference_id: Some(item.response.order_id.clone()), - incremental_authorization_allowed: None, - charge_id: None, + match item.response { + KlarnaAuthResponse::KlarnaPaymentsAuthResponse(ref response) => { + let connector_response = + response + .authorized_payment_method + .as_ref() + .map(|authorized_payment_method| { + types::ConnectorResponseData::with_additional_payment_method_data( + types::AdditionalPaymentMethodConnectorResponse::from( + authorized_payment_method.clone(), + ), + ) + }); + + Ok(Self { + response: Ok(types::PaymentsResponseData::TransactionResponse { + resource_id: types::ResponseId::ConnectorTransactionId( + response.order_id.clone(), + ), + redirection_data: Box::new(None), + mandate_reference: Box::new(None), + connector_metadata: None, + network_txn_id: None, + connector_response_reference_id: Some(response.order_id.clone()), + incremental_authorization_allowed: None, + charge_id: None, + }), + status: enums::AttemptStatus::foreign_from(( + response.fraud_status.clone(), + item.data.request.is_auto_capture()?, + )), + connector_response, + ..item.data + }) + } + KlarnaAuthResponse::KlarnaCheckoutAuthResponse(ref response) => Ok(Self { + response: Ok(types::PaymentsResponseData::TransactionResponse { + resource_id: types::ResponseId::ConnectorTransactionId( + response.order_id.clone(), + ), + redirection_data: Box::new(Some(RedirectForm::Html { + html_data: response.html_snippet.clone(), + })), + mandate_reference: Box::new(None), + connector_metadata: None, + network_txn_id: None, + connector_response_reference_id: Some(response.order_id.clone()), + incremental_authorization_allowed: None, + charge_id: None, + }), + status: enums::AttemptStatus::foreign_from(( + response.status.clone(), + item.data.request.is_auto_capture()?, + )), + connector_response: None, + ..item.data }), - status: enums::AttemptStatus::foreign_from(( - item.response.fraud_status, - item.data.request.is_auto_capture()?, - )), - connector_response: Some(connector_response), - ..item.data - }) + } } } - -#[derive(Debug, Serialize)] +#[derive(Default, Debug, Serialize, Deserialize)] pub struct OrderLines { name: String, quantity: u16, unit_price: MinorUnit, total_amount: MinorUnit, + total_tax_amount: Option, + tax_rate: Option, } #[derive(Debug, Serialize)] @@ -325,6 +470,13 @@ pub enum KlarnaFraudStatus { Rejected, } +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum KlarnaCheckoutStatus { + CheckoutComplete, + CheckoutIncomplete, +} + impl ForeignFrom<(KlarnaFraudStatus, bool)> for enums::AttemptStatus { fn foreign_from((klarna_status, is_auto_capture): (KlarnaFraudStatus, bool)) -> Self { match klarna_status { @@ -341,13 +493,42 @@ impl ForeignFrom<(KlarnaFraudStatus, bool)> for enums::AttemptStatus { } } +impl ForeignFrom<(KlarnaCheckoutStatus, bool)> for enums::AttemptStatus { + fn foreign_from((klarna_status, is_auto_capture): (KlarnaCheckoutStatus, bool)) -> Self { + match klarna_status { + KlarnaCheckoutStatus::CheckoutIncomplete => { + if is_auto_capture { + Self::AuthenticationPending + } else { + Self::Authorized + } + } + KlarnaCheckoutStatus::CheckoutComplete => Self::Charged, + } + } +} + +#[derive(Debug, Deserialize, Serialize)] +#[serde(untagged)] +pub enum KlarnaPsyncResponse { + KlarnaSDKPsyncResponse(KlarnaSDKSyncResponse), + KlarnaCheckoutPSyncResponse(KlarnaCheckoutSyncResponse), +} + #[derive(Debug, Serialize, Deserialize)] -pub struct KlarnaPsyncResponse { +pub struct KlarnaSDKSyncResponse { pub order_id: String, pub status: KlarnaPaymentStatus, pub klarna_reference: Option, } +#[derive(Debug, Serialize, Deserialize)] +pub struct KlarnaCheckoutSyncResponse { + pub order_id: String, + pub status: KlarnaCheckoutStatus, + pub options: CheckoutOptions, +} + #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] pub enum KlarnaPaymentStatus { @@ -379,25 +560,45 @@ impl fn try_from( item: types::ResponseRouterData, ) -> Result { - Ok(Self { - status: enums::AttemptStatus::from(item.response.status), - response: Ok(types::PaymentsResponseData::TransactionResponse { - resource_id: types::ResponseId::ConnectorTransactionId( - item.response.order_id.clone(), - ), - redirection_data: Box::new(None), - mandate_reference: Box::new(None), - connector_metadata: None, - network_txn_id: None, - connector_response_reference_id: item - .response - .klarna_reference - .or(Some(item.response.order_id)), - incremental_authorization_allowed: None, - charge_id: None, + match item.response { + KlarnaPsyncResponse::KlarnaSDKPsyncResponse(response) => Ok(Self { + status: enums::AttemptStatus::from(response.status), + response: Ok(types::PaymentsResponseData::TransactionResponse { + resource_id: types::ResponseId::ConnectorTransactionId( + response.order_id.clone(), + ), + redirection_data: Box::new(None), + mandate_reference: Box::new(None), + connector_metadata: None, + network_txn_id: None, + connector_response_reference_id: response + .klarna_reference + .or(Some(response.order_id.clone())), + incremental_authorization_allowed: None, + charge_id: None, + }), + ..item.data }), - ..item.data - }) + KlarnaPsyncResponse::KlarnaCheckoutPSyncResponse(response) => Ok(Self { + status: enums::AttemptStatus::foreign_from(( + response.status.clone(), + response.options.auto_capture, + )), + response: Ok(types::PaymentsResponseData::TransactionResponse { + resource_id: types::ResponseId::ConnectorTransactionId( + response.order_id.clone(), + ), + redirection_data: Box::new(None), + mandate_reference: Box::new(None), + connector_metadata: None, + network_txn_id: None, + connector_response_reference_id: Some(response.order_id.clone()), + incremental_authorization_allowed: None, + charge_id: None, + }), + ..item.data + }), + } } } diff --git a/crates/router/src/connector/nuvei/transformers.rs b/crates/router/src/connector/nuvei/transformers.rs index 121ec1d7b7ce..a4195655ed38 100644 --- a/crates/router/src/connector/nuvei/transformers.rs +++ b/crates/router/src/connector/nuvei/transformers.rs @@ -977,6 +977,7 @@ where get_pay_later_info(AlternativePaymentMethodType::AfterPay, item) } domain::PayLaterData::KlarnaSdk { .. } + | domain::PayLaterData::KlarnaCheckout {} | domain::PayLaterData::AffirmRedirect {} | domain::PayLaterData::PayBrightRedirect {} | domain::PayLaterData::WalleyRedirect {} diff --git a/crates/router/src/connector/paypal/transformers.rs b/crates/router/src/connector/paypal/transformers.rs index 11e01b78e134..600b7ab0e221 100644 --- a/crates/router/src/connector/paypal/transformers.rs +++ b/crates/router/src/connector/paypal/transformers.rs @@ -1256,6 +1256,7 @@ impl TryFrom<&domain::PayLaterData> for PaypalPaymentsRequest { match value { domain::PayLaterData::KlarnaRedirect { .. } | domain::PayLaterData::KlarnaSdk { .. } + | domain::PayLaterData::KlarnaCheckout {} | domain::PayLaterData::AffirmRedirect {} | domain::PayLaterData::AfterpayClearpayRedirect { .. } | domain::PayLaterData::PayBrightRedirect {} diff --git a/crates/router/src/connector/stripe/transformers.rs b/crates/router/src/connector/stripe/transformers.rs index 2f0b0e0316fd..262b0348b5ae 100644 --- a/crates/router/src/connector/stripe/transformers.rs +++ b/crates/router/src/connector/stripe/transformers.rs @@ -992,6 +992,7 @@ impl TryFrom<&domain::payments::PayLaterData> for StripePaymentMethodType { } domain::PayLaterData::KlarnaSdk { .. } + | domain::PayLaterData::KlarnaCheckout {} | domain::PayLaterData::PayBrightRedirect {} | domain::PayLaterData::WalleyRedirect {} | domain::PayLaterData::AlmaRedirect {} diff --git a/crates/router/src/connector/utils.rs b/crates/router/src/connector/utils.rs index 1ea7565f69fe..171f19bc70ab 100644 --- a/crates/router/src/connector/utils.rs +++ b/crates/router/src/connector/utils.rs @@ -2793,6 +2793,7 @@ pub enum PaymentMethodDataType { SwishQr, KlarnaRedirect, KlarnaSdk, + KlarnaCheckout, AffirmRedirect, AfterpayClearpayRedirect, PayBrightRedirect, @@ -2916,6 +2917,7 @@ impl From for PaymentMethodDataType { domain::payments::PaymentMethodData::PayLater(pay_later_data) => match pay_later_data { domain::payments::PayLaterData::KlarnaRedirect { .. } => Self::KlarnaRedirect, domain::payments::PayLaterData::KlarnaSdk { .. } => Self::KlarnaSdk, + domain::payments::PayLaterData::KlarnaCheckout {} => Self::KlarnaCheckout, domain::payments::PayLaterData::AffirmRedirect {} => Self::AffirmRedirect, domain::payments::PayLaterData::AfterpayClearpayRedirect { .. } => { Self::AfterpayClearpayRedirect diff --git a/crates/router/src/core/payments/operations/payment_confirm.rs b/crates/router/src/core/payments/operations/payment_confirm.rs index aa551ce6fff6..96406932445a 100644 --- a/crates/router/src/core/payments/operations/payment_confirm.rs +++ b/crates/router/src/core/payments/operations/payment_confirm.rs @@ -1514,6 +1514,7 @@ impl UpdateTracker, api::PaymentsRequest> for surcharge_amount, tax_amount, ), + connector_mandate_detail: payment_data .payment_attempt .connector_mandate_detail, diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs index a316d6edc372..36b338f2d528 100644 --- a/crates/router/src/core/payments/operations/payment_create.rs +++ b/crates/router/src/core/payments/operations/payment_create.rs @@ -1428,6 +1428,15 @@ impl PaymentCreate { let skip_external_tax_calculation = request.skip_external_tax_calculation; + let tax_details = request + .order_tax_amount + .map(|tax_amount| diesel_models::TaxDetails { + default: Some(diesel_models::DefaultTax { + order_tax_amount: tax_amount, + }), + payment_method_type: None, + }); + Ok(storage::PaymentIntent { payment_id: payment_id.to_owned(), merchant_id: merchant_account.get_id().to_owned(), @@ -1482,7 +1491,7 @@ impl PaymentCreate { is_payment_processor_token_flow, organization_id: merchant_account.organization_id.clone(), shipping_cost: request.shipping_cost, - tax_details: None, + tax_details, skip_external_tax_calculation, psd2_sca_exemption_type: request.psd2_sca_exemption_type, }) diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index 85bc51a09a7f..528eb99e7df7 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -259,6 +259,7 @@ pub async fn construct_payment_router_data_for_authorize<'a>( .net_amount .get_amount_as_i64(), minor_amount: payment_data.payment_attempt.amount_details.net_amount, + order_tax_amount: None, currency: payment_data.payment_intent.amount_details.currency, browser_info: None, email: None, @@ -2427,25 +2428,6 @@ pub fn mobile_payment_next_steps_check( Ok(mobile_payment_next_step) } -pub fn change_order_details_to_new_type( - order_amount: MinorUnit, - order_details: api_models::payments::OrderDetails, -) -> Option> { - Some(vec![api_models::payments::OrderDetailsWithAmount { - product_name: order_details.product_name, - quantity: order_details.quantity, - amount: order_amount, - product_img_link: order_details.product_img_link, - requires_shipping: order_details.requires_shipping, - product_id: order_details.product_id, - category: order_details.category, - sub_category: order_details.sub_category, - brand: order_details.brand, - product_type: order_details.product_type, - product_tax_code: order_details.product_tax_code, - }]) -} - impl ForeignFrom for api_models::payments::NextActionData { fn foreign_from(qr_info: api_models::payments::QrCodeInformation) -> Self { match qr_info { @@ -2625,6 +2607,10 @@ impl TryFrom> for types::PaymentsAuthoriz statement_descriptor: payment_data.payment_intent.statement_descriptor_name, capture_method: payment_data.payment_attempt.capture_method, amount: amount.get_amount_as_i64(), + order_tax_amount: payment_data + .payment_attempt + .net_amount + .get_order_tax_amount(), minor_amount: amount, currency: payment_data.currency, browser_info, @@ -2961,7 +2947,6 @@ impl TryFrom> for types::SdkPaymentsSessi #[cfg(feature = "v1")] impl TryFrom> for types::SdkPaymentsSessionUpdateData { type Error = error_stack::Report; - fn try_from(additional_data: PaymentAdditionalData<'_, F>) -> Result { let payment_data = additional_data.payment_data; let order_tax_amount = payment_data diff --git a/crates/router/src/types.rs b/crates/router/src/types.rs index 2ab433785160..de4c063c41aa 100644 --- a/crates/router/src/types.rs +++ b/crates/router/src/types.rs @@ -873,6 +873,7 @@ impl ForeignFrom<&SetupMandateRouterData> for PaymentsAuthorizeData { email: data.request.email.clone(), customer_name: data.request.customer_name.clone(), amount: 0, + order_tax_amount: Some(MinorUnit::zero()), minor_amount: MinorUnit::new(0), statement_descriptor: None, capture_method: None, diff --git a/crates/router/src/types/api/verify_connector.rs b/crates/router/src/types/api/verify_connector.rs index 3bd318731313..bd55bd96b96e 100644 --- a/crates/router/src/types/api/verify_connector.rs +++ b/crates/router/src/types/api/verify_connector.rs @@ -29,6 +29,7 @@ impl VerifyConnectorData { amount: 1000, minor_amount: common_utils::types::MinorUnit::new(1000), confirm: true, + order_tax_amount: None, currency: storage_enums::Currency::USD, metadata: None, mandate_id: None, diff --git a/crates/router/src/types/transformers.rs b/crates/router/src/types/transformers.rs index d4cd57754362..1f55aa5801dd 100644 --- a/crates/router/src/types/transformers.rs +++ b/crates/router/src/types/transformers.rs @@ -1239,6 +1239,7 @@ impl ForeignFrom for payments::PaymentAttemptResponse { attempt_id: payment_attempt.attempt_id, status: payment_attempt.status, amount: payment_attempt.net_amount.get_order_amount(), + order_tax_amount: payment_attempt.net_amount.get_order_tax_amount(), currency: payment_attempt.currency, connector: payment_attempt.connector, error_message: payment_attempt.error_reason, diff --git a/crates/router/tests/connectors/payme.rs b/crates/router/tests/connectors/payme.rs index 1994acb6a659..15f980e242e1 100644 --- a/crates/router/tests/connectors/payme.rs +++ b/crates/router/tests/connectors/payme.rs @@ -90,6 +90,8 @@ fn payment_method_details() -> Option { brand: None, product_type: None, product_tax_code: None, + tax_rate: None, + total_tax_amount: None, }]), router_return_url: Some("https://hyperswitch.io".to_string()), webhook_url: Some("https://hyperswitch.io".to_string()), @@ -391,6 +393,8 @@ async fn should_fail_payment_for_incorrect_cvc() { brand: None, product_type: None, product_tax_code: None, + tax_rate: None, + total_tax_amount: None, }]), router_return_url: Some("https://hyperswitch.io".to_string()), webhook_url: Some("https://hyperswitch.io".to_string()), @@ -431,6 +435,8 @@ async fn should_fail_payment_for_invalid_exp_month() { brand: None, product_type: None, product_tax_code: None, + tax_rate: None, + total_tax_amount: None, }]), router_return_url: Some("https://hyperswitch.io".to_string()), webhook_url: Some("https://hyperswitch.io".to_string()), @@ -471,6 +477,8 @@ async fn should_fail_payment_for_incorrect_expiry_year() { brand: None, product_type: None, product_tax_code: None, + tax_rate: None, + total_tax_amount: None, }]), router_return_url: Some("https://hyperswitch.io".to_string()), webhook_url: Some("https://hyperswitch.io".to_string()), diff --git a/crates/router/tests/connectors/utils.rs b/crates/router/tests/connectors/utils.rs index f195aeaf7c40..489b55a227b3 100644 --- a/crates/router/tests/connectors/utils.rs +++ b/crates/router/tests/connectors/utils.rs @@ -939,6 +939,7 @@ impl Default for PaymentAuthorizeType { payment_method_data: types::domain::PaymentMethodData::Card(CCardType::default().0), amount: 100, minor_amount: MinorUnit::new(100), + order_tax_amount: Some(MinorUnit::zero()), currency: enums::Currency::USD, confirm: true, statement_descriptor_suffix: None, diff --git a/crates/router/tests/connectors/zen.rs b/crates/router/tests/connectors/zen.rs index de60c5e8d86a..a13fe48d2559 100644 --- a/crates/router/tests/connectors/zen.rs +++ b/crates/router/tests/connectors/zen.rs @@ -334,6 +334,8 @@ async fn should_fail_payment_for_incorrect_card_number() { brand: None, product_type: None, product_tax_code: None, + tax_rate: None, + total_tax_amount: None, }]), email: Some(Email::from_str("test@gmail.com").unwrap()), webhook_url: Some("https://1635-116-74-253-164.ngrok-free.app".to_string()), @@ -377,6 +379,8 @@ async fn should_fail_payment_for_incorrect_cvc() { brand: None, product_type: None, product_tax_code: None, + tax_rate: None, + total_tax_amount: None, }]), email: Some(Email::from_str("test@gmail.com").unwrap()), webhook_url: Some("https://1635-116-74-253-164.ngrok-free.app".to_string()), @@ -420,6 +424,8 @@ async fn should_fail_payment_for_invalid_exp_month() { brand: None, product_type: None, product_tax_code: None, + tax_rate: None, + total_tax_amount: None, }]), email: Some(Email::from_str("test@gmail.com").unwrap()), webhook_url: Some("https://1635-116-74-253-164.ngrok-free.app".to_string()), @@ -463,6 +469,8 @@ async fn should_fail_payment_for_incorrect_expiry_year() { brand: None, product_type: None, product_tax_code: None, + tax_rate: None, + total_tax_amount: None, }]), email: Some(Email::from_str("test@gmail.com").unwrap()), webhook_url: Some("https://1635-116-74-253-164.ngrok-free.app".to_string()),