Skip to content

Commit

Permalink
fix(connector_onboarding): Check if connector exists for the merchant…
Browse files Browse the repository at this point in the history
… account and add reset tracking id API (#3229)
  • Loading branch information
ThisIsMani authored Jan 16, 2024
1 parent 1bbd9d5 commit 58cc8d6
Show file tree
Hide file tree
Showing 10 changed files with 186 additions and 28 deletions.
6 changes: 6 additions & 0 deletions crates/api_models/src/connector_onboarding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,9 @@ pub struct PayPalOnboardingDone {
pub struct PayPalIntegrationDone {
pub connector_id: String,
}

#[derive(serde::Deserialize, serde::Serialize, Debug, Clone)]
pub struct ResetTrackingIdRequest {
pub connector_id: String,
pub connector: enums::Connector,
}
4 changes: 3 additions & 1 deletion crates/api_models/src/events/connector_onboarding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ use common_utils::events::{ApiEventMetric, ApiEventsType};

use crate::connector_onboarding::{
ActionUrlRequest, ActionUrlResponse, OnboardingStatus, OnboardingSyncRequest,
ResetTrackingIdRequest,
};

common_utils::impl_misc_api_event_type!(
ActionUrlRequest,
ActionUrlResponse,
OnboardingSyncRequest,
OnboardingStatus
OnboardingStatus,
ResetTrackingIdRequest
);
3 changes: 3 additions & 0 deletions crates/router/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ pub const VERIFY_CONNECTOR_ID_PREFIX: &str = "conn_verify";
#[cfg(feature = "olap")]
pub const VERIFY_CONNECTOR_MERCHANT_ID: &str = "test_merchant";

#[cfg(feature = "olap")]
pub const CONNECTOR_ONBOARDING_CONFIG_PREFIX: &str = "onboarding";

/// Max payment session expiry
pub const MAX_SESSION_EXPIRY: u32 = 7890000;

Expand Down
44 changes: 32 additions & 12 deletions crates/router/src/core/connector_onboarding.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use api_models::{connector_onboarding as api, enums};
use error_stack::ResultExt;
use masking::Secret;

use crate::{
Expand All @@ -19,16 +18,23 @@ pub trait AccessToken {

pub async fn get_action_url(
state: AppState,
user_from_token: auth::UserFromToken,
request: api::ActionUrlRequest,
) -> RouterResponse<api::ActionUrlResponse> {
utils::check_if_connector_exists(&state, &request.connector_id, &user_from_token.merchant_id)
.await?;

let connector_onboarding_conf = state.conf.connector_onboarding.clone();
let is_enabled = utils::is_enabled(request.connector, &connector_onboarding_conf);
let tracking_id =
utils::get_tracking_id_from_configs(&state, &request.connector_id, request.connector)
.await?;

match (is_enabled, request.connector) {
(Some(true), enums::Connector::Paypal) => {
let action_url = Box::pin(paypal::get_action_url_from_paypal(
state,
request.connector_id,
tracking_id,
request.return_url,
))
.await?;
Expand All @@ -49,40 +55,42 @@ pub async fn sync_onboarding_status(
user_from_token: auth::UserFromToken,
request: api::OnboardingSyncRequest,
) -> RouterResponse<api::OnboardingStatus> {
let merchant_account = user_from_token
.get_merchant_account(state.clone())
.await
.change_context(ApiErrorResponse::MerchantAccountNotFound)?;
utils::check_if_connector_exists(&state, &request.connector_id, &user_from_token.merchant_id)
.await?;

let connector_onboarding_conf = state.conf.connector_onboarding.clone();
let is_enabled = utils::is_enabled(request.connector, &connector_onboarding_conf);
let tracking_id =
utils::get_tracking_id_from_configs(&state, &request.connector_id, request.connector)
.await?;

match (is_enabled, request.connector) {
(Some(true), enums::Connector::Paypal) => {
let status = Box::pin(paypal::sync_merchant_onboarding_status(
state.clone(),
request.connector_id.clone(),
tracking_id,
))
.await?;
if let api::OnboardingStatus::PayPal(api::PayPalOnboardingStatus::Success(
ref inner_data,
ref paypal_onboarding_data,
)) = status
{
let connector_onboarding_conf = state.conf.connector_onboarding.clone();
let auth_details = oss_types::ConnectorAuthType::SignatureKey {
api_key: connector_onboarding_conf.paypal.client_secret,
key1: connector_onboarding_conf.paypal.client_id,
api_secret: Secret::new(inner_data.payer_id.clone()),
api_secret: Secret::new(paypal_onboarding_data.payer_id.clone()),
};
let some_data = paypal::update_mca(
let update_mca_data = paypal::update_mca(
&state,
&merchant_account,
user_from_token.merchant_id,
request.connector_id.to_owned(),
auth_details,
)
.await?;

return Ok(ApplicationResponse::Json(api::OnboardingStatus::PayPal(
api::PayPalOnboardingStatus::ConnectorIntegrated(some_data),
api::PayPalOnboardingStatus::ConnectorIntegrated(update_mca_data),
)));
}
Ok(ApplicationResponse::Json(status))
Expand All @@ -94,3 +102,15 @@ pub async fn sync_onboarding_status(
.into()),
}
}

pub async fn reset_tracking_id(
state: AppState,
user_from_token: auth::UserFromToken,
request: api::ResetTrackingIdRequest,
) -> RouterResponse<()> {
utils::check_if_connector_exists(&state, &request.connector_id, &user_from_token.merchant_id)
.await?;
utils::set_tracking_id_in_configs(&state, &request.connector_id, request.connector).await?;

Ok(ApplicationResponse::StatusOk)
}
20 changes: 8 additions & 12 deletions crates/router/src/core/connector_onboarding/paypal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ fn build_referral_url(state: AppState) -> String {

async fn build_referral_request(
state: AppState,
connector_id: String,
tracking_id: String,
return_url: String,
) -> RouterResult<Request> {
let access_token = utils::paypal::generate_access_token(state.clone()).await?;
let request_body = types::paypal::PartnerReferralRequest::new(connector_id, return_url);
let request_body = types::paypal::PartnerReferralRequest::new(tracking_id, return_url);

utils::paypal::build_paypal_post_request(
build_referral_url(state),
Expand All @@ -38,12 +38,12 @@ async fn build_referral_request(

pub async fn get_action_url_from_paypal(
state: AppState,
connector_id: String,
tracking_id: String,
return_url: String,
) -> RouterResult<String> {
let referral_request = Box::pin(build_referral_request(
state.clone(),
connector_id,
tracking_id,
return_url,
))
.await?;
Expand Down Expand Up @@ -137,7 +137,7 @@ async fn find_paypal_merchant_by_tracking_id(

pub async fn update_mca(
state: &AppState,
merchant_account: &oss_types::domain::MerchantAccount,
merchant_id: String,
connector_id: String,
auth_details: oss_types::ConnectorAuthType,
) -> RouterResult<oss_api_types::MerchantConnectorResponse> {
Expand All @@ -159,13 +159,9 @@ pub async fn update_mca(
connector_webhook_details: None,
pm_auth_config: None,
};
let mca_response = admin::update_payment_connector(
state.clone(),
&merchant_account.merchant_id,
&connector_id,
request,
)
.await?;
let mca_response =
admin::update_payment_connector(state.clone(), &merchant_id, &connector_id, request)
.await?;

match mca_response {
ApplicationResponse::Json(mca_data) => Ok(mca_data),
Expand Down
1 change: 1 addition & 0 deletions crates/router/src/routes/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -961,5 +961,6 @@ impl ConnectorOnboarding {
.app_data(web::Data::new(state))
.service(web::resource("/action_url").route(web::post().to(get_action_url)))
.service(web::resource("/sync").route(web::post().to(sync_onboarding_status)))
.service(web::resource("/reset_tracking_id").route(web::post().to(reset_tracking_id)))
}
}
21 changes: 20 additions & 1 deletion crates/router/src/routes/connector_onboarding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub async fn get_action_url(
state,
&http_req,
req_payload.clone(),
|state, _: auth::UserFromToken, req| core::get_action_url(state, req),
core::get_action_url,
&auth::JWTAuth(Permission::MerchantAccountWrite),
api_locking::LockAction::NotApplicable,
))
Expand All @@ -45,3 +45,22 @@ pub async fn sync_onboarding_status(
))
.await
}

pub async fn reset_tracking_id(
state: web::Data<AppState>,
http_req: HttpRequest,
json_payload: web::Json<api_types::ResetTrackingIdRequest>,
) -> HttpResponse {
let flow = Flow::ResetTrackingId;
let req_payload = json_payload.into_inner();
Box::pin(api::server_wrap(
flow.clone(),
state,
&http_req,
req_payload.clone(),
core::reset_tracking_id,
&auth::JWTAuth(Permission::MerchantAccountWrite),
api_locking::LockAction::NotApplicable,
))
.await
}
4 changes: 3 additions & 1 deletion crates/router/src/routes/lock_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,9 @@ impl From<Flow> for ApiIdentifier {
Self::UserRole
}

Flow::GetActionUrl | Flow::SyncOnboardingStatus => Self::ConnectorOnboarding,
Flow::GetActionUrl | Flow::SyncOnboardingStatus | Flow::ResetTrackingId => {
Self::ConnectorOnboarding
}
}
}
}
109 changes: 108 additions & 1 deletion crates/router/src/utils/connector_onboarding.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
use diesel_models::{ConfigNew, ConfigUpdate};
use error_stack::ResultExt;

use super::errors::StorageErrorExt;
use crate::{
consts,
core::errors::{api_error_response::NotImplementedMessage, ApiErrorResponse, RouterResult},
routes::app::settings,
routes::{app::settings, AppState},
types::{self, api::enums},
};

Expand Down Expand Up @@ -34,3 +39,105 @@ pub fn is_enabled(
_ => None,
}
}

pub async fn check_if_connector_exists(
state: &AppState,
connector_id: &str,
merchant_id: &str,
) -> RouterResult<()> {
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(ApiErrorResponse::MerchantAccountNotFound)?;

let _connector = state
.store
.find_by_merchant_connector_account_merchant_id_merchant_connector_id(
merchant_id,
connector_id,
&key_store,
)
.await
.to_not_found_response(ApiErrorResponse::MerchantConnectorAccountNotFound {
id: connector_id.to_string(),
})?;

Ok(())
}

pub async fn set_tracking_id_in_configs(
state: &AppState,
connector_id: &str,
connector: enums::Connector,
) -> RouterResult<()> {
let timestamp = common_utils::date_time::now_unix_timestamp().to_string();
let find_config = state
.store
.find_config_by_key(&build_key(connector_id, connector))
.await;

if find_config.is_ok() {
state
.store
.update_config_by_key(
&build_key(connector_id, connector),
ConfigUpdate::Update {
config: Some(timestamp),
},
)
.await
.change_context(ApiErrorResponse::InternalServerError)
.attach_printable("Error updating data in configs table")?;
} else if find_config
.as_ref()
.map_err(|e| e.current_context().is_db_not_found())
.err()
.unwrap_or(false)
{
state
.store
.insert_config(ConfigNew {
key: build_key(connector_id, connector),
config: timestamp,
})
.await
.change_context(ApiErrorResponse::InternalServerError)
.attach_printable("Error inserting data in configs table")?;
} else {
find_config.change_context(ApiErrorResponse::InternalServerError)?;
}

Ok(())
}

pub async fn get_tracking_id_from_configs(
state: &AppState,
connector_id: &str,
connector: enums::Connector,
) -> RouterResult<String> {
let timestamp = state
.store
.find_config_by_key_unwrap_or(
&build_key(connector_id, connector),
Some(common_utils::date_time::now_unix_timestamp().to_string()),
)
.await
.change_context(ApiErrorResponse::InternalServerError)
.attach_printable("Error getting data from configs table")?
.config;

Ok(format!("{}_{}", connector_id, timestamp))
}

fn build_key(connector_id: &str, connector: enums::Connector) -> String {
format!(
"{}_{}_{}",
consts::CONNECTOR_ONBOARDING_CONFIG_PREFIX,
connector,
connector_id,
)
}
2 changes: 2 additions & 0 deletions crates/router_env/src/logger/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,8 @@ pub enum Flow {
GetActionUrl,
/// Sync connector onboarding status
SyncOnboardingStatus,
/// Reset tracking id
ResetTrackingId,
/// Verify email Token
VerifyEmail,
/// Send verify email
Expand Down

0 comments on commit 58cc8d6

Please sign in to comment.