From a6570b6a06917be27e543cb35bb210df4fc6391e Mon Sep 17 00:00:00 2001 From: Swangi Kumari <85639103+swangi-kumari@users.noreply.github.com> Date: Wed, 29 May 2024 15:39:10 +0530 Subject: [PATCH] refactor(connector): [Klarna] Refactor Authorize call and configs for prod (#4750) Co-authored-by: Samraat Bansal --- config/config.example.toml | 2 +- config/deployments/integration_test.toml | 2 +- config/deployments/production.toml | 2 +- config/deployments/sandbox.toml | 2 +- config/development.toml | 4 +- config/docker_compose.toml | 2 +- crates/connector_configs/src/common_config.rs | 11 ++ crates/connector_configs/src/connector.rs | 10 ++ .../src/response_modifier.rs | 1 + crates/connector_configs/src/transformer.rs | 3 + .../connector_configs/toml/development.toml | 7 +- crates/connector_configs/toml/production.toml | 7 +- crates/connector_configs/toml/sandbox.toml | 7 +- crates/router/src/connector/klarna.rs | 83 +++++++++--- .../src/connector/klarna/transformers.rs | 124 +++++++++++++----- crates/router/src/core/admin.rs | 1 + loadtest/config/development.toml | 2 +- 17 files changed, 204 insertions(+), 66 deletions(-) diff --git a/config/config.example.toml b/config/config.example.toml index d10e8216e9..52d5472d6e 100644 --- a/config/config.example.toml +++ b/config/config.example.toml @@ -195,7 +195,7 @@ gocardless.base_url = "https://api-sandbox.gocardless.com" gpayments.base_url = "https://{{merchant_endpoint_prefix}}-test.api.as1.gpayments.net" helcim.base_url = "https://api.helcim.com/" iatapay.base_url = "https://sandbox.iata-pay.iata.org/api/v1" -klarna.base_url = "https://api-na.playground.klarna.com/" +klarna.base_url = "https://api{{region_based_endpoint}}.playground.klarna.com/" mifinity.base_url = "https://demo.mifinity.com/" mollie.base_url = "https://api.mollie.com/v2/" mollie.secondary_base_url = "https://api.cc.mollie.com/v1/" diff --git a/config/deployments/integration_test.toml b/config/deployments/integration_test.toml index 9551cd2a80..4f8896d418 100644 --- a/config/deployments/integration_test.toml +++ b/config/deployments/integration_test.toml @@ -49,7 +49,7 @@ gocardless.base_url = "https://api-sandbox.gocardless.com" gpayments.base_url = "https://{{merchant_endpoint_prefix}}-test.api.as1.gpayments.net" helcim.base_url = "https://api.helcim.com/" iatapay.base_url = "https://sandbox.iata-pay.iata.org/api/v1" -klarna.base_url = "https://api-na.playground.klarna.com/" +klarna.base_url = "https://api{{region_based_endpoint}}.playground.klarna.com/" mifinity.base_url = "https://demo.mifinity.com/" mollie.base_url = "https://api.mollie.com/v2/" mollie.secondary_base_url = "https://api.cc.mollie.com/v1/" diff --git a/config/deployments/production.toml b/config/deployments/production.toml index 5f94086743..39c0b21315 100644 --- a/config/deployments/production.toml +++ b/config/deployments/production.toml @@ -53,7 +53,7 @@ gocardless.base_url = "https://api.gocardless.com" gpayments.base_url = "https://{{merchant_endpoint_prefix}}-test.api.as1.gpayments.net" helcim.base_url = "https://api.helcim.com/" iatapay.base_url = "https://iata-pay.iata.org/api/v1" -klarna.base_url = "https://api-na.playground.klarna.com/" +klarna.base_url = "https://api{{region_based_endpoint}}.klarna.com/" mifinity.base_url = "https://secure.mifinity.com/" mollie.base_url = "https://api.mollie.com/v2/" mollie.secondary_base_url = "https://api.cc.mollie.com/v1/" diff --git a/config/deployments/sandbox.toml b/config/deployments/sandbox.toml index d5f63524e6..ef7e49c7b9 100644 --- a/config/deployments/sandbox.toml +++ b/config/deployments/sandbox.toml @@ -53,7 +53,7 @@ gocardless.base_url = "https://api-sandbox.gocardless.com" gpayments.base_url = "https://{{merchant_endpoint_prefix}}-test.api.as1.gpayments.net" helcim.base_url = "https://api.helcim.com/" iatapay.base_url = "https://sandbox.iata-pay.iata.org/api/v1" -klarna.base_url = "https://api-na.playground.klarna.com/" +klarna.base_url = "https://api{{region_based_endpoint}}.playground.klarna.com/" mifinity.base_url = "https://demo.mifinity.com/" mollie.base_url = "https://api.mollie.com/v2/" mollie.secondary_base_url = "https://api.cc.mollie.com/v1/" diff --git a/config/development.toml b/config/development.toml index dfba91b514..6c71df7b07 100644 --- a/config/development.toml +++ b/config/development.toml @@ -197,7 +197,7 @@ gocardless.base_url = "https://api-sandbox.gocardless.com" gpayments.base_url = "https://{{merchant_endpoint_prefix}}-test.api.as1.gpayments.net" helcim.base_url = "https://api.helcim.com/" iatapay.base_url = "https://sandbox.iata-pay.iata.org/api/v1" -klarna.base_url = "https://api-na.playground.klarna.com/" +klarna.base_url = "https://api{{region_based_endpoint}}.playground.klarna.com/" mifinity.base_url = "https://demo.mifinity.com/" mollie.base_url = "https://api.mollie.com/v2/" mollie.secondary_base_url = "https://api.cc.mollie.com/v1/" @@ -404,8 +404,6 @@ debit = { currency = "USD" } [pm_filters.klarna] klarna = { country = "AU,AT,BE,CA,CZ,DK,FI,FR,DE,GR,IE,IT,NL,NZ,NO,PL,PT,ES,SE,CH,GB,US", currency = "AUD,EUR,EUR,CAD,CZK,DKK,EUR,EUR,EUR,EUR,EUR,EUR,EUR,NZD,NOK,PLN,EUR,EUR,SEK,CHF,GBP,USD" } -credit = { not_available_flows = { capture_method = "manual" } } -debit = { not_available_flows = { capture_method = "manual" } } [pm_filters.zen] credit = { not_available_flows = { capture_method = "manual" } } diff --git a/config/docker_compose.toml b/config/docker_compose.toml index d371d08148..cedcb8fedb 100644 --- a/config/docker_compose.toml +++ b/config/docker_compose.toml @@ -133,7 +133,7 @@ gocardless.base_url = "https://api-sandbox.gocardless.com" gpayments.base_url = "https://{{merchant_endpoint_prefix}}-test.api.as1.gpayments.net" helcim.base_url = "https://api.helcim.com/" iatapay.base_url = "https://sandbox.iata-pay.iata.org/api/v1" -klarna.base_url = "https://api-na.playground.klarna.com/" +klarna.base_url = "https://api{{region_based_endpoint}}.playground.klarna.com/" mifinity.base_url = "https://demo.mifinity.com/" mollie.base_url = "https://api.mollie.com/v2/" mollie.secondary_base_url = "https://api.cc.mollie.com/v1/" diff --git a/crates/connector_configs/src/common_config.rs b/crates/connector_configs/src/common_config.rs index fff210b6e4..fb4bf93c6f 100644 --- a/crates/connector_configs/src/common_config.rs +++ b/crates/connector_configs/src/common_config.rs @@ -97,6 +97,16 @@ pub struct ApiModelMetaData { pub three_ds_requestor_name: Option, pub three_ds_requestor_id: Option, pub pull_mechanism_for_external_3ds_enabled: Option, + pub klarna_region: Option, +} + +#[serde_with::skip_serializing_none] +#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)] + +pub enum KlarnaEndpoint { + Europe, + NorthAmerica, + Oceania, } #[serde_with::skip_serializing_none] @@ -199,4 +209,5 @@ pub struct DashboardMetaData { pub three_ds_requestor_name: Option, pub three_ds_requestor_id: Option, pub pull_mechanism_for_external_3ds_enabled: Option, + pub klarna_region: Option, } diff --git a/crates/connector_configs/src/connector.rs b/crates/connector_configs/src/connector.rs index 7118c87b09..f02f5e61c3 100644 --- a/crates/connector_configs/src/connector.rs +++ b/crates/connector_configs/src/connector.rs @@ -71,6 +71,15 @@ pub enum ApplePayTomlConfig { Zen(ZenApplePay), } +#[serde_with::skip_serializing_none] +#[derive(Debug, Clone, serde::Serialize, Deserialize)] + +pub enum KlarnaEndpoint { + Europe, + NorthAmerica, + Oceania, +} + #[serde_with::skip_serializing_none] #[derive(Debug, Deserialize, serde::Serialize, Clone)] pub struct ConfigMetadata { @@ -91,6 +100,7 @@ pub struct ConfigMetadata { pub three_ds_requestor_name: Option, pub three_ds_requestor_id: Option, pub pull_mechanism_for_external_3ds_enabled: Option, + pub klarna_region: Option, } #[serde_with::skip_serializing_none] diff --git a/crates/connector_configs/src/response_modifier.rs b/crates/connector_configs/src/response_modifier.rs index ebf97d8316..bdd366ce1c 100644 --- a/crates/connector_configs/src/response_modifier.rs +++ b/crates/connector_configs/src/response_modifier.rs @@ -322,6 +322,7 @@ impl From for DashboardMetaData { three_ds_requestor_id: api_model.three_ds_requestor_id, pull_mechanism_for_external_3ds_enabled: api_model .pull_mechanism_for_external_3ds_enabled, + klarna_region: api_model.klarna_region, } } } diff --git a/crates/connector_configs/src/transformer.rs b/crates/connector_configs/src/transformer.rs index ae4b020676..94cc06786a 100644 --- a/crates/connector_configs/src/transformer.rs +++ b/crates/connector_configs/src/transformer.rs @@ -197,6 +197,7 @@ impl DashboardRequestPayload { three_ds_requestor_id: None, pull_mechanism_for_external_3ds_enabled: None, paypal_sdk: None, + klarna_region: None, }; let meta_data = match request.metadata { Some(data) => data, @@ -221,6 +222,7 @@ impl DashboardRequestPayload { let three_ds_requestor_id = meta_data.three_ds_requestor_id; let pull_mechanism_for_external_3ds_enabled = meta_data.pull_mechanism_for_external_3ds_enabled; + let klarna_region = meta_data.klarna_region; Some(ApiModelMetaData { google_pay, @@ -241,6 +243,7 @@ impl DashboardRequestPayload { three_ds_requestor_name, three_ds_requestor_id, pull_mechanism_for_external_3ds_enabled, + klarna_region, }) } diff --git a/crates/connector_configs/toml/development.toml b/crates/connector_configs/toml/development.toml index fcccf9c7e2..f779ecfd70 100644 --- a/crates/connector_configs/toml/development.toml +++ b/crates/connector_configs/toml/development.toml @@ -1137,8 +1137,11 @@ merchant_secret="Source verification key" [klarna] [[klarna.pay_later]] payment_method_type = "klarna" -[klarna.connector_auth.HeaderKey] -api_key="Klarna API Key" +[klarna.connector_auth.BodyKey] +key1="Klarna Merchant Username" +api_key="Klarna Merchant ID Password" +[klarna.metadata] +klarna_region="Region of your Klarna Merchant Account" [klarna.connector_webhook_details] merchant_secret="Source verification key" diff --git a/crates/connector_configs/toml/production.toml b/crates/connector_configs/toml/production.toml index 96fba850e7..fa7ea1b832 100644 --- a/crates/connector_configs/toml/production.toml +++ b/crates/connector_configs/toml/production.toml @@ -954,8 +954,11 @@ merchant_secret="Source verification key" [klarna] [[klarna.pay_later]] payment_method_type = "klarna" -[klarna.connector_auth.HeaderKey] -api_key="Klarna API Key" +[klarna.connector_auth.BodyKey] +key1="Klarna Merchant Username" +api_key="Klarna Merchant ID Password" +[klarna.metadata] +klarna_region="Region of your Klarna Merchant Account" [klarna.connector_webhook_details] merchant_secret="Source verification key" diff --git a/crates/connector_configs/toml/sandbox.toml b/crates/connector_configs/toml/sandbox.toml index 932352f20e..d1376a15d0 100644 --- a/crates/connector_configs/toml/sandbox.toml +++ b/crates/connector_configs/toml/sandbox.toml @@ -1137,8 +1137,11 @@ merchant_secret="Source verification key" [klarna] [[klarna.pay_later]] payment_method_type = "klarna" -[klarna.connector_auth.HeaderKey] -api_key="Klarna API Key" +[klarna.connector_auth.BodyKey] +key1="Klarna Merchant Username" +api_key="Klarna Merchant ID Password" +[klarna.metadata] +klarna_region="Region of your Klarna Merchant Account" [klarna.connector_webhook_details] merchant_secret="Source verification key" diff --git a/crates/router/src/connector/klarna.rs b/crates/router/src/connector/klarna.rs index 48b6616a64..284a6a65f7 100644 --- a/crates/router/src/connector/klarna.rs +++ b/crates/router/src/connector/klarna.rs @@ -1,8 +1,11 @@ pub mod transformers; use std::fmt::Debug; +use api_models::enums; +use base64::Engine; use common_utils::request::RequestContent; use error_stack::{report, ResultExt}; +use masking::PeekInterface; use transformers as klarna; use crate::{ @@ -51,9 +54,14 @@ impl ConnectorCommon for Klarna { ) -> CustomResult)>, errors::ConnectorError> { let auth = klarna::KlarnaAuthType::try_from(auth_type) .change_context(errors::ConnectorError::FailedToObtainAuthType)?; + let encoded_api_key = consts::BASE64_ENGINE.encode(format!( + "{}:{}", + auth.username.peek(), + auth.password.peek() + )); Ok(vec![( headers::AUTHORIZATION.to_string(), - auth.basic_token.into_masked(), + format!("Basic {encoded_api_key}").into_masked(), )]) } @@ -74,11 +82,13 @@ impl ConnectorCommon for Klarna { let reason = response .error_messages .map(|messages| messages.join(" & ")) - .or(response.error_message); + .or(response.error_message.clone()); Ok(types::ErrorResponse { status_code: res.status_code, code: response.error_code, - message: consts::NO_ERROR_MESSAGE.to_string(), + message: response + .error_message + .unwrap_or(consts::NO_ERROR_MESSAGE.to_string()), reason, attempt_status: None, connector_transaction_id: None, @@ -86,7 +96,21 @@ impl ConnectorCommon for Klarna { } } -impl ConnectorValidation for Klarna {} +impl ConnectorValidation for Klarna { + fn validate_capture_method( + &self, + capture_method: Option, + _pmt: Option, + ) -> CustomResult<(), errors::ConnectorError> { + let capture_method = capture_method.unwrap_or_default(); + match capture_method { + enums::CaptureMethod::Automatic | enums::CaptureMethod::Manual => Ok(()), + enums::CaptureMethod::ManualMultiple | enums::CaptureMethod::Scheduled => Err( + connector_utils::construct_not_supported_error_report(capture_method, self.id()), + ), + } + } +} impl api::Payment for Klarna {} @@ -118,6 +142,22 @@ impl // Not Implemented (R) } +fn build_region_specific_endpoint( + base_url: &str, + connector_metadata: &Option, +) -> CustomResult { + let klarna_metadata_object = + transformers::KlarnaConnectorMetadataObject::try_from(connector_metadata)?; + let region_based_endpoint = klarna_metadata_object + .klarna_region + .ok_or(errors::ConnectorError::InvalidConnectorConfig { + config: "merchant_connector_account.metadata.region_based_endpoint", + }) + .map(String::from)?; + + Ok(base_url.replace("{{region_based_endpoint}}", ®ion_based_endpoint)) +} + impl services::ConnectorIntegration< api::Session, @@ -147,14 +187,13 @@ impl fn get_url( &self, - _req: &types::PaymentsSessionRouterData, + req: &types::PaymentsSessionRouterData, connectors: &settings::Connectors, ) -> CustomResult { - Ok(format!( - "{}{}", - self.base_url(connectors), - "payments/v1/sessions" - )) + let endpoint = + build_region_specific_endpoint(self.base_url(connectors), &req.connector_meta_data)?; + + Ok(format!("{}{}", endpoint, "payments/v1/sessions")) } fn get_request_body( @@ -162,7 +201,14 @@ impl req: &types::PaymentsSessionRouterData, _connectors: &settings::Connectors, ) -> CustomResult { - let connector_req = klarna::KlarnaSessionRequest::try_from(req)?; + let connector_router_data = klarna::KlarnaRouterData::try_from(( + &self.get_currency_unit(), + req.request.currency, + req.request.amount, + req, + ))?; + + let connector_req = klarna::KlarnaSessionRequest::try_from(&connector_router_data)?; // encode only for for urlencoded things. Ok(RequestContent::Json(Box::new(connector_req))) } @@ -304,6 +350,8 @@ impl .payment_method_type .as_ref() .ok_or_else(connector_utils::missing_field_err("payment_method_type"))?; + let endpoint = + build_region_specific_endpoint(self.base_url(connectors), &req.connector_meta_data)?; match payment_method_data { domain::PaymentMethodData::PayLater(domain::PayLaterData::KlarnaSdk { token }) => { @@ -313,8 +361,7 @@ impl common_enums::PaymentMethodType::Klarna, ) => Ok(format!( "{}payments/v1/authorizations/{}/order", - self.base_url(connectors), - token + endpoint, token )), ( common_enums::PaymentExperience::DisplayQrCode @@ -430,9 +477,13 @@ impl | domain::PaymentMethodData::Upi(_) | domain::PaymentMethodData::Voucher(_) | domain::PaymentMethodData::GiftCard(_) - | domain::PaymentMethodData::CardToken(_) => Err(error_stack::report!( - errors::ConnectorError::MismatchedPaymentData - )), + | domain::PaymentMethodData::CardToken(_) => { + Err(report!(errors::ConnectorError::NotImplemented( + connector_utils::get_unimplemented_payment_method_error_message( + req.connector.as_str(), + ), + ))) + } } } diff --git a/crates/router/src/connector/klarna/transformers.rs b/crates/router/src/connector/klarna/transformers.rs index 15fed065f0..12fd1a0b43 100644 --- a/crates/router/src/connector/klarna/transformers.rs +++ b/crates/router/src/connector/klarna/transformers.rs @@ -1,11 +1,13 @@ use api_models::payments; -use error_stack::report; +use common_utils::pii; +use error_stack::{report, ResultExt}; use masking::{ExposeInterface, Secret}; use serde::{Deserialize, Serialize}; use crate::{ + connector::utils::{self, PaymentsAuthorizeRequestData, RouterData}, core::errors, - types::{self, storage::enums}, + types::{self, storage::enums, transformers::ForeignFrom}, }; #[derive(Debug, Serialize)] @@ -32,16 +34,50 @@ impl TryFrom<(&types::api::CurrencyUnit, enums::Currency, i64, T)> for Klarna } } -#[derive(Default, Debug, Serialize)] -pub struct KlarnaPaymentsRequest { - order_lines: Vec, - order_amount: i64, - purchase_country: String, - purchase_currency: enums::Currency, - merchant_reference1: String, +#[derive(Debug, Serialize, Deserialize)] +pub struct KlarnaConnectorMetadataObject { + pub klarna_region: Option, } -#[derive(Default, Debug, Deserialize, Serialize)] +#[derive(Debug, Serialize, Deserialize)] +pub enum KlarnaEndpoint { + Europe, + NorthAmerica, + Oceania, +} + +impl From for String { + fn from(endpoint: KlarnaEndpoint) -> Self { + Self::from(match endpoint { + KlarnaEndpoint::Europe => "", + KlarnaEndpoint::NorthAmerica => "-na", + KlarnaEndpoint::Oceania => "-oc", + }) + } +} + +impl TryFrom<&Option> for KlarnaConnectorMetadataObject { + type Error = error_stack::Report; + fn try_from(meta_data: &Option) -> Result { + let metadata: Self = utils::to_connector_meta_from_secret::(meta_data.clone()) + .change_context(errors::ConnectorError::InvalidConnectorConfig { + config: "metadata", + })?; + Ok(metadata) + } +} + +#[derive(Default, Debug, Serialize)] +pub struct KlarnaPaymentsRequest { + auto_capture: bool, + order_lines: Vec, + order_amount: i64, + purchase_country: enums::CountryAlpha2, + purchase_currency: enums::Currency, + merchant_reference1: Option, +} + +#[derive(Debug, Deserialize, Serialize)] pub struct KlarnaPaymentsResponse { order_id: String, fraud_status: KlarnaFraudStatus, @@ -50,9 +86,8 @@ pub struct KlarnaPaymentsResponse { #[derive(Debug, Serialize)] pub struct KlarnaSessionRequest { intent: KlarnaSessionIntent, - purchase_country: String, + purchase_country: enums::CountryAlpha2, purchase_currency: enums::Currency, - locale: String, order_amount: i64, order_lines: Vec, } @@ -60,20 +95,25 @@ pub struct KlarnaSessionRequest { #[derive(Deserialize, Serialize, Debug)] pub struct KlarnaSessionResponse { pub client_token: Secret, - pub session_id: Secret, + pub session_id: String, } -impl TryFrom<&types::PaymentsSessionRouterData> for KlarnaSessionRequest { +impl TryFrom<&KlarnaRouterData<&types::PaymentsSessionRouterData>> for KlarnaSessionRequest { type Error = error_stack::Report; - fn try_from(item: &types::PaymentsSessionRouterData) -> Result { - let request = &item.request; + fn try_from( + item: &KlarnaRouterData<&types::PaymentsSessionRouterData>, + ) -> Result { + let request = &item.router_data.request; match request.order_details.clone() { Some(order_details) => Ok(Self { intent: KlarnaSessionIntent::Buy, - purchase_country: "US".to_string(), + purchase_country: request.country.ok_or( + errors::ConnectorError::MissingRequiredField { + field_name: "billing.address.country", + }, + )?, purchase_currency: request.currency, - order_amount: request.amount, - locale: "en-US".to_string(), + order_amount: item.amount, order_lines: order_details .iter() .map(|data| OrderLines { @@ -85,7 +125,7 @@ impl TryFrom<&types::PaymentsSessionRouterData> for KlarnaSessionRequest { .collect(), }), None => Err(report!(errors::ConnectorError::MissingRequiredField { - field_name: "product_name", + field_name: "order_details", })), } } @@ -104,7 +144,7 @@ impl TryFrom> session_token: types::api::SessionToken::Klarna(Box::new( payments::KlarnaSessionTokenResponse { session_token: response.client_token.clone().expose(), - session_id: response.session_id.clone().expose(), + session_id: response.session_id.clone(), }, )), }), @@ -122,9 +162,9 @@ impl TryFrom<&KlarnaRouterData<&types::PaymentsAuthorizeRouterData>> for KlarnaP let request = &item.router_data.request; match request.order_details.clone() { Some(order_details) => Ok(Self { - purchase_country: "US".to_string(), + purchase_country: item.router_data.get_billing_country()?, purchase_currency: request.currency, - order_amount: request.amount, + order_amount: item.amount, order_lines: order_details .iter() .map(|data| OrderLines { @@ -134,10 +174,11 @@ impl TryFrom<&KlarnaRouterData<&types::PaymentsAuthorizeRouterData>> for KlarnaP total_amount: i64::from(data.quantity) * (data.amount), }) .collect(), - merchant_reference1: item.router_data.connector_request_reference_id.clone(), + merchant_reference1: Some(item.router_data.connector_request_reference_id.clone()), + auto_capture: request.is_auto_capture()?, }), None => Err(report!(errors::ConnectorError::MissingRequiredField { - field_name: "product_name" + field_name: "order_details" })), } } @@ -163,11 +204,15 @@ impl TryFrom> incremental_authorization_allowed: None, charge_id: None, }), - status: item.response.fraud_status.into(), + status: enums::AttemptStatus::foreign_from(( + item.response.fraud_status, + item.data.request.is_auto_capture()?, + )), ..item.data }) } } + #[derive(Debug, Serialize)] pub struct OrderLines { name: String, @@ -186,15 +231,17 @@ pub enum KlarnaSessionIntent { } pub struct KlarnaAuthType { - pub basic_token: Secret, + pub username: Secret, + pub password: Secret, } impl TryFrom<&types::ConnectorAuthType> for KlarnaAuthType { type Error = error_stack::Report; fn try_from(auth_type: &types::ConnectorAuthType) -> Result { - if let types::ConnectorAuthType::HeaderKey { api_key } = auth_type { + if let types::ConnectorAuthType::BodyKey { api_key, key1 } = auth_type { Ok(Self { - basic_token: api_key.to_owned(), + username: key1.to_owned(), + password: api_key.to_owned(), }) } else { Err(errors::ConnectorError::FailedToObtainAuthType.into()) @@ -202,19 +249,26 @@ impl TryFrom<&types::ConnectorAuthType> for KlarnaAuthType { } } -#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "UPPERCASE")] pub enum KlarnaFraudStatus { Accepted, - #[default] Pending, + Rejected, } -impl From for enums::AttemptStatus { - fn from(item: KlarnaFraudStatus) -> Self { - match item { - KlarnaFraudStatus::Accepted => Self::Charged, +impl ForeignFrom<(KlarnaFraudStatus, bool)> for enums::AttemptStatus { + fn foreign_from((klarna_status, is_auto_capture): (KlarnaFraudStatus, bool)) -> Self { + match klarna_status { + KlarnaFraudStatus::Accepted => { + if is_auto_capture { + Self::Charged + } else { + Self::Authorized + } + } KlarnaFraudStatus::Pending => Self::Authorizing, + KlarnaFraudStatus::Rejected => Self::Failure, } } } diff --git a/crates/router/src/core/admin.rs b/crates/router/src/core/admin.rs index b50c5b6968..459da09f47 100644 --- a/crates/router/src/core/admin.rs +++ b/crates/router/src/core/admin.rs @@ -1947,6 +1947,7 @@ pub(crate) fn validate_auth_and_metadata_type( } api_enums::Connector::Klarna => { klarna::transformers::KlarnaAuthType::try_from(val)?; + klarna::transformers::KlarnaConnectorMetadataObject::try_from(connector_meta_data)?; Ok(()) } api_enums::Connector::Mollie => { diff --git a/loadtest/config/development.toml b/loadtest/config/development.toml index 878451080e..837ef4fe75 100644 --- a/loadtest/config/development.toml +++ b/loadtest/config/development.toml @@ -100,7 +100,7 @@ gocardless.base_url = "https://api-sandbox.gocardless.com" gpayments.base_url = "https://{{merchant_endpoint_prefix}}-test.api.as1.gpayments.net" helcim.base_url = "https://api.helcim.com/" iatapay.base_url = "https://sandbox.iata-pay.iata.org/api/v1" -klarna.base_url = "https://api-na.playground.klarna.com/" +klarna.base_url = "https://api{{region_based_endpoint}}.playground.klarna.com/" mifinity.base_url = "https://demo.mifinity.com/" mollie.base_url = "https://api.mollie.com/v2/" mollie.secondary_base_url = "https://api.cc.mollie.com/v1/"