Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(router): add an api to migrate the apple pay certificates from connector metadata to connector_wallets_details column in merchant connector account #4790

Merged
merged 40 commits into from
Jun 6, 2024
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
1d41ab0
add column certificates in the merchant connector account
ShankarSinghC May 27, 2024
5957ad2
remove column certificates in the merchant connector account
ShankarSinghC May 28, 2024
582ee22
feat(router): add an api to migrate the apple pay certificates from c…
ShankarSinghC May 28, 2024
40fb53f
fix openapi error
ShankarSinghC May 28, 2024
60c4281
add connector_wallets_details in mca retrieve
ShankarSinghC May 28, 2024
9a47f30
docs(openapi): re-generate OpenAPI specification
hyperswitch-bot[bot] May 28, 2024
24c6a7d
Merge branch 'main' of https://github.com/juspay/hyperswitch into app…
ShankarSinghC May 28, 2024
47ef629
if create mca has apple pay details in the metadata insert it in the …
ShankarSinghC May 28, 2024
c1995c4
add connector_wallets_details in router data
ShankarSinghC May 29, 2024
290a854
Merge branch 'apple_pay/migrate-cert' of https://github.com/juspay/hy…
ShankarSinghC May 29, 2024
4689a4a
add connector_wallets_details fallback for mca create
ShankarSinghC May 29, 2024
7b9fcfc
remove connector_wallets_details from mca request
ShankarSinghC May 29, 2024
a9700b3
docs(openapi): re-generate OpenAPI specification
hyperswitch-bot[bot] May 29, 2024
f1e046e
add a ppc, ppc_key, ppc_at fields in apple pay session token
ShankarSinghC May 30, 2024
855b567
Merge branch 'apple_pay/migrate-cert' of https://github.com/juspay/hy…
ShankarSinghC May 30, 2024
200d2d5
generate openeapi spec
ShankarSinghC May 30, 2024
b86f448
remove connector_wallets_details from mca update request
ShankarSinghC May 30, 2024
9299f81
docs(openapi): re-generate OpenAPI specification
hyperswitch-bot[bot] May 30, 2024
2f62932
Merge branch 'main' of https://github.com/juspay/hyperswitch into app…
ShankarSinghC May 30, 2024
822e2aa
Merge branch 'apple_pay/migrate-cert' of https://github.com/juspay/hy…
ShankarSinghC May 30, 2024
09e9dd3
address pr comments
ShankarSinghC May 30, 2024
9658e95
Merge branch 'main' into apple_pay/migrate-cert
ShankarSinghC May 30, 2024
13ec3a2
address pr comments
ShankarSinghC Jun 1, 2024
7321758
Merge branch 'main' of https://github.com/juspay/hyperswitch into app…
ShankarSinghC Jun 1, 2024
0767c55
fix typos
ShankarSinghC Jun 1, 2024
72309c8
accept list of merchant ids as input to the certificate migration api
ShankarSinghC Jun 2, 2024
ca7936d
fix typos
ShankarSinghC Jun 2, 2024
32b7859
remove the unnecessary import
ShankarSinghC Jun 2, 2024
58e44a0
make fields ApplePayCertificatesMigrationResponse as sanke case
ShankarSinghC Jun 2, 2024
fd5aa68
fix clippy errors
ShankarSinghC Jun 2, 2024
93dc945
make connector_wallets_details field in ConnectorWalletDetailsUpdate …
ShankarSinghC Jun 3, 2024
daad5ba
address pr comments
ShankarSinghC Jun 3, 2024
3d27be8
Merge branch 'main' of https://github.com/juspay/hyperswitch into app…
ShankarSinghC Jun 3, 2024
15df915
chore: run formatter
hyperswitch-bot[bot] Jun 3, 2024
a3ca704
Replace AppState with SessionState
ShankarSinghC Jun 4, 2024
acd2eea
retrun the underlying error in the generics
ShankarSinghC Jun 5, 2024
8a58000
impl db transaction to update multiple merchant connector accounts
ShankarSinghC Jun 5, 2024
16c15d7
fix clippy errors
ShankarSinghC Jun 5, 2024
4aa32f6
address pr comments
ShankarSinghC Jun 5, 2024
4ab8a62
Update crates/router/src/core/apple_pay_certificates_migration.rs
ShankarSinghC Jun 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions crates/api_models/src/apple_pay_certificates_migration.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#[derive(Debug, Clone, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ApplePayCertificatesMigrationResponse {
pub status_message: String,
pub status_code: String,
}
1 change: 1 addition & 0 deletions crates/api_models/src/events.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod apple_pay_certificates_migration;
pub mod connector_onboarding;
pub mod customer;
pub mod dispute;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use common_utils::events::ApiEventMetric;

