diff --git a/config/development.toml b/config/development.toml index ced0a7b4fd..46b0766be9 100644 --- a/config/development.toml +++ b/config/development.toml @@ -47,6 +47,7 @@ locker_decryption_key1 = "" locker_decryption_key2 = "" vault_encryption_key = "" vault_private_key = "" +tunnel_private_key = "" [connectors.supported] wallets = ["klarna", "braintree", "applepay"] diff --git a/crates/common_utils/src/ext_traits.rs b/crates/common_utils/src/ext_traits.rs index 29a24449d9..aefb532471 100644 --- a/crates/common_utils/src/ext_traits.rs +++ b/crates/common_utils/src/ext_traits.rs @@ -147,17 +147,17 @@ where /// /// Extending functionalities of `bytes::Bytes` /// -pub trait BytesExt { +pub trait BytesExt { /// /// Convert `bytes::Bytes` into type `` using `serde::Deserialize` /// - fn parse_struct<'de>(&'de self, type_name: &str) -> CustomResult + fn parse_struct<'de, T>(&'de self, type_name: &str) -> CustomResult where T: Deserialize<'de>; } -impl BytesExt for bytes::Bytes { - fn parse_struct<'de>(&'de self, _type_name: &str) -> CustomResult +impl BytesExt for bytes::Bytes { + fn parse_struct<'de, T>(&'de self, _type_name: &str) -> CustomResult where T: Deserialize<'de>, { diff --git a/crates/router/src/compatibility/stripe.rs b/crates/router/src/compatibility/stripe.rs index 9ce9fef1f4..5d3fd5b6cd 100644 --- a/crates/router/src/compatibility/stripe.rs +++ b/crates/router/src/compatibility/stripe.rs @@ -20,6 +20,7 @@ impl StripeApis { .service(app::PaymentIntents::server(state.clone())) .service(app::Refunds::server(state.clone())) .service(app::Customers::server(state.clone())) - .service(app::Webhooks::server(state)) + .service(app::Webhooks::server(state.clone())) + .service(app::Mandates::server(state)) } } diff --git a/crates/router/src/compatibility/stripe/app.rs b/crates/router/src/compatibility/stripe/app.rs index 24abb90b42..540cb5df6a 100644 --- a/crates/router/src/compatibility/stripe/app.rs +++ b/crates/router/src/compatibility/stripe/app.rs @@ -1,7 +1,7 @@ use actix_web::{web, Scope}; use super::{customers::*, payment_intents::*, refunds::*, setup_intents::*, webhooks::*}; -use crate::routes::{self, webhooks}; +use crate::routes::{self, mandates, webhooks}; pub struct PaymentIntents; @@ -111,3 +111,13 @@ impl Webhooks { ) } } + +pub struct Mandates; + +impl Mandates { + pub fn server(config: routes::AppState) -> Scope { + web::scope("/payment_methods") + .app_data(web::Data::new(config)) + .service(web::resource("/{id}/detach").route(web::post().to(mandates::revoke_mandate))) + } +} diff --git a/crates/router/src/compatibility/stripe/payment_intents/types.rs b/crates/router/src/compatibility/stripe/payment_intents/types.rs index 0046ae3eb1..eaaf82b1f0 100644 --- a/crates/router/src/compatibility/stripe/payment_intents/types.rs +++ b/crates/router/src/compatibility/stripe/payment_intents/types.rs @@ -1,6 +1,6 @@ use api_models::payments; use common_utils::{date_time, ext_traits::StringExt, pii as secret}; -use error_stack::ResultExt; +use error_stack::{IntoReport, ResultExt}; use serde::{Deserialize, Serialize}; use crate::{ @@ -10,7 +10,7 @@ use crate::{ pii::{self, Email, PeekInterface}, types::{ api::{admin, enums as api_enums}, - transformers::{ForeignFrom, ForeignInto}, + transformers::{ForeignFrom, ForeignTryFrom}, }, }; @@ -59,6 +59,7 @@ impl From for api_enums::PaymentMethod { } } } + #[derive(Default, PartialEq, Eq, Deserialize, Clone)] pub struct StripePaymentMethodData { #[serde(rename = "type")] @@ -143,12 +144,32 @@ pub struct StripePaymentIntentRequest { pub client_secret: Option>, pub payment_method_options: Option, pub merchant_connector_details: Option, + pub mandate_id: Option, + pub off_session: Option, } impl TryFrom for payments::PaymentsRequest { type Error = error_stack::Report; fn try_from(item: StripePaymentIntentRequest) -> errors::RouterResult { - Ok(Self { + let (mandate_options, authentication_type) = match item.payment_method_options { + Some(pmo) => { + let StripePaymentMethodOptions::Card { + request_three_d_secure, + mandate_options, + }: StripePaymentMethodOptions = pmo; + ( + Option::::foreign_try_from(( + mandate_options, + item.currency.to_owned(), + ))?, + Some(api_enums::AuthenticationType::foreign_from( + request_three_d_secure, + )), + ) + } + None => (None, None), + }; + let request = Ok(Self { payment_id: item.id.map(payments::PaymentIdType::PaymentIntentId), amount: item.amount.map(|amount| amount.into()), connector: item.connector, @@ -188,16 +209,15 @@ impl TryFrom for payments::PaymentsRequest { statement_descriptor_suffix: item.statement_descriptor_suffix, metadata: item.metadata, client_secret: item.client_secret.map(|s| s.peek().clone()), - authentication_type: item.payment_method_options.map(|pmo| { - let StripePaymentMethodOptions::Card { - request_three_d_secure, - } = pmo; - - request_three_d_secure.foreign_into() - }), + authentication_type, + mandate_data: mandate_options, merchant_connector_details: item.merchant_connector_details, + setup_future_usage: item.setup_future_usage, + mandate_id: item.mandate_id, + off_session: item.off_session, ..Self::default() - }) + }); + request } } @@ -374,7 +394,7 @@ impl From for StripePaymentIntentResponse { created: u64::try_from(date_time::now().assume_utc().unix_timestamp()) .unwrap_or_default(), method_type: "card".to_string(), - live_mode: false, + livemode: false, }, error_type: code, }), @@ -391,7 +411,7 @@ pub struct StripePaymentMethod { created: u64, #[serde(rename = "type")] method_type: String, - live_mode: bool, + livemode: bool, } #[derive(Default, Eq, PartialEq, Serialize)] @@ -404,7 +424,7 @@ pub struct Charges { } impl Charges { - fn new() -> Self { + pub fn new() -> Self { Self { object: "list", data: vec![], @@ -491,15 +511,83 @@ impl From for StripePaymentIntentListResponse { } } -#[derive(PartialEq, Eq, Deserialize, Clone)] +#[derive(PartialEq, Eq, Deserialize, Clone, Debug)] #[serde(rename_all = "snake_case")] pub enum StripePaymentMethodOptions { Card { request_three_d_secure: Option, + mandate_options: Option, }, } -#[derive(Default, Eq, PartialEq, Serialize, Deserialize, Clone)] +#[derive(Eq, PartialEq, Debug, serde::Deserialize, serde::Serialize, Clone)] +#[serde(rename_all = "snake_case")] +pub enum StripeMandateType { + SingleUse, + MultiUse, +} + +#[derive(PartialEq, Eq, Clone, Default, Deserialize, Serialize, Debug)] +pub struct MandateOption { + #[serde(default, with = "common_utils::custom_serde::timestamp::option")] + pub accepted_at: Option, + pub user_agent: Option, + pub ip_address: Option>, + pub mandate_type: Option, + pub amount: Option, + #[serde(default, with = "common_utils::custom_serde::timestamp::option")] + pub start_date: Option, + #[serde(default, with = "common_utils::custom_serde::timestamp::option")] + pub end_date: Option, +} + +impl ForeignTryFrom<(Option, Option)> for Option { + type Error = error_stack::Report; + fn foreign_try_from( + (mandate_options, currency): (Option, Option), + ) -> errors::RouterResult { + let currency = currency + .ok_or(errors::ApiErrorResponse::MissingRequiredField { + field_name: "currency", + }) + .into_report() + .and_then(|c| { + c.to_uppercase().parse_enum("currency").change_context( + errors::ApiErrorResponse::InvalidDataValue { + field_name: "currency", + }, + ) + })?; + let mandate_data = mandate_options.map(|mandate| payments::MandateData { + mandate_type: match mandate.mandate_type { + Some(item) => match item { + StripeMandateType::SingleUse => { + payments::MandateType::SingleUse(payments::MandateAmountData { + amount: mandate.amount.unwrap_or_default(), + currency, + start_date: mandate.start_date, + end_date: mandate.end_date, + metadata: None, + }) + } + StripeMandateType::MultiUse => payments::MandateType::MultiUse(None), + }, + None => api_models::payments::MandateType::MultiUse(None), + }, + customer_acceptance: payments::CustomerAcceptance { + acceptance_type: payments::AcceptanceType::Online, + accepted_at: mandate.accepted_at, + online: Some(payments::OnlineMandate { + ip_address: mandate.ip_address.unwrap_or_default(), + user_agent: mandate.user_agent.unwrap_or_default(), + }), + }, + }); + Ok(mandate_data) + } +} + +#[derive(Default, Eq, PartialEq, Serialize, Deserialize, Clone, Debug)] #[serde(rename_all = "snake_case")] pub enum Request3DS { #[default] diff --git a/crates/router/src/compatibility/stripe/setup_intents.rs b/crates/router/src/compatibility/stripe/setup_intents.rs index b11be5b346..d907c45d14 100644 --- a/crates/router/src/compatibility/stripe/setup_intents.rs +++ b/crates/router/src/compatibility/stripe/setup_intents.rs @@ -28,7 +28,11 @@ pub async fn setup_intents_create( } }; - let create_payment_req: payment_types::PaymentsRequest = payload.into(); + let create_payment_req: payment_types::PaymentsRequest = + match payment_types::PaymentsRequest::try_from(payload) { + Ok(req) => req, + Err(err) => return api::log_and_return_error_response(err), + }; wrap::compatibility_api_wrap::< _, @@ -124,7 +128,11 @@ pub async fn setup_intents_update( } }; - let mut payload: payment_types::PaymentsRequest = stripe_payload.into(); + let mut payload: payment_types::PaymentsRequest = + match payment_types::PaymentsRequest::try_from(stripe_payload) { + Ok(req) => req, + Err(err) => return api::log_and_return_error_response(err), + }; payload.payment_id = Some(api_types::PaymentIdType::PaymentIntentId(setup_id)); let (auth_type, auth_flow) = @@ -179,7 +187,11 @@ pub async fn setup_intents_confirm( } }; - let mut payload: payment_types::PaymentsRequest = stripe_payload.into(); + let mut payload: payment_types::PaymentsRequest = + match payment_types::PaymentsRequest::try_from(stripe_payload) { + Ok(req) => req, + Err(err) => return api::log_and_return_error_response(err), + }; payload.payment_id = Some(api_types::PaymentIdType::PaymentIntentId(setup_id)); payload.confirm = Some(true); diff --git a/crates/router/src/compatibility/stripe/setup_intents/types.rs b/crates/router/src/compatibility/stripe/setup_intents/types.rs index 0279e36ac8..645729d083 100644 --- a/crates/router/src/compatibility/stripe/setup_intents/types.rs +++ b/crates/router/src/compatibility/stripe/setup_intents/types.rs @@ -1,12 +1,21 @@ -use api_models::{payments, refunds}; +use api_models::payments; +use common_utils::{date_time, ext_traits::StringExt}; +use error_stack::ResultExt; use router_env::logger; use serde::{Deserialize, Serialize}; use serde_json::Value; use crate::{ + compatibility::stripe::{ + payment_intents::types as payment_intent, refunds::types as stripe_refunds, + }, + consts, core::errors, pii::{self, PeekInterface}, - types::api::{self as api_types, enums as api_enums}, + types::{ + api::{self as api_types, admin, enums as api_enums}, + transformers::{ForeignFrom, ForeignTryFrom}, + }, }; #[derive(Default, Serialize, PartialEq, Eq, Deserialize, Clone)] @@ -108,11 +117,14 @@ impl From for payments::Address { } } } + #[derive(Default, PartialEq, Eq, Deserialize, Clone)] + pub struct StripeSetupIntentRequest { pub confirm: Option, pub customer: Option, pub description: Option, + pub currency: Option, pub payment_method_data: Option, pub receipt_email: Option, pub return_url: Option, @@ -123,17 +135,46 @@ pub struct StripeSetupIntentRequest { pub statement_descriptor_suffix: Option, pub metadata: Option, pub client_secret: Option>, + pub payment_method_options: Option, + pub payment_method: Option, + pub merchant_connector_details: Option, } -impl From for payments::PaymentsRequest { - fn from(item: StripeSetupIntentRequest) -> Self { - Self { +impl TryFrom for payments::PaymentsRequest { + type Error = error_stack::Report; + fn try_from(item: StripeSetupIntentRequest) -> errors::RouterResult { + let (mandate_options, authentication_type) = match item.payment_method_options { + Some(pmo) => { + let payment_intent::StripePaymentMethodOptions::Card { + request_three_d_secure, + mandate_options, + }: payment_intent::StripePaymentMethodOptions = pmo; + ( + Option::::foreign_try_from(( + mandate_options, + item.currency.to_owned(), + ))?, + Some(api_enums::AuthenticationType::foreign_from( + request_three_d_secure, + )), + ) + } + None => (None, None), + }; + let request = Ok(Self { amount: Some(api_types::Amount::Zero), - currency: Some(api_enums::Currency::default()), capture_method: None, amount_to_capture: None, confirm: item.confirm, customer_id: item.customer, + currency: item + .currency + .as_ref() + .map(|c| c.to_uppercase().parse_enum("currency")) + .transpose() + .change_context(errors::ApiErrorResponse::InvalidDataValue { + field_name: "currency", + })?, email: item.receipt_email, name: item .billing_details @@ -163,8 +204,13 @@ impl From for payments::PaymentsRequest { statement_descriptor_suffix: item.statement_descriptor_suffix, metadata: item.metadata, client_secret: item.client_secret.map(|s| s.peek().clone()), + setup_future_usage: item.setup_future_usage, + merchant_connector_details: item.merchant_connector_details, + authentication_type, + mandate_data: mandate_options, ..Default::default() - } + }); + request } } @@ -232,6 +278,32 @@ impl From for payments::PaymentsCancelRequest { } } } +#[derive(Default, Eq, PartialEq, Serialize)] +pub struct RedirectUrl { + pub return_url: Option, + pub url: Option, +} + +#[derive(Eq, PartialEq, Serialize)] +pub struct StripeNextAction { + #[serde(rename = "type")] + stype: payments::NextActionType, + redirect_to_url: RedirectUrl, +} + +pub(crate) fn into_stripe_next_action( + next_action: Option, + return_url: Option, +) -> Option { + next_action.map(|n| StripeNextAction { + stype: n.next_action_type, + redirect_to_url: RedirectUrl { + return_url, + url: n.redirect_to_url, + }, + }) +} + #[derive(Default, Eq, PartialEq, Serialize)] pub struct StripeSetupIntentResponse { pub id: Option, @@ -241,8 +313,35 @@ pub struct StripeSetupIntentResponse { #[serde(with = "common_utils::custom_serde::iso8601::option")] pub created: Option, pub customer: Option, - pub refunds: Option>, + pub refunds: Option>, pub mandate_id: Option, + pub next_action: Option, + pub last_payment_error: Option, + pub charges: payment_intent::Charges, +} + +#[derive(Default, Eq, PartialEq, Serialize)] +pub struct LastPaymentError { + charge: Option, + code: Option, + decline_code: Option, + message: String, + param: Option, + payment_method: StripePaymentMethod, + #[serde(rename = "type")] + error_type: String, +} + +#[derive(Default, Eq, PartialEq, Serialize)] +pub struct StripePaymentMethod { + #[serde(rename = "id")] + payment_method_id: String, + object: &'static str, + card: Option, + created: u64, + #[serde(rename = "type")] + method_type: String, + livemode: bool, } impl From for StripeSetupIntentResponse { @@ -251,11 +350,36 @@ impl From for StripeSetupIntentResponse { object: "setup_intent".to_owned(), status: StripeSetupStatus::from(resp.status), client_secret: resp.client_secret, + charges: payment_intent::Charges::new(), created: resp.created, customer: resp.customer_id, id: resp.payment_id, - refunds: resp.refunds, + refunds: resp + .refunds + .map(|a| a.into_iter().map(Into::into).collect()), mandate_id: resp.mandate_id, + next_action: into_stripe_next_action(resp.next_action, resp.return_url), + last_payment_error: resp.error_code.map(|code| -> LastPaymentError { + LastPaymentError { + charge: None, + code: Some(code.to_owned()), + decline_code: None, + message: resp + .error_message + .unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()), + param: None, + payment_method: StripePaymentMethod { + payment_method_id: "place_holder_id".to_string(), + object: "payment_method", + card: None, + created: u64::try_from(date_time::now().assume_utc().unix_timestamp()) + .unwrap_or_default(), + method_type: "card".to_string(), + livemode: false, + }, + error_type: code, + } + }), } } } diff --git a/crates/router/src/configs/settings.rs b/crates/router/src/configs/settings.rs index f246f9eb42..9a29cd23a1 100644 --- a/crates/router/src/configs/settings.rs +++ b/crates/router/src/configs/settings.rs @@ -266,6 +266,7 @@ pub struct Jwekey { pub locker_decryption_key2: String, pub vault_encryption_key: String, pub vault_private_key: String, + pub tunnel_private_key: String, } #[derive(Debug, Deserialize, Clone, Default)] diff --git a/crates/router/src/connector/stripe.rs b/crates/router/src/connector/stripe.rs index 2f74ad756c..5e6797a096 100644 --- a/crates/router/src/connector/stripe.rs +++ b/crates/router/src/connector/stripe.rs @@ -489,20 +489,22 @@ impl types::PaymentsResponseData: Clone, { let id = data.request.connector_transaction_id.clone(); - let response: transformers::PaymentIntentSyncResponse = - match id.get_connector_transaction_id() { - Ok(x) if x.starts_with("set") => res - .response - .parse_struct("SetupIntentSyncResponse") - .change_context(errors::ConnectorError::ResponseDeserializationFailed), - Ok(_) => res - .response - .parse_struct("PaymentIntentSyncResponse") - .change_context(errors::ConnectorError::ResponseDeserializationFailed), - Err(err) => { - Err(err).change_context(errors::ConnectorError::MissingConnectorTransactionID) - } - }?; + let response: transformers::PaymentIntentSyncResponse = match id + .get_connector_transaction_id() + { + Ok(x) if x.starts_with("set") => res + .response + .parse_struct::("SetupIntentSyncResponse") + .change_context(errors::ConnectorError::ResponseDeserializationFailed) + .map(Into::into), + Ok(_) => res + .response + .parse_struct("PaymentIntentSyncResponse") + .change_context(errors::ConnectorError::ResponseDeserializationFailed), + Err(err) => { + Err(err).change_context(errors::ConnectorError::MissingConnectorTransactionID) + } + }?; types::RouterData::try_from(types::ResponseRouterData { response, diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs index 536b29387a..e2d9d7f4d4 100644 --- a/crates/router/src/core/payments/helpers.rs +++ b/crates/router/src/core/payments/helpers.rs @@ -1,12 +1,14 @@ use std::borrow::Cow; -use base64::Engine; use common_utils::{ ext_traits::{AsyncExt, ByteSliceExt, ValueExt}, fp_utils, }; // TODO : Evaluate all the helper functions () use error_stack::{report, IntoReport, ResultExt}; +#[cfg(feature = "kms")] +use external_services::kms; +use josekit::jwe; use masking::{ExposeOptionInterface, PeekInterface}; use router_env::{instrument, tracing}; use storage_models::{enums, merchant_account, payment_intent}; @@ -1546,11 +1548,12 @@ impl MerchantConnectorAccountType { } pub async fn get_merchant_connector_account( - db: &dyn StorageInterface, + state: &AppState, merchant_id: &str, connector_label: &str, creds_identifier: Option, ) -> RouterResult { + let db = &*state.store; match creds_identifier { Some(creds_identifier) => { let mca_config = db @@ -1560,20 +1563,35 @@ pub async fn get_merchant_connector_account( errors::ApiErrorResponse::MerchantConnectorAccountNotFound, )?; - let cached_mca = consts::BASE64_ENGINE - .decode(mca_config.config.as_bytes()) - .into_report() - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable( - "Failed to decode merchant_connector_details sent in request and then put in cache", - )? - .parse_struct("MerchantConnectorDetails") - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable( - "Failed to parse merchant_connector_details sent in request and then put in cache", - )?; + #[cfg(feature = "kms")] + let kms_config = &state.conf.kms; - Ok(MerchantConnectorAccountType::CacheVal(cached_mca)) + #[cfg(feature = "kms")] + let private_key = kms::get_kms_client(kms_config) + .await + .decrypt(state.conf.jwekey.tunnel_private_key.to_owned()) + .await + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Error getting tunnel private key")?; + + #[cfg(not(feature = "kms"))] + let private_key = state.conf.jwekey.tunnel_private_key.to_owned(); + + let decrypted_mca = services::decrypt_jwe(mca_config.config.as_str(), services::KeyIdCheck::SkipKeyIdCheck, private_key, jwe::RSA_OAEP_256) + .await + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable( + "Failed to decrypt merchant_connector_details sent in request and then put in cache", + )?; + + let res = String::into_bytes(decrypted_mca) + .parse_struct("MerchantConnectorDetails") + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable( + "Failed to parse merchant_connector_details sent in request and then put in cache", + )?; + + Ok(MerchantConnectorAccountType::CacheVal(res)) } None => db .find_merchant_connector_account_by_merchant_id_connector_label( diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index ba8dcfd474..83875ca8a2 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -44,9 +44,8 @@ where connector_id, ); - let db = &*state.store; merchant_connector_account = helpers::get_merchant_connector_account( - db, + state, merchant_account.merchant_id.as_str(), &connector_label, payment_data.creds_identifier.to_owned(), @@ -695,6 +694,7 @@ impl TryFrom> for types::VerifyRequestDat off_session: payment_data.mandate_id.as_ref().map(|_| true), mandate_id: payment_data.mandate_id.clone(), setup_mandate_details: payment_data.setup_mandate, + return_url: payment_data.payment_intent.return_url, }) } } diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs index bed8baa772..4611cc3ebc 100644 --- a/crates/router/src/core/utils.rs +++ b/crates/router/src/core/utils.rs @@ -30,8 +30,6 @@ pub async fn construct_refund_router_data<'a, F>( refund: &'a storage::Refund, creds_identifier: Option, ) -> RouterResult> { - let db = &*state.store; - let connector_label = helpers::get_connector_label( payment_intent.business_country, &payment_intent.business_label, @@ -40,7 +38,7 @@ pub async fn construct_refund_router_data<'a, F>( ); let merchant_connector_account = helpers::get_merchant_connector_account( - db, + state, merchant_account.merchant_id.as_str(), &connector_label, creds_identifier, @@ -234,7 +232,6 @@ pub async fn construct_accept_dispute_router_data<'a>( merchant_account: &storage::MerchantAccount, dispute: &storage::Dispute, ) -> RouterResult { - let db = &*state.store; let connector_id = &dispute.connector; let connector_label = helpers::get_connector_label( payment_intent.business_country, @@ -243,7 +240,7 @@ pub async fn construct_accept_dispute_router_data<'a>( connector_id, ); let merchant_connector_account = helpers::get_merchant_connector_account( - db, + state, merchant_account.merchant_id.as_str(), &connector_label, None, @@ -296,7 +293,6 @@ pub async fn construct_submit_evidence_router_data<'a>( dispute: &storage::Dispute, submit_evidence_request_data: types::SubmitEvidenceRequestData, ) -> RouterResult { - let db = &*state.store; let connector_id = &dispute.connector; let connector_label = helpers::get_connector_label( payment_intent.business_country, @@ -305,7 +301,7 @@ pub async fn construct_submit_evidence_router_data<'a>( connector_id, ); let merchant_connector_account = helpers::get_merchant_connector_account( - db, + state, merchant_account.merchant_id.as_str(), &connector_label, None, @@ -356,7 +352,6 @@ pub async fn construct_upload_file_router_data<'a>( connector_id: &str, file_key: String, ) -> RouterResult { - let db = &*state.store; let connector_label = helpers::get_connector_label( payment_intent.business_country, &payment_intent.business_label, @@ -364,7 +359,7 @@ pub async fn construct_upload_file_router_data<'a>( connector_id, ); let merchant_connector_account = helpers::get_merchant_connector_account( - db, + state, merchant_account.merchant_id.as_str(), &connector_label, None, @@ -418,7 +413,7 @@ pub async fn construct_defend_dispute_router_data<'a>( merchant_account: &storage::MerchantAccount, dispute: &storage::Dispute, ) -> RouterResult { - let db = &*state.store; + let _db = &*state.store; let connector_id = &dispute.connector; let connector_label = helpers::get_connector_label( payment_intent.business_country, @@ -427,7 +422,7 @@ pub async fn construct_defend_dispute_router_data<'a>( connector_id, ); let merchant_connector_account = helpers::get_merchant_connector_account( - db, + state, merchant_account.merchant_id.as_str(), &connector_label, None, diff --git a/crates/router/src/types.rs b/crates/router/src/types.rs index aecbbfe6bd..d67dd9f7b4 100644 --- a/crates/router/src/types.rs +++ b/crates/router/src/types.rs @@ -299,6 +299,7 @@ pub struct VerifyRequestData { pub setup_future_usage: Option, pub off_session: Option, pub setup_mandate_details: Option, + pub return_url: Option, } #[derive(Debug, Clone)]