mirror of
				https://github.com/juspay/hyperswitch.git
				synced 2025-10-31 01:57:45 +08:00 
			
		
		
		
	feat(router): add support for filtering PaymentMethodTypes at a session (#883)
Co-authored-by: Kashif <mohammed.kashif@juspay.in>
This commit is contained in:
		| @ -212,6 +212,10 @@ pub struct PaymentsRequest { | |||||||
|     /// Merchant connector details used to make payments. |     /// Merchant connector details used to make payments. | ||||||
|     pub merchant_connector_details: Option<admin::MerchantConnectorDetailsWrap>, |     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 |     /// Business sub label for the payment | ||||||
|     pub business_sub_label: Option<String>, |     pub business_sub_label: Option<String>, | ||||||
| } | } | ||||||
| @ -1058,6 +1062,10 @@ pub struct PaymentsResponse { | |||||||
|  |  | ||||||
|     /// The business_sub_label for this payment |     /// The business_sub_label for this payment | ||||||
|     pub business_sub_label: Option<String>, |     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)] | #[derive(Clone, Debug, serde::Deserialize, ToSchema)] | ||||||
| @ -1318,6 +1326,10 @@ pub struct Metadata { | |||||||
|     pub data: pii::SecretSerdeValue, |     pub data: pii::SecretSerdeValue, | ||||||
|     /// Payload coming in request as a metadata field |     /// Payload coming in request as a metadata field | ||||||
|     pub payload: Option<pii::SecretSerdeValue>, |     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)] | #[derive(Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)] | ||||||
|  | |||||||
| @ -1056,6 +1056,26 @@ async fn filter_payment_methods( | |||||||
|         let parse_result = serde_json::from_value::<PaymentMethodsEnabled>(payment_method); |         let parse_result = serde_json::from_value::<PaymentMethodsEnabled>(payment_method); | ||||||
|         if let Ok(payment_methods_enabled) = parse_result { |         if let Ok(payment_methods_enabled) = parse_result { | ||||||
|             let payment_method = payment_methods_enabled.payment_method; |             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 |             for payment_method_type_info in payment_methods_enabled | ||||||
|                 .payment_method_types |                 .payment_method_types | ||||||
|                 .unwrap_or_default() |                 .unwrap_or_default() | ||||||
| @ -1115,6 +1135,11 @@ async fn filter_payment_methods( | |||||||
|                             .map(|value| value.foreign_into()), |                             .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 connector = connector.clone(); | ||||||
|  |  | ||||||
|                     let response_pm_type = ResponsePaymentMethodIntermediate::new( |                     let response_pm_type = ResponsePaymentMethodIntermediate::new( | ||||||
| @ -1123,7 +1148,7 @@ async fn filter_payment_methods( | |||||||
|                         payment_method, |                         payment_method, | ||||||
|                     ); |                     ); | ||||||
|  |  | ||||||
|                     if filter && filter2 && filter3 && filter4 && filter5 { |                     if filter && filter2 && filter3 && filter4 && filter5 && filter6 { | ||||||
|                         resp.push(response_pm_type); |                         resp.push(response_pm_type); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
| @ -1358,6 +1383,13 @@ fn filter_amount_based(payment_method: &RequestPaymentMethodTypes, amount: Optio | |||||||
|     min_check && max_check |     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( | fn filter_recurring_based( | ||||||
|     payment_method: &RequestPaymentMethodTypes, |     payment_method: &RequestPaymentMethodTypes, | ||||||
|     recurring_enabled: Option<bool>, |     recurring_enabled: Option<bool>, | ||||||
|  | |||||||
| @ -323,6 +323,7 @@ impl PaymentRedirectFlow for PaymentRedirectCompleteAuthorize { | |||||||
|                 order_details: None, |                 order_details: None, | ||||||
|                 data: masking::Secret::new("{}".into()), |                 data: masking::Secret::new("{}".into()), | ||||||
|                 payload: Some(req.json_payload.unwrap_or(serde_json::json!({})).into()), |                 payload: Some(req.json_payload.unwrap_or(serde_json::json!({})).into()), | ||||||
|  |                 allowed_payment_method_types: None, | ||||||
|             }), |             }), | ||||||
|             ..Default::default() |             ..Default::default() | ||||||
|         }; |         }; | ||||||
|  | |||||||
| @ -485,7 +485,13 @@ impl PaymentCreate { | |||||||
|         let metadata = request |         let metadata = request | ||||||
|             .metadata |             .metadata | ||||||
|             .as_ref() |             .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() |             .transpose() | ||||||
|             .change_context(errors::ApiErrorResponse::InternalServerError) |             .change_context(errors::ApiErrorResponse::InternalServerError) | ||||||
|             .attach_printable("Encoding Metadata to value failed")?; |             .attach_printable("Encoding Metadata to value failed")?; | ||||||
|  | |||||||
| @ -288,6 +288,19 @@ where | |||||||
|                         connector_name, |                         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( |                 services::ApplicationResponse::Json( | ||||||
|                     response |                     response | ||||||
|                         .set_payment_id(Some(payment_attempt.payment_id)) |                         .set_payment_id(Some(payment_attempt.payment_id)) | ||||||
| @ -369,6 +382,10 @@ where | |||||||
|                         .set_business_country(payment_intent.business_country) |                         .set_business_country(payment_intent.business_country) | ||||||
|                         .set_business_label(payment_intent.business_label) |                         .set_business_label(payment_intent.business_label) | ||||||
|                         .set_business_sub_label(payment_attempt.business_sub_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(), |                         .to_owned(), | ||||||
|                 ) |                 ) | ||||||
|             } |             } | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 Kashif
					Kashif