mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-11-01 19:42:27 +08:00
feat(router): add mertics to apple pay flow (#2235)
Co-authored-by: ItsMeShashank <shashank.attarde@juspay.in>
This commit is contained in:
@ -1796,3 +1796,8 @@ pub enum ReconStatus {
|
||||
Active,
|
||||
Disabled,
|
||||
}
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum ApplePayFlow {
|
||||
Simplified,
|
||||
Manual,
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@ pub mod types;
|
||||
|
||||
use std::{fmt::Debug, marker::PhantomData, ops::Deref, time::Instant};
|
||||
|
||||
use api_models::payments::HeaderPayload;
|
||||
use api_models::{enums, payments::HeaderPayload};
|
||||
use common_utils::{ext_traits::AsyncExt, pii};
|
||||
use data_models::mandates::MandateData;
|
||||
use diesel_models::{ephemeral_key, fraud_check::FraudCheck};
|
||||
@ -48,7 +48,10 @@ use crate::{
|
||||
self as router_types, api, domain,
|
||||
storage::{self, enums as storage_enums},
|
||||
},
|
||||
utils::{add_connector_http_status_code_metrics, Encode, OptionExt, ValueExt},
|
||||
utils::{
|
||||
add_apple_pay_flow_metrics, add_connector_http_status_code_metrics, Encode, OptionExt,
|
||||
ValueExt,
|
||||
},
|
||||
workflows::payment_sync,
|
||||
};
|
||||
|
||||
@ -1105,45 +1108,44 @@ fn is_payment_method_tokenization_enabled_for_connector(
|
||||
.unwrap_or(false))
|
||||
}
|
||||
|
||||
fn is_apple_pay_predecrypt(
|
||||
fn decide_apple_pay_flow(
|
||||
payment_method_type: &Option<api_models::enums::PaymentMethodType>,
|
||||
merchant_connector_account: &Option<helpers::MerchantConnectorAccountType>,
|
||||
) -> RouterResult<bool> {
|
||||
Ok(payment_method_type
|
||||
.map(|pmt| match pmt {
|
||||
) -> Option<enums::ApplePayFlow> {
|
||||
payment_method_type.and_then(|pmt| match pmt {
|
||||
api_models::enums::PaymentMethodType::ApplePay => {
|
||||
check_apple_pay_metadata(merchant_connector_account)
|
||||
}
|
||||
_ => Ok(false),
|
||||
_ => None,
|
||||
})
|
||||
.transpose()?
|
||||
.unwrap_or(false))
|
||||
}
|
||||
|
||||
fn check_apple_pay_metadata(
|
||||
merchant_connector_account: &Option<helpers::MerchantConnectorAccountType>,
|
||||
) -> RouterResult<bool> {
|
||||
let apple_pay_predecrypt = merchant_connector_account
|
||||
.clone()
|
||||
.and_then(|mca| {
|
||||
) -> Option<enums::ApplePayFlow> {
|
||||
merchant_connector_account.clone().and_then(|mca| {
|
||||
let metadata = mca.get_metadata();
|
||||
metadata.and_then(|apple_pay_metadata| {
|
||||
let parsed_metadata: Result<api_models::payments::ApplepaySessionTokenData, _> =
|
||||
apple_pay_metadata.parse_value("ApplepaySessionTokenData");
|
||||
apple_pay_metadata.parse_value("ApplepaySessionTokenData").map_err(|error| logger::error!(%error, "Failed to Parse Value to ApplepaySessionTokenData"));
|
||||
|
||||
parsed_metadata.ok().map(|metadata| match metadata.data {
|
||||
api_models::payments::ApplepaySessionTokenMetadata::ApplePayCombined(
|
||||
apple_pay_combined,
|
||||
) => match apple_pay_combined {
|
||||
api_models::payments::ApplePayCombinedMetadata::Simplified { .. } => true,
|
||||
api_models::payments::ApplePayCombinedMetadata::Manual { .. } => false,
|
||||
api_models::payments::ApplePayCombinedMetadata::Simplified { .. } => {
|
||||
enums::ApplePayFlow::Simplified
|
||||
}
|
||||
api_models::payments::ApplePayCombinedMetadata::Manual { .. } => {
|
||||
enums::ApplePayFlow::Manual
|
||||
}
|
||||
},
|
||||
api_models::payments::ApplepaySessionTokenMetadata::ApplePay(_) => false,
|
||||
api_models::payments::ApplepaySessionTokenMetadata::ApplePay(_) => {
|
||||
enums::ApplePayFlow::Manual
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
.unwrap_or(false);
|
||||
Ok(apple_pay_predecrypt)
|
||||
}
|
||||
|
||||
fn is_payment_method_type_allowed_for_connector(
|
||||
@ -1166,8 +1168,11 @@ async fn decide_payment_method_tokenize_action(
|
||||
payment_method: &storage::enums::PaymentMethod,
|
||||
pm_parent_token: Option<&String>,
|
||||
is_connector_tokenization_enabled: bool,
|
||||
is_apple_pay_predecrypt_supported: bool,
|
||||
apple_pay_flow: Option<enums::ApplePayFlow>,
|
||||
) -> RouterResult<TokenizationAction> {
|
||||
let is_apple_pay_predecrypt_supported =
|
||||
matches!(apple_pay_flow, Some(enums::ApplePayFlow::Simplified));
|
||||
|
||||
match pm_parent_token {
|
||||
None => {
|
||||
if is_connector_tokenization_enabled && is_apple_pay_predecrypt_supported {
|
||||
@ -1272,10 +1277,16 @@ where
|
||||
payment_method_type,
|
||||
)?;
|
||||
|
||||
let is_apple_pay_predecrypt = is_apple_pay_predecrypt(
|
||||
let apple_pay_flow = decide_apple_pay_flow(
|
||||
payment_method_type,
|
||||
&Some(merchant_connector_account.clone()),
|
||||
)?;
|
||||
);
|
||||
|
||||
add_apple_pay_flow_metrics(
|
||||
&apple_pay_flow,
|
||||
payment_data.payment_attempt.connector.clone(),
|
||||
payment_data.payment_attempt.merchant_id.clone(),
|
||||
);
|
||||
|
||||
let payment_method_action = decide_payment_method_tokenize_action(
|
||||
state,
|
||||
@ -1283,7 +1294,7 @@ where
|
||||
payment_method,
|
||||
payment_data.token.as_ref(),
|
||||
is_connector_tokenization_enabled,
|
||||
is_apple_pay_predecrypt,
|
||||
apple_pay_flow,
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
||||
@ -2540,6 +2540,7 @@ pub fn router_data_type_conversion<F1, F2, Req1, Req2, Res1, Res2>(
|
||||
test_mode: router_data.test_mode,
|
||||
connector_api_version: router_data.connector_api_version,
|
||||
connector_http_status_code: router_data.connector_http_status_code,
|
||||
apple_pay_flow: router_data.apple_pay_flow,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -419,6 +419,13 @@ async fn payment_response_update_tracker<F: Clone, T: types::Capturable>(
|
||||
metrics::SUCCESSFUL_PAYMENT.add(&metrics::CONTEXT, 1, &[]);
|
||||
}
|
||||
|
||||
utils::add_apple_pay_payment_status_metrics(
|
||||
router_data.status,
|
||||
router_data.apple_pay_flow,
|
||||
payment_data.payment_attempt.connector.clone(),
|
||||
payment_data.payment_attempt.merchant_id.clone(),
|
||||
);
|
||||
|
||||
let (capture_updates, payment_attempt_update) =
|
||||
match payment_data.multiple_capture_data {
|
||||
Some(multiple_capture_data) => {
|
||||
|
||||
@ -115,6 +115,11 @@ where
|
||||
None
|
||||
};
|
||||
|
||||
let apple_pay_flow = payments::decide_apple_pay_flow(
|
||||
&payment_data.payment_attempt.payment_method_type,
|
||||
&Some(merchant_connector_account.clone()),
|
||||
);
|
||||
|
||||
router_data = types::RouterData {
|
||||
flow: PhantomData,
|
||||
merchant_id: merchant_account.merchant_id.clone(),
|
||||
@ -157,6 +162,7 @@ where
|
||||
payment_method_balance: None,
|
||||
connector_api_version,
|
||||
connector_http_status_code: None,
|
||||
apple_pay_flow,
|
||||
};
|
||||
|
||||
Ok(router_data)
|
||||
|
||||
@ -187,6 +187,7 @@ pub async fn construct_payout_router_data<'a, F>(
|
||||
payment_method_balance: None,
|
||||
connector_api_version: None,
|
||||
connector_http_status_code: None,
|
||||
apple_pay_flow: None,
|
||||
};
|
||||
|
||||
Ok(router_data)
|
||||
@ -325,6 +326,7 @@ pub async fn construct_refund_router_data<'a, F>(
|
||||
payment_method_balance: None,
|
||||
connector_api_version,
|
||||
connector_http_status_code: None,
|
||||
apple_pay_flow: None,
|
||||
};
|
||||
|
||||
Ok(router_data)
|
||||
@ -551,6 +553,7 @@ pub async fn construct_accept_dispute_router_data<'a>(
|
||||
payment_method_balance: None,
|
||||
connector_api_version: None,
|
||||
connector_http_status_code: None,
|
||||
apple_pay_flow: None,
|
||||
};
|
||||
Ok(router_data)
|
||||
}
|
||||
@ -635,6 +638,7 @@ pub async fn construct_submit_evidence_router_data<'a>(
|
||||
test_mode,
|
||||
connector_api_version: None,
|
||||
connector_http_status_code: None,
|
||||
apple_pay_flow: None,
|
||||
};
|
||||
Ok(router_data)
|
||||
}
|
||||
@ -724,6 +728,7 @@ pub async fn construct_upload_file_router_data<'a>(
|
||||
test_mode,
|
||||
connector_api_version: None,
|
||||
connector_http_status_code: None,
|
||||
apple_pay_flow: None,
|
||||
};
|
||||
Ok(router_data)
|
||||
}
|
||||
@ -811,6 +816,7 @@ pub async fn construct_defend_dispute_router_data<'a>(
|
||||
test_mode,
|
||||
connector_api_version: None,
|
||||
connector_http_status_code: None,
|
||||
apple_pay_flow: None,
|
||||
};
|
||||
Ok(router_data)
|
||||
}
|
||||
@ -891,6 +897,7 @@ pub async fn construct_retrieve_file_router_data<'a>(
|
||||
test_mode,
|
||||
connector_api_version: None,
|
||||
connector_http_status_code: None,
|
||||
apple_pay_flow: None,
|
||||
};
|
||||
Ok(router_data)
|
||||
}
|
||||
|
||||
@ -115,6 +115,7 @@ pub async fn construct_webhook_router_data<'a>(
|
||||
payment_method_balance: None,
|
||||
connector_api_version: None,
|
||||
connector_http_status_code: None,
|
||||
apple_pay_flow: None,
|
||||
};
|
||||
Ok(router_data)
|
||||
}
|
||||
|
||||
@ -94,5 +94,13 @@ histogram_metric!(CARD_DELETE_TIME, GLOBAL_METER);
|
||||
histogram_metric!(ENCRYPTION_TIME, GLOBAL_METER);
|
||||
histogram_metric!(DECRYPTION_TIME, GLOBAL_METER);
|
||||
|
||||
// Apple Pay Flow Metrics
|
||||
counter_metric!(APPLE_PAY_MANUAL_FLOW, GLOBAL_METER);
|
||||
counter_metric!(APPLE_PAY_SIMPLIFIED_FLOW, GLOBAL_METER);
|
||||
counter_metric!(APPLE_PAY_MANUAL_FLOW_SUCCESSFUL_PAYMENT, GLOBAL_METER);
|
||||
counter_metric!(APPLE_PAY_SIMPLIFIED_FLOW_SUCCESSFUL_PAYMENT, GLOBAL_METER);
|
||||
counter_metric!(APPLE_PAY_MANUAL_FLOW_FAILED_PAYMENT, GLOBAL_METER);
|
||||
counter_metric!(APPLE_PAY_SIMPLIFIED_FLOW_FAILED_PAYMENT, GLOBAL_METER);
|
||||
|
||||
pub mod request;
|
||||
pub mod utils;
|
||||
|
||||
@ -285,6 +285,9 @@ pub struct RouterData<Flow, Request, Response> {
|
||||
|
||||
pub test_mode: Option<bool>,
|
||||
pub connector_http_status_code: Option<u16>,
|
||||
|
||||
/// Contains apple pay flow type simplified or manual
|
||||
pub apple_pay_flow: Option<storage_enums::ApplePayFlow>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, serde::Deserialize)]
|
||||
@ -1108,6 +1111,7 @@ impl<F1, F2, T1, T2> From<(&RouterData<F1, T1, PaymentsResponseData>, T2)>
|
||||
payment_method_balance: data.payment_method_balance.clone(),
|
||||
connector_api_version: data.connector_api_version.clone(),
|
||||
connector_http_status_code: data.connector_http_status_code,
|
||||
apple_pay_flow: data.apple_pay_flow.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1161,6 +1165,7 @@ impl<F1, F2>
|
||||
payment_method_balance: None,
|
||||
connector_api_version: None,
|
||||
connector_http_status_code: data.connector_http_status_code,
|
||||
apple_pay_flow: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ pub mod ext_traits;
|
||||
#[cfg(feature = "kv_store")]
|
||||
pub mod storage_partitioning;
|
||||
|
||||
use api_models::{payments, webhooks};
|
||||
use api_models::{enums, payments, webhooks};
|
||||
use base64::Engine;
|
||||
pub use common_utils::{
|
||||
crypto,
|
||||
@ -530,3 +530,104 @@ impl CustomerAddress for api_models::customers::CustomerRequest {
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_apple_pay_flow_metrics(
|
||||
apple_pay_flow: &Option<enums::ApplePayFlow>,
|
||||
connector: Option<String>,
|
||||
merchant_id: String,
|
||||
) {
|
||||
if let Some(flow) = apple_pay_flow {
|
||||
match flow {
|
||||
enums::ApplePayFlow::Simplified => metrics::APPLE_PAY_SIMPLIFIED_FLOW.add(
|
||||
&metrics::CONTEXT,
|
||||
1,
|
||||
&[
|
||||
metrics::request::add_attributes(
|
||||
"connector",
|
||||
connector.to_owned().unwrap_or("null".to_string()),
|
||||
),
|
||||
metrics::request::add_attributes("merchant_id", merchant_id.to_owned()),
|
||||
],
|
||||
),
|
||||
enums::ApplePayFlow::Manual => metrics::APPLE_PAY_MANUAL_FLOW.add(
|
||||
&metrics::CONTEXT,
|
||||
1,
|
||||
&[
|
||||
metrics::request::add_attributes(
|
||||
"connector",
|
||||
connector.to_owned().unwrap_or("null".to_string()),
|
||||
),
|
||||
metrics::request::add_attributes("merchant_id", merchant_id.to_owned()),
|
||||
],
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_apple_pay_payment_status_metrics(
|
||||
payment_attempt_status: enums::AttemptStatus,
|
||||
apple_pay_flow: Option<enums::ApplePayFlow>,
|
||||
connector: Option<String>,
|
||||
merchant_id: String,
|
||||
) {
|
||||
if payment_attempt_status == enums::AttemptStatus::Charged {
|
||||
if let Some(flow) = apple_pay_flow {
|
||||
match flow {
|
||||
enums::ApplePayFlow::Simplified => {
|
||||
metrics::APPLE_PAY_SIMPLIFIED_FLOW_SUCCESSFUL_PAYMENT.add(
|
||||
&metrics::CONTEXT,
|
||||
1,
|
||||
&[
|
||||
metrics::request::add_attributes(
|
||||
"connector",
|
||||
connector.to_owned().unwrap_or("null".to_string()),
|
||||
),
|
||||
metrics::request::add_attributes("merchant_id", merchant_id.to_owned()),
|
||||
],
|
||||
)
|
||||
}
|
||||
enums::ApplePayFlow::Manual => metrics::APPLE_PAY_MANUAL_FLOW_SUCCESSFUL_PAYMENT
|
||||
.add(
|
||||
&metrics::CONTEXT,
|
||||
1,
|
||||
&[
|
||||
metrics::request::add_attributes(
|
||||
"connector",
|
||||
connector.to_owned().unwrap_or("null".to_string()),
|
||||
),
|
||||
metrics::request::add_attributes("merchant_id", merchant_id.to_owned()),
|
||||
],
|
||||
),
|
||||
}
|
||||
}
|
||||
} else if payment_attempt_status == enums::AttemptStatus::Failure {
|
||||
if let Some(flow) = apple_pay_flow {
|
||||
match flow {
|
||||
enums::ApplePayFlow::Simplified => {
|
||||
metrics::APPLE_PAY_SIMPLIFIED_FLOW_FAILED_PAYMENT.add(
|
||||
&metrics::CONTEXT,
|
||||
1,
|
||||
&[
|
||||
metrics::request::add_attributes(
|
||||
"connector",
|
||||
connector.to_owned().unwrap_or("null".to_string()),
|
||||
),
|
||||
metrics::request::add_attributes("merchant_id", merchant_id.to_owned()),
|
||||
],
|
||||
)
|
||||
}
|
||||
enums::ApplePayFlow::Manual => metrics::APPLE_PAY_MANUAL_FLOW_FAILED_PAYMENT.add(
|
||||
&metrics::CONTEXT,
|
||||
1,
|
||||
&[
|
||||
metrics::request::add_attributes(
|
||||
"connector",
|
||||
connector.to_owned().unwrap_or("null".to_string()),
|
||||
),
|
||||
metrics::request::add_attributes("merchant_id", merchant_id.to_owned()),
|
||||
],
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -91,6 +91,7 @@ fn construct_payment_router_data() -> types::PaymentsAuthorizeRouterData {
|
||||
payment_method_balance: None,
|
||||
connector_api_version: None,
|
||||
connector_http_status_code: None,
|
||||
apple_pay_flow: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -146,6 +147,7 @@ fn construct_refund_router_data<F>() -> types::RefundsRouterData<F> {
|
||||
payment_method_balance: None,
|
||||
connector_api_version: None,
|
||||
connector_http_status_code: None,
|
||||
apple_pay_flow: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -513,6 +513,7 @@ pub trait ConnectorActions: Connector {
|
||||
payment_method_balance: None,
|
||||
connector_api_version: None,
|
||||
connector_http_status_code: None,
|
||||
apple_pay_flow: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user