feat(router): add support for filtering PaymentMethodTypes at a session (#883)

Co-authored-by: Kashif <mohammed.kashif@juspay.in>
This commit is contained in:
Kashif
2023-04-21 02:52:04 +05:30
committed by GitHub
parent 93b69e74b4
commit 465933ba72
5 changed files with 70 additions and 2 deletions

View File

@ -212,6 +212,10 @@ pub struct PaymentsRequest {
/// Merchant connector details used to make payments.
pub merchant_connector_details: Option<admin::MerchantConnectorDetailsWrap>,
/// Allowed Payment Method Types for a given PaymentIntent
#[schema(value_type = Option<Vec<PaymentMethodType>>)]
pub allowed_payment_method_types: Option<Vec<api_enums::PaymentMethodType>>,
/// Business sub label for the payment
pub business_sub_label: Option<String>,
}
@ -1058,6 +1062,10 @@ pub struct PaymentsResponse {
/// The business_sub_label for this payment
pub business_sub_label: Option<String>,
/// Allowed Payment Method Types for a given PaymentIntent
#[schema(value_type = Option<Vec<PaymentMethodType>>)]
pub allowed_payment_method_types: Option<Vec<api_enums::PaymentMethodType>>,
}
#[derive(Clone, Debug, serde::Deserialize, ToSchema)]
@ -1318,6 +1326,10 @@ pub struct Metadata {
pub data: pii::SecretSerdeValue,
/// Payload coming in request as a metadata field
pub payload: Option<pii::SecretSerdeValue>,
/// Allowed payment method types for a payment intent
#[schema(value_type = Option<Vec<PaymentMethodType>>)]
pub allowed_payment_method_types: Option<Vec<api_enums::PaymentMethodType>>,
}
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)]

View File

@ -1056,6 +1056,26 @@ async fn filter_payment_methods(
let parse_result = serde_json::from_value::<PaymentMethodsEnabled>(payment_method);
if let Ok(payment_methods_enabled) = parse_result {
let payment_method = payment_methods_enabled.payment_method;
let allowed_payment_method_types = payment_intent
.map(|payment_intent|
payment_intent
.metadata
.as_ref()
.and_then(|masked_metadata| {
let metadata = masked_metadata.peek().clone();
let parsed_metadata: Option<api_models::payments::Metadata> =
serde_json::from_value(metadata)
.map_err(|error| logger::error!(%error, "Failed to deserialize PaymentIntent metadata"))
.ok();
parsed_metadata.and_then(|pm| {
logger::info!(
"Only given PaymentMethodTypes will be allowed {:?}",
pm.allowed_payment_method_types
);
pm.allowed_payment_method_types
})
}))
.and_then(|a| a);
for payment_method_type_info in payment_methods_enabled
.payment_method_types
.unwrap_or_default()
@ -1115,6 +1135,11 @@ async fn filter_payment_methods(
.map(|value| value.foreign_into()),
);
let filter6 = filter_pm_based_on_allowed_types(
allowed_payment_method_types.as_ref(),
&payment_method_object.payment_method_type,
);
let connector = connector.clone();
let response_pm_type = ResponsePaymentMethodIntermediate::new(
@ -1123,7 +1148,7 @@ async fn filter_payment_methods(
payment_method,
);
if filter && filter2 && filter3 && filter4 && filter5 {
if filter && filter2 && filter3 && filter4 && filter5 && filter6 {
resp.push(response_pm_type);
}
}
@ -1358,6 +1383,13 @@ fn filter_amount_based(payment_method: &RequestPaymentMethodTypes, amount: Optio
min_check && max_check
}
fn filter_pm_based_on_allowed_types(
allowed_types: Option<&Vec<api_enums::PaymentMethodType>>,
payment_method_type: &api_enums::PaymentMethodType,
) -> bool {
allowed_types.map_or(true, |pm| pm.contains(payment_method_type))
}
fn filter_recurring_based(
payment_method: &RequestPaymentMethodTypes,
recurring_enabled: Option<bool>,

View File

@ -323,6 +323,7 @@ impl PaymentRedirectFlow for PaymentRedirectCompleteAuthorize {
order_details: None,
data: masking::Secret::new("{}".into()),
payload: Some(req.json_payload.unwrap_or(serde_json::json!({})).into()),
allowed_payment_method_types: None,
}),
..Default::default()
};

View File

@ -485,7 +485,13 @@ impl PaymentCreate {
let metadata = request
.metadata
.as_ref()
.map(Encode::<api_models::payments::Metadata>::encode_to_value)
.map(|metadata| {
let transformed_metadata = api_models::payments::Metadata {
allowed_payment_method_types: request.allowed_payment_method_types.clone(),
..metadata.clone()
};
Encode::<api_models::payments::Metadata>::encode_to_value(&transformed_metadata)
})
.transpose()
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Encoding Metadata to value failed")?;

View File

@ -288,6 +288,19 @@ where
connector_name,
)
});
let parsed_metadata: Option<api_models::payments::Metadata> = payment_intent
.metadata
.clone()
.map(|metadata_value| {
metadata_value
.parse_value("metadata")
.change_context(errors::ApiErrorResponse::InvalidDataValue {
field_name: "metadata",
})
.attach_printable("unable to parse metadata")
})
.transpose()
.unwrap_or_default();
services::ApplicationResponse::Json(
response
.set_payment_id(Some(payment_attempt.payment_id))
@ -369,6 +382,10 @@ where
.set_business_country(payment_intent.business_country)
.set_business_label(payment_intent.business_label)
.set_business_sub_label(payment_attempt.business_sub_label)
.set_allowed_payment_method_types(
parsed_metadata
.and_then(|metadata| metadata.allowed_payment_method_types),
)
.to_owned(),
)
}