use crate::apple_pay_certificates_migration::ApplePayCertificatesMigrationResponse;

impl ApiEventMetric for ApplePayCertificatesMigrationResponse {
fn get_api_event_type(&self) -> Option<common_utils::events::ApiEventsType> {
Some(common_utils::events::ApiEventsType::ApplePayCertificatesMigration)
}
}
1 change: 1 addition & 0 deletions crates/api_models/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
pub mod admin;
pub mod analytics;
pub mod api_keys;
pub mod apple_pay_certificates_migration;
pub mod blocklist;
pub mod cards_info;
pub mod conditional_configs;
Expand Down
17 changes: 17 additions & 0 deletions crates/api_models/src/payments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4172,6 +4172,23 @@ pub struct SessionTokenInfo {
pub initiative_context: String,
#[schema(value_type = Option<CountryAlpha2>)]
pub merchant_business_country: Option<api_enums::CountryAlpha2>,
#[serde(flatten)]
pub payment_processing_details_at: Option<PaymentProcessingDetailsAt>,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
#[serde(tag = "payment_processing_details_at")]
pub enum PaymentProcessingDetailsAt {
Hyperswitch(PaymentProcessingDetails),
Connector,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq, ToSchema)]
pub struct PaymentProcessingDetails {
#[schema(value_type = String)]
pub payment_processing_certificate: Secret<String>,
#[schema(value_type = String)]
pub payment_processing_certificate_key: Secret<String>,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
Expand Down
5 changes: 0 additions & 5 deletions crates/common_enums/src/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2284,11 +2284,6 @@ pub enum ReconStatus {
Active,
Disabled,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ApplePayFlow {
Simplified,
Manual,
}

#[derive(
Clone,
Expand Down
1 change: 1 addition & 0 deletions crates/common_utils/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ pub enum ApiEventsType {
// TODO: This has to be removed once the corresponding apiEventTypes are created
Miscellaneous,
RustLocker,
ApplePayCertificatesMigration,
FraudCheck,
Recon,
Dispute {
Expand Down
2 changes: 1 addition & 1 deletion crates/connector_configs/src/connector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ pub enum ConnectorAuthType {
#[derive(Debug, Deserialize, serde::Serialize, Clone)]
#[serde(untagged)]
pub enum ApplePayTomlConfig {
Standard(payments::ApplePayMetadata),
Standard(Box<payments::ApplePayMetadata>),
Zen(ZenApplePay),
}

Expand Down
3 changes: 3 additions & 0 deletions crates/diesel_models/src/merchant_connector_account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ pub struct MerchantConnectorAccount {
pub applepay_verified_domains: Option<Vec<String>>,
pub pm_auth_config: Option<serde_json::Value>,
pub status: storage_enums::ConnectorStatus,
pub connector_wallets_details: Option<Encryption>,
}

#[derive(Clone, Debug, Insertable, router_derive::DebugAsDisplay)]
Expand Down Expand Up @@ -72,6 +73,7 @@ pub struct MerchantConnectorAccountNew {
pub applepay_verified_domains: Option<Vec<String>>,
pub pm_auth_config: Option<serde_json::Value>,
pub status: storage_enums::ConnectorStatus,
pub connector_wallets_details: Option<Encryption>,
}

#[derive(Clone, Debug, AsChangeset, router_derive::DebugAsDisplay)]
Expand All @@ -96,6 +98,7 @@ pub struct MerchantConnectorAccountUpdateInternal {
pub applepay_verified_domains: Option<Vec<String>>,
pub pm_auth_config: Option<serde_json::Value>,
pub status: Option<storage_enums::ConnectorStatus>,
pub connector_wallets_details: Option<Encryption>,
}

impl MerchantConnectorAccountUpdateInternal {
Expand Down
1 change: 1 addition & 0 deletions crates/diesel_models/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,7 @@ diesel::table! {
applepay_verified_domains -> Nullable<Array<Nullable<Text>>>,
pm_auth_config -> Nullable<Jsonb>,
status -> ConnectorStatus,
connector_wallets_details -> Nullable<Bytea>,
}
}

Expand Down
7 changes: 7 additions & 0 deletions crates/hyperswitch_domain_models/src/payment_method_data.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use api_models::payments;
use common_utils::pii::{self, Email};
use masking::Secret;
use serde::{Deserialize, Serialize};
Expand All @@ -22,6 +23,12 @@ pub enum PaymentMethodData {
CardToken(CardToken),
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ApplePayFlow {
Simplified(payments::PaymentProcessingDetails),
Manual,
}

impl PaymentMethodData {
pub fn get_payment_method(&self) -> Option<common_enums::PaymentMethod> {
match self {
Expand Down
5 changes: 3 additions & 2 deletions crates/hyperswitch_domain_models/src/router_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::{collections::HashMap, marker::PhantomData};

use masking::Secret;

use crate::payment_address::PaymentAddress;
use crate::{payment_address::PaymentAddress, payment_method_data};

#[derive(Debug, Clone)]
pub struct RouterData<Flow, Request, Response> {
Expand All @@ -21,6 +21,7 @@ pub struct RouterData<Flow, Request, Response> {
pub address: PaymentAddress,
pub auth_type: common_enums::enums::AuthenticationType,
pub connector_meta_data: Option<common_utils::pii::SecretSerdeValue>,
pub connector_wallets_details: Option<common_utils::pii::SecretSerdeValue>,
pub amount_captured: Option<i64>,
pub access_token: Option<AccessToken>,
pub session_token: Option<String>,
Expand Down Expand Up @@ -55,7 +56,7 @@ pub struct RouterData<Flow, Request, Response> {
pub connector_http_status_code: Option<u16>,
pub external_latency: Option<u128>,
/// Contains apple pay flow type simplified or manual
pub apple_pay_flow: Option<common_enums::enums::ApplePayFlow>,
pub apple_pay_flow: Option<payment_method_data::ApplePayFlow>,

pub frm_metadata: Option<common_utils::pii::SecretSerdeValue>,

Expand Down
2 changes: 2 additions & 0 deletions crates/openapi/src/openapi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,8 @@ Never share your secret api keys. Keep them guarded and secure.
api_models::payments::FeatureMetadata,
api_models::payments::ApplepayConnectorMetadataRequest,
api_models::payments::SessionTokenInfo,
api_models::payments::PaymentProcessingDetailsAt,
api_models::payments::PaymentProcessingDetails,
api_models::payments::SwishQrData,
api_models::payments::AirwallexData,
api_models::payments::NoonData,
Expand Down
1 change: 1 addition & 0 deletions crates/router/src/core.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
pub mod admin;
pub mod api_keys;
pub mod api_locking;
pub mod apple_pay_certificates_migration;
pub mod authentication;
pub mod blocklist;
pub mod cache;
Expand Down
53 changes: 52 additions & 1 deletion crates/router/src/core/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use crate::{
},
db::StorageInterface,
routes::{metrics, AppState},
services::{self, api as service_api},
services::{self, api as service_api, logger},
types::{
self, api,
domain::{
Expand Down Expand Up @@ -918,6 +918,24 @@ pub async fn create_payment_connector(
}
}

let apple_pay_metadata = helpers::get_applepay_metadata(req.metadata.clone())
.map_err(|error| {
logger::info!(
"Apple pay metadata parsing failed for while creating merchant connector account in create_payment_connector {:?}",
error
)
})
.ok();

let connector_apple_pay_details = apple_pay_metadata
.map(|metadata| {
serde_json::to_value(metadata)
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed to serialize apple pay metadata as JSON")
})
.transpose()?
.map(masking::Secret::new);

let merchant_connector_account = domain::MerchantConnectorAccount {
merchant_id: merchant_id.to_string(),
connector_type: req.connector_type,
Expand Down Expand Up @@ -961,6 +979,13 @@ pub async fn create_payment_connector(
applepay_verified_domains: None,
pm_auth_config: req.pm_auth_config.clone(),
status: connector_status,
connector_wallets_details: connector_apple_pay_details.async_map(|wallets_details| async { domain_types::encrypt(
wallets_details,
key_store.key.peek(),
)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Unable to encrypt connector wallets details")}).await.transpose()?
ShankarSinghC marked this conversation as resolved.
Show resolved Hide resolved
};

let transaction_type = match req.connector_type {
Expand Down Expand Up @@ -1200,6 +1225,25 @@ pub async fn update_payment_connector(
expected_format: "auth_type and api_key".to_string(),
})?;
let metadata = req.metadata.clone().or(mca.metadata.clone());

let apple_pay_metadata = helpers::get_applepay_metadata(metadata.clone())
.map_err(|error| {
logger::info!(
"Apple pay metadata parsing failed for while update merchant connector account in update_payment_connector {:?}",
error
)
})
.ok();

let connector_apple_pay_details = apple_pay_metadata
.map(|metadata| {
serde_json::to_value(metadata)
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed to serialize apple pay metadata as JSON")
})
.transpose()?
.map(masking::Secret::new);

let connector_name = mca.connector_name.as_ref();
let connector_enum = api_models::enums::Connector::from_str(connector_name)
.change_context(errors::ApiErrorResponse::InvalidDataValue {
Expand Down Expand Up @@ -1275,6 +1319,13 @@ pub async fn update_payment_connector(
applepay_verified_domains: None,
pm_auth_config: req.pm_auth_config,
status: Some(connector_status),
connector_wallets_details: connector_apple_pay_details
ShankarSinghC marked this conversation as resolved.
Show resolved Hide resolved
.async_lift(|wallets_details| {
domain_types::encrypt_optional(wallets_details, key_store.key.get_inner().peek())
})
.await
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed while encrypting connector wallets details")?,
};

// Profile id should always be present
Expand Down
108 changes: 108 additions & 0 deletions crates/router/src/core/apple_pay_certificates_migration.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
use api_models::apple_pay_certificates_migration::ApplePayCertificatesMigrationResponse;
use common_utils::errors::CustomResult;
use error_stack::ResultExt;
use masking::{PeekInterface, Secret};

use super::{
errors::{self, StorageErrorExt},
payments::helpers,
};
use crate::{
routes::AppState,
services::{self, logger},
types::{domain::types as domain_types, storage},
};

pub async fn apple_pay_certificates_migration(
state: AppState,
merchant_id: &str,
ShankarSinghC marked this conversation as resolved.
Show resolved Hide resolved
) -> CustomResult<
services::ApplicationResponse<ApplePayCertificatesMigrationResponse>,
errors::ApiErrorResponse,
> {
let db = state.store.as_ref();

let key_store = state
.store
.get_merchant_key_store_by_merchant_id(
merchant_id,
&state.store.get_master_key().to_vec().into(),
)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)?;

let merchant_connector_accounts = db
.find_merchant_connector_account_by_merchant_id_and_disabled_list(
merchant_id,
true,
&key_store,
)
.await
.to_not_found_response(errors::ApiErrorResponse::InternalServerError)?;

for connector_account in merchant_connector_accounts {
let connector_apple_pay_metadata =
helpers::get_applepay_metadata(connector_account.clone().metadata)
.map_err(|error| {
logger::info!(
"Apple pay metadata parsing failed for {:?} in certificates migrations api {:?}",
connector_account.clone().connector_name,
error
)
ShankarSinghC marked this conversation as resolved.
Show resolved Hide resolved
})
.ok();

if let Some(apple_pay_metadata) = connector_apple_pay_metadata {
let encrypted_apple_pay_metadata = domain_types::encrypt(
Secret::new(
serde_json::to_value(apple_pay_metadata)
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed to serialize apple pay metadata as JSON")?,
),
key_store.key.get_inner().peek(),
)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Unable to encrypt connector apple pay metadata")?;

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: None,
pm_auth_config: None,
connector_label: None,
status: None,
connector_wallets_details: Some(encrypted_apple_pay_metadata),
};
ShankarSinghC marked this conversation as resolved.
Show resolved Hide resolved
db.update_merchant_connector_account(
connector_account.clone(),
updated_mca.into(),
&key_store,
)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable_lazy(|| {
format!(
"Failed while updating MerchantConnectorAccount: id: {:?}",
connector_account.merchant_connector_id
)
})?;
}
}

Ok(services::api::ApplicationResponse::Json(
ApplePayCertificatesMigrationResponse {
status_code: "200".to_string(),
status_message: "Apple pay certificate migration completed".to_string(),
},
ShankarSinghC marked this conversation as resolved.
Show resolved Hide resolved
))
}
1 change: 1 addition & 0 deletions crates/router/src/core/authentication/transformers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ pub fn construct_router_data<F: Clone, Req, Res>(
address,
auth_type: common_enums::AuthenticationType::NoThreeDs,
connector_meta_data: merchant_connector_account.get_metadata(),
connector_wallets_details: merchant_connector_account.get_connector_wallets_details(),
amount_captured: None,
access_token: None,
session_token: None,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ impl ConstructFlowSpecificData<frm_api::Checkout, FraudCheckCheckoutData, FraudC
address: self.address.clone(),
auth_type: storage_enums::AuthenticationType::NoThreeDs,
connector_meta_data: None,
connector_wallets_details: None,
amount_captured: None,
request: FraudCheckCheckoutData {
amount: self.payment_attempt.amount.get_amount_as_i64(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ pub async fn construct_fulfillment_router_data<'a>(
address: PaymentAddress::default(),
auth_type: payment_attempt.authentication_type.unwrap_or_default(),
connector_meta_data: merchant_connector_account.get_metadata(),
connector_wallets_details: merchant_connector_account.get_connector_wallets_details(),
amount_captured: payment_intent
.amount_captured
.map(|amt| amt.get_amount_as_i64()),
Expand Down
Loading
Loading