refactor(router): get route for applepay_verified_domains (#2157)

This commit is contained in:
Prajjwal Kumar
2023-09-14 17:20:37 +05:30
committed by GitHub
parent 05696d326f
commit fb1760b1d8
7 changed files with 157 additions and 89 deletions

View File

@ -1,6 +1,6 @@
/// The request body for verification of merchant (everything except domain_names are prefilled) /// The request body for verification of merchant (everything except domain_names are prefilled)
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "snake_case")]
pub struct ApplepayMerchantVerificationConfigs { pub struct ApplepayMerchantVerificationConfigs {
pub domain_names: Vec<String>, pub domain_names: Vec<String>,
pub encrypt_to: String, pub encrypt_to: String,
@ -10,7 +10,7 @@ pub struct ApplepayMerchantVerificationConfigs {
/// The derivation point for domain names from request body /// The derivation point for domain names from request body
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "snake_case")]
pub struct ApplepayMerchantVerificationRequest { pub struct ApplepayMerchantVerificationRequest {
pub domain_names: Vec<String>, pub domain_names: Vec<String>,
pub merchant_connector_account_id: String, pub merchant_connector_account_id: String,
@ -18,22 +18,21 @@ pub struct ApplepayMerchantVerificationRequest {
/// Response to be sent for the verify/applepay api /// Response to be sent for the verify/applepay api
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "snake_case")]
pub struct ApplepayMerchantResponse { pub struct ApplepayMerchantResponse {
pub status_message: String, pub status_message: String,
pub status_code: u16,
} }
/// QueryParams to be send by the merchant for fetching the verified domains /// QueryParams to be send by the merchant for fetching the verified domains
#[derive(Debug, serde::Deserialize)] #[derive(Debug, serde::Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "snake_case")]
pub struct ApplepayGetVerifiedDomainsParam { 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 /// Response to be sent for derivation of the already verified domains
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "snake_case")]
pub struct ApplepayVerifiedDomainsResponse { pub struct ApplepayVerifiedDomainsResponse {
pub status_code: u16,
pub verified_domains: Vec<String>, pub verified_domains: Vec<String>,
} }

View File

@ -15,4 +15,6 @@ pub mod payments;
pub mod payouts; pub mod payouts;
pub mod refunds; pub mod refunds;
pub mod utils; pub mod utils;
#[cfg(all(feature = "olap", feature = "kms"))]
pub mod verification;
pub mod webhooks; pub mod webhooks;

View File

@ -1,17 +1,17 @@
pub mod utils;
use actix_web::web; use actix_web::web;
use api_models::verifications::{self, ApplepayMerchantResponse}; use api_models::verifications::{self, ApplepayMerchantResponse};
use common_utils::errors::CustomResult; use common_utils::{errors::CustomResult, ext_traits::Encode};
use error_stack::{Report, ResultExt}; use error_stack::ResultExt;
#[cfg(feature = "kms")] #[cfg(feature = "kms")]
use external_services::kms; use external_services::kms;
use crate::{ use crate::{
core::errors::{self, api_error_response, utils::StorageErrorExt}, core::errors::{self, api_error_response, utils::StorageErrorExt},
db::StorageInterface,
headers, logger, headers, logger,
routes::AppState, routes::AppState,
services, types, services, types,
types::storage,
utils,
}; };
const APPLEPAY_INTERNAL_MERCHANT_NAME: &str = "Applepay_merchant"; 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_cert = &state.conf.applepay_merchant_configs.merchant_cert;
let encrypted_key = &state.conf.applepay_merchant_configs.merchant_cert_key; let encrypted_key = &state.conf.applepay_merchant_configs.merchant_cert_key;
let applepay_endpoint = &state.conf.applepay_merchant_configs.applepay_endpoint; let applepay_endpoint = &state.conf.applepay_merchant_configs.applepay_endpoint;
let applepay_internal_merchant_identifier = kms::get_kms_client(kms_config) let applepay_internal_merchant_identifier = kms::get_kms_client(kms_config)
.await .await
.decrypt(encrypted_merchant_identifier) .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( let applepay_req = types::RequestBody::log_and_get_request_body(
&request_body, &request_body,
utils::Encode::<verifications::ApplepayMerchantVerificationRequest>::encode_to_string_of_json, Encode::<verifications::ApplepayMerchantVerificationRequest>::encode_to_string_of_json,
) )
.change_context(errors::ApiErrorResponse::InternalServerError) .change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed to encode ApplePay session request to a string of json")?; .attach_printable("Failed to encode ApplePay session request to a string of json")?;
let apple_pay_merch_verification_req = services::RequestBuilder::new() let apple_pay_merch_verification_req = services::RequestBuilder::new()
.method(services::Method::Post) .method(services::Method::Post)
@ -79,7 +80,7 @@ pub async fn verify_merchant_creds_for_applepay(
.build(); .build();
let response = services::call_connector_api(state, apple_pay_merch_verification_req).await; 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 = let applepay_response =
response.change_context(api_error_response::ApiErrorResponse::InternalServerError)?; response.change_context(api_error_response::ApiErrorResponse::InternalServerError)?;
@ -87,7 +88,7 @@ pub async fn verify_merchant_creds_for_applepay(
// Error is already logged // Error is already logged
Ok(match applepay_response { Ok(match applepay_response {
Ok(_) => { Ok(_) => {
check_existence_and_add_domain_to_db( utils::check_existence_and_add_domain_to_db(
state, state,
merchant_id, merchant_id,
body.merchant_connector_account_id.clone(), body.merchant_connector_account_id.clone(),
@ -96,93 +97,43 @@ pub async fn verify_merchant_creds_for_applepay(
.await .await
.change_context(api_error_response::ApiErrorResponse::InternalServerError)?; .change_context(api_error_response::ApiErrorResponse::InternalServerError)?;
services::api::ApplicationResponse::Json(ApplepayMerchantResponse { services::api::ApplicationResponse::Json(ApplepayMerchantResponse {
status_code: 200,
status_message: "Applepay verification Completed".to_string(), status_message: "Applepay verification Completed".to_string(),
}) })
} }
Err(error) => { Err(error) => {
logger::error!(?error); logger::error!(?error);
services::api::ApplicationResponse::Json(ApplepayMerchantResponse { services::api::ApplicationResponse::Json(ApplepayMerchantResponse {
status_code: 200,
status_message: "Applepay verification Failed".to_string(), 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_id: String,
merchant_connector_id: String, merchant_connector_id: String,
domain_from_req: Vec<String>, ) -> CustomResult<
) -> CustomResult<Vec<String>, errors::ApiErrorResponse> { services::ApplicationResponse<api_models::verifications::ApplepayVerifiedDomainsResponse>,
let key_store = state api_error_response::ApiErrorResponse,
.store > {
.get_merchant_key_store_by_merchant_id( let key_store = db
&merchant_id, .get_merchant_key_store_by_merchant_id(&merchant_id, &db.get_master_key().to_vec().into())
&state.store.get_master_key().to_vec().into(),
)
.await .await
.to_not_found_response(errors::ApiErrorResponse::InternalServerError)?; .to_not_found_response(errors::ApiErrorResponse::InternalServerError)?;
let merchant_connector_account = state let verified_domains = db
.store
.find_by_merchant_connector_account_merchant_id_merchant_connector_id( .find_by_merchant_connector_account_merchant_id_merchant_connector_id(
&merchant_id, merchant_id.as_str(),
&merchant_connector_id, merchant_connector_id.as_str(),
&key_store, &key_store,
) )
.await .await
.change_context(errors::ApiErrorResponse::InternalServerError)?; .change_context(api_error_response::ApiErrorResponse::ResourceIdNotFound)?
let mut already_verified_domains = merchant_connector_account
.applepay_verified_domains .applepay_verified_domains
.clone()
.unwrap_or_default(); .unwrap_or_default();
let mut new_verified_domains: Vec<String> = domain_from_req Ok(services::api::ApplicationResponse::Json(
.into_iter() api_models::verifications::ApplepayVerifiedDomainsResponse { verified_domains },
.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<Result<types::Response, types::Response>, Report<errors::ApiClientError>>,
) {
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)));
} }

View File

@ -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<String>,
) -> CustomResult<Vec<String>, 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<String> = 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<Result<types::Response, types::Response>, Report<errors::ApiClientError>>,
) {
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))
});
}

View File

@ -12,7 +12,7 @@ use super::dummy_connector::*;
#[cfg(feature = "payouts")] #[cfg(feature = "payouts")]
use super::payouts::*; use super::payouts::*;
#[cfg(all(feature = "olap", feature = "kms"))] #[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")] #[cfg(feature = "olap")]
use super::{admin::*, api_keys::*, disputes::*, files::*}; use super::{admin::*, api_keys::*, disputes::*, files::*};
use super::{cache::*, health::*}; use super::{cache::*, health::*};
@ -589,5 +589,9 @@ impl Verify {
web::resource("/{merchant_id}/apple_pay") web::resource("/{merchant_id}/apple_pay")
.route(web::post().to(apple_pay_merchant_registration)), .route(web::post().to(apple_pay_merchant_registration)),
) )
.service(
web::resource("/applepay_verified_domains")
.route(web::get().to(retrieve_apple_pay_verified_domains)),
)
} }
} }

View File

@ -4,11 +4,10 @@ use router_env::{instrument, tracing, Flow};
use super::app::AppState; use super::app::AppState;
use crate::{ use crate::{
core::verification,
services::{api, authentication as auth}, services::{api, authentication as auth},
utils::verification,
}; };
#[cfg(all(feature = "olap", feature = "kms"))]
#[instrument(skip_all, fields(flow = ?Flow::Verification))] #[instrument(skip_all, fields(flow = ?Flow::Verification))]
pub async fn apple_pay_merchant_registration( pub async fn apple_pay_merchant_registration(
state: web::Data<AppState>, state: web::Data<AppState>,
@ -36,3 +35,30 @@ pub async fn apple_pay_merchant_registration(
) )
.await .await
} }
#[instrument(skip_all, fields(flow = ?Flow::Verification))]
pub async fn retrieve_apple_pay_verified_domains(
state: web::Data<AppState>,
req: HttpRequest,
params: web::Query<verifications::ApplepayGetVerifiedDomainsParam>,
) -> impl Responder {
let flow = Flow::Verification;
let merchant_id = &params.merchant_id;
let mca_id = &params.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
}

View File

@ -1,8 +1,6 @@
pub mod custom_serde; pub mod custom_serde;
pub mod db_utils; pub mod db_utils;
pub mod ext_traits; pub mod ext_traits;
#[cfg(all(feature = "olap", feature = "kms"))]
pub mod verification;
#[cfg(feature = "kv_store")] #[cfg(feature = "kv_store")]
pub mod storage_partitioning; pub mod storage_partitioning;