From fb1760b1d8b5ca55dbaa93ab18f9fba9e7930e17 Mon Sep 17 00:00:00 2001 From: Prajjwal Kumar Date: Thu, 14 Sep 2023 17:20:37 +0530 Subject: [PATCH] refactor(router): get route for applepay_verified_domains (#2157) --- crates/api_models/src/verifications.rs | 15 ++- crates/router/src/core.rs | 2 + .../src/{utils => core}/verification.rs | 103 +++++------------- crates/router/src/core/verification/utils.rs | 88 +++++++++++++++ crates/router/src/routes/app.rs | 6 +- crates/router/src/routes/verification.rs | 30 ++++- crates/router/src/utils.rs | 2 - 7 files changed, 157 insertions(+), 89 deletions(-) rename crates/router/src/{utils => core}/verification.rs (59%) create mode 100644 crates/router/src/core/verification/utils.rs diff --git a/crates/api_models/src/verifications.rs b/crates/api_models/src/verifications.rs index 22e9a0194e..e8aff66015 100644 --- a/crates/api_models/src/verifications.rs +++ b/crates/api_models/src/verifications.rs @@ -1,6 +1,6 @@ /// The request body for verification of merchant (everything except domain_names are prefilled) #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] -#[serde(rename_all = "camelCase")] +#[serde(rename_all = "snake_case")] pub struct ApplepayMerchantVerificationConfigs { pub domain_names: Vec, pub encrypt_to: String, @@ -10,7 +10,7 @@ pub struct ApplepayMerchantVerificationConfigs { /// The derivation point for domain names from request body #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] -#[serde(rename_all = "camelCase")] +#[serde(rename_all = "snake_case")] pub struct ApplepayMerchantVerificationRequest { pub domain_names: Vec, pub merchant_connector_account_id: String, @@ -18,22 +18,21 @@ pub struct ApplepayMerchantVerificationRequest { /// Response to be sent for the verify/applepay api #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] -#[serde(rename_all = "camelCase")] +#[serde(rename_all = "snake_case")] pub struct ApplepayMerchantResponse { pub status_message: String, - pub status_code: u16, } /// QueryParams to be send by the merchant for fetching the verified domains #[derive(Debug, serde::Deserialize)] -#[serde(rename_all = "camelCase")] +#[serde(rename_all = "snake_case")] pub struct ApplepayGetVerifiedDomainsParam { - pub business_profile_id: String, + pub merchant_id: String, + pub merchant_connector_account_id: String, } /// Response to be sent for derivation of the already verified domains #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] -#[serde(rename_all = "camelCase")] +#[serde(rename_all = "snake_case")] pub struct ApplepayVerifiedDomainsResponse { - pub status_code: u16, pub verified_domains: Vec, } diff --git a/crates/router/src/core.rs b/crates/router/src/core.rs index c01bdf6fb7..545553cae4 100644 --- a/crates/router/src/core.rs +++ b/crates/router/src/core.rs @@ -15,4 +15,6 @@ pub mod payments; pub mod payouts; pub mod refunds; pub mod utils; +#[cfg(all(feature = "olap", feature = "kms"))] +pub mod verification; pub mod webhooks; diff --git a/crates/router/src/utils/verification.rs b/crates/router/src/core/verification.rs similarity index 59% rename from crates/router/src/utils/verification.rs rename to crates/router/src/core/verification.rs index b0613540c5..cc2162908a 100644 --- a/crates/router/src/utils/verification.rs +++ b/crates/router/src/core/verification.rs @@ -1,17 +1,17 @@ +pub mod utils; use actix_web::web; use api_models::verifications::{self, ApplepayMerchantResponse}; -use common_utils::errors::CustomResult; -use error_stack::{Report, ResultExt}; +use common_utils::{errors::CustomResult, ext_traits::Encode}; +use error_stack::ResultExt; #[cfg(feature = "kms")] use external_services::kms; use crate::{ core::errors::{self, api_error_response, utils::StorageErrorExt}, + db::StorageInterface, headers, logger, routes::AppState, services, types, - types::storage, - utils, }; const APPLEPAY_INTERNAL_MERCHANT_NAME: &str = "Applepay_merchant"; @@ -33,6 +33,7 @@ pub async fn verify_merchant_creds_for_applepay( let encrypted_cert = &state.conf.applepay_merchant_configs.merchant_cert; let encrypted_key = &state.conf.applepay_merchant_configs.merchant_cert_key; let applepay_endpoint = &state.conf.applepay_merchant_configs.applepay_endpoint; + let applepay_internal_merchant_identifier = kms::get_kms_client(kms_config) .await .decrypt(encrypted_merchant_identifier) @@ -60,10 +61,10 @@ pub async fn verify_merchant_creds_for_applepay( let applepay_req = types::RequestBody::log_and_get_request_body( &request_body, - utils::Encode::::encode_to_string_of_json, - ) - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Failed to encode ApplePay session request to a string of json")?; + Encode::::encode_to_string_of_json, + ) + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Failed to encode ApplePay session request to a string of json")?; let apple_pay_merch_verification_req = services::RequestBuilder::new() .method(services::Method::Post) @@ -79,7 +80,7 @@ pub async fn verify_merchant_creds_for_applepay( .build(); let response = services::call_connector_api(state, apple_pay_merch_verification_req).await; - log_applepay_verification_response_if_error(&response); + utils::log_applepay_verification_response_if_error(&response); let applepay_response = response.change_context(api_error_response::ApiErrorResponse::InternalServerError)?; @@ -87,7 +88,7 @@ pub async fn verify_merchant_creds_for_applepay( // Error is already logged Ok(match applepay_response { Ok(_) => { - check_existence_and_add_domain_to_db( + utils::check_existence_and_add_domain_to_db( state, merchant_id, body.merchant_connector_account_id.clone(), @@ -96,93 +97,43 @@ pub async fn verify_merchant_creds_for_applepay( .await .change_context(api_error_response::ApiErrorResponse::InternalServerError)?; services::api::ApplicationResponse::Json(ApplepayMerchantResponse { - status_code: 200, status_message: "Applepay verification Completed".to_string(), }) } Err(error) => { logger::error!(?error); services::api::ApplicationResponse::Json(ApplepayMerchantResponse { - status_code: 200, status_message: "Applepay verification Failed".to_string(), }) } }) } -async fn check_existence_and_add_domain_to_db( - state: &AppState, + +pub async fn get_verified_apple_domains_with_mid_mca_id( + db: &dyn StorageInterface, merchant_id: String, merchant_connector_id: String, - domain_from_req: Vec, -) -> CustomResult, errors::ApiErrorResponse> { - let key_store = state - .store - .get_merchant_key_store_by_merchant_id( - &merchant_id, - &state.store.get_master_key().to_vec().into(), - ) +) -> CustomResult< + services::ApplicationResponse, + api_error_response::ApiErrorResponse, +> { + let key_store = db + .get_merchant_key_store_by_merchant_id(&merchant_id, &db.get_master_key().to_vec().into()) .await .to_not_found_response(errors::ApiErrorResponse::InternalServerError)?; - let merchant_connector_account = state - .store + let verified_domains = db .find_by_merchant_connector_account_merchant_id_merchant_connector_id( - &merchant_id, - &merchant_connector_id, + merchant_id.as_str(), + merchant_connector_id.as_str(), &key_store, ) .await - .change_context(errors::ApiErrorResponse::InternalServerError)?; - - let mut already_verified_domains = merchant_connector_account + .change_context(api_error_response::ApiErrorResponse::ResourceIdNotFound)? .applepay_verified_domains - .clone() .unwrap_or_default(); - let mut new_verified_domains: Vec = domain_from_req - .into_iter() - .filter(|req_domain| !already_verified_domains.contains(req_domain)) - .collect(); - - already_verified_domains.append(&mut new_verified_domains); - let updated_mca = storage::MerchantConnectorAccountUpdate::Update { - merchant_id: None, - connector_type: None, - connector_name: None, - connector_account_details: None, - test_mode: None, - disabled: None, - merchant_connector_id: None, - payment_methods_enabled: None, - metadata: None, - frm_configs: None, - connector_webhook_details: None, - applepay_verified_domains: Some(already_verified_domains.clone()), - }; - state - .store - .update_merchant_connector_account( - merchant_connector_account, - updated_mca.into(), - &key_store, - ) - .await - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable_lazy(|| { - format!("Failed while updating MerchantConnectorAccount: id: {merchant_connector_id}") - })?; - - Ok(already_verified_domains.clone()) -} - -fn log_applepay_verification_response_if_error( - response: &Result, Report>, -) { - if let Err(error) = response.as_ref() { - logger::error!(?error); - }; - response - .as_ref() - .ok() - .map(|res| res.as_ref().map_err(|error| logger::error!(?error))); + Ok(services::api::ApplicationResponse::Json( + api_models::verifications::ApplepayVerifiedDomainsResponse { verified_domains }, + )) } diff --git a/crates/router/src/core/verification/utils.rs b/crates/router/src/core/verification/utils.rs new file mode 100644 index 0000000000..36bf4b7d71 --- /dev/null +++ b/crates/router/src/core/verification/utils.rs @@ -0,0 +1,88 @@ +use common_utils::errors::CustomResult; +use error_stack::{Report, ResultExt}; + +use crate::{ + core::errors::{self, utils::StorageErrorExt}, + logger, + routes::AppState, + types, + types::storage, +}; + +pub async fn check_existence_and_add_domain_to_db( + state: &AppState, + merchant_id: String, + merchant_connector_id: String, + domain_from_req: Vec, +) -> CustomResult, errors::ApiErrorResponse> { + let key_store = state + .store + .get_merchant_key_store_by_merchant_id( + &merchant_id, + &state.store.get_master_key().to_vec().into(), + ) + .await + .to_not_found_response(errors::ApiErrorResponse::InternalServerError)?; + + let merchant_connector_account = state + .store + .find_by_merchant_connector_account_merchant_id_merchant_connector_id( + &merchant_id, + &merchant_connector_id, + &key_store, + ) + .await + .change_context(errors::ApiErrorResponse::InternalServerError)?; + + let mut already_verified_domains = merchant_connector_account + .applepay_verified_domains + .clone() + .unwrap_or_default(); + + let mut new_verified_domains: Vec = domain_from_req + .into_iter() + .filter(|req_domain| !already_verified_domains.contains(req_domain)) + .collect(); + + already_verified_domains.append(&mut new_verified_domains); + let updated_mca = storage::MerchantConnectorAccountUpdate::Update { + merchant_id: None, + connector_type: None, + connector_name: None, + connector_account_details: None, + test_mode: None, + disabled: None, + merchant_connector_id: None, + payment_methods_enabled: None, + metadata: None, + frm_configs: None, + connector_webhook_details: None, + applepay_verified_domains: Some(already_verified_domains.clone()), + }; + state + .store + .update_merchant_connector_account( + merchant_connector_account, + updated_mca.into(), + &key_store, + ) + .await + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable_lazy(|| { + format!("Failed while updating MerchantConnectorAccount: id: {merchant_connector_id}") + })?; + + Ok(already_verified_domains.clone()) +} + +pub fn log_applepay_verification_response_if_error( + response: &Result, Report>, +) { + if let Err(error) = response.as_ref() { + logger::error!(applepay_domain_verification_error= ?error); + }; + response.as_ref().ok().map(|res| { + res.as_ref() + .map_err(|error| logger::error!(applepay_domain_verification_error= ?error)) + }); +} diff --git a/crates/router/src/routes/app.rs b/crates/router/src/routes/app.rs index 8c529a42d5..d5691279bc 100644 --- a/crates/router/src/routes/app.rs +++ b/crates/router/src/routes/app.rs @@ -12,7 +12,7 @@ use super::dummy_connector::*; #[cfg(feature = "payouts")] use super::payouts::*; #[cfg(all(feature = "olap", feature = "kms"))] -use super::verification::apple_pay_merchant_registration; +use super::verification::{apple_pay_merchant_registration, retrieve_apple_pay_verified_domains}; #[cfg(feature = "olap")] use super::{admin::*, api_keys::*, disputes::*, files::*}; use super::{cache::*, health::*}; @@ -589,5 +589,9 @@ impl Verify { web::resource("/{merchant_id}/apple_pay") .route(web::post().to(apple_pay_merchant_registration)), ) + .service( + web::resource("/applepay_verified_domains") + .route(web::get().to(retrieve_apple_pay_verified_domains)), + ) } } diff --git a/crates/router/src/routes/verification.rs b/crates/router/src/routes/verification.rs index 1cb7ed6256..e8985bbde5 100644 --- a/crates/router/src/routes/verification.rs +++ b/crates/router/src/routes/verification.rs @@ -4,11 +4,10 @@ use router_env::{instrument, tracing, Flow}; use super::app::AppState; use crate::{ + core::verification, services::{api, authentication as auth}, - utils::verification, }; -#[cfg(all(feature = "olap", feature = "kms"))] #[instrument(skip_all, fields(flow = ?Flow::Verification))] pub async fn apple_pay_merchant_registration( state: web::Data, @@ -36,3 +35,30 @@ pub async fn apple_pay_merchant_registration( ) .await } + +#[instrument(skip_all, fields(flow = ?Flow::Verification))] +pub async fn retrieve_apple_pay_verified_domains( + state: web::Data, + req: HttpRequest, + params: web::Query, +) -> impl Responder { + let flow = Flow::Verification; + let merchant_id = ¶ms.merchant_id; + let mca_id = ¶ms.merchant_connector_account_id; + + api::server_wrap( + flow, + state.get_ref(), + &req, + merchant_id.clone(), + |state, _, _| { + verification::get_verified_apple_domains_with_mid_mca_id( + &*state.store, + merchant_id.to_string(), + mca_id.clone(), + ) + }, + auth::auth_type(&auth::ApiKeyAuth, &auth::JWTAuth, req.headers()), + ) + .await +} diff --git a/crates/router/src/utils.rs b/crates/router/src/utils.rs index b9e4504a99..94571bb1fc 100644 --- a/crates/router/src/utils.rs +++ b/crates/router/src/utils.rs @@ -1,8 +1,6 @@ pub mod custom_serde; pub mod db_utils; pub mod ext_traits; -#[cfg(all(feature = "olap", feature = "kms"))] -pub mod verification; #[cfg(feature = "kv_store")] pub mod storage_partitioning;