-
Notifications
You must be signed in to change notification settings - Fork 3.9k
feat(payment-methods): add filtering logic for payment method list v2 #8606
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
Conversation
Changed Files
|
… payment_method list (#8317) Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems fine, should be throughly tested before further deployments in different environments.
crates/api_models/src/payments.rs
Outdated
@@ -7701,7 +7703,38 @@ pub enum SdkType { | |||
|
|||
#[cfg(feature = "v2")] | |||
#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, ToSchema)] | |||
pub struct PaymentMethodsListRequest {} | |||
pub struct PaymentMethodsListRequest { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already have a PaymentMethodListRequest
struct in api_models/src/payment_methods.rs
. Please consider using that. We can also remove the extra deserializer crate dependency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This struct was introduced by @Narayanbhat166 for v2, while the struct in api_models/src/payment_methods.rs
is for v1. Are we sure about merging them given if we try to differentiate v1 and v2 parameters?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
deserialize_form_style_query_parameter
crate is import for v2 specifically to take vector as a input in query params. for example {{baseUrl}}/v2/payments/:id/payment-methods?accepted_countries=US,UK,NZ
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have 2 versions of PaymentMethodListRequest
in payment_methods.rs
, one for v1 and another for v2.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are two separate structure present to differentiate payment's and payment method's PML. In case of future deviation in implementation, this will be useful. Currently updating the name of both as per suggestion
|
||
/// Indicates whether the payment method is eligible for card networks | ||
#[serde(deserialize_with = "option_form_vec_deserialize", default)] | ||
#[schema(value_type = Option<Vec<CardNetwork>>, example = json!(["visa", "mastercard"]))] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we please have a test case added for the deserializer which is added
payment_method_type, | ||
)) | ||
.map(|value| filter_config_country_currency_based(value, country, currency)) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we really need this match case? we are calling the same fn in both the cases.
…ordea-sepa * 'main' of github.com:juspay/hyperswitch: (89 commits) feat(router): [worldpayvantiv] add dispute list sync and implement dispute (#8830) feat(core): Add support for Void after Capture (#8839) fix(wasm): [FISERV] Added GooglePay Payment Method Type (#8832) feat(connector): [Barclaycard] Add Google Pay Payment Method (#8786) chore(version): 2025.08.06.0 feat(core): Added additional authentication fields for 3ds external authentication (#8758) refactor(core): propagate network_transaction_id in response of payment (#8829) fix(core): add fix for stopping multiple event locking idempotent logs (#8034) feat(connector): [AUTHORIZEDOTNET] create connector customer flow added (#8774) feat(core): Add L2_L3 Data Support (#8828) feat(connector): [NMI] Add mandates flow (#8652) fix(connector): [Wise] send uuid as connector_transaction_id (#8836) feat(core): populate UCS status_code in response headers (#8788) feat(external_services): Fixed Url for Unified Connector Service gRPC Client (#8587) chore: reorder v2 migrations folders (#8671) fix(router): Take merchant ID from headers in API Key - Revoke (v2) (#8808) fix(connector): (payload) currency auth key wasm changes (#8825) feat(payment-methods): add filtering logic for payment method list v2 (#8606) feat(router): add support for apple pay pre-decrypted token in the payments confirm call (#8815) chore(version): 2025.08.05.0 ...
Type of Change
Description
Implementation Details
The core of this change is the
filter_payment_methods
function, which is designed to be called iteratively for eachPaymentMethodsEnabledForConnector
object. The function's primary responsibility is to decide whether a given payment method should be included in the list of available options presented to the user.It achieves this by executing three sequential sets of logical checks, represented by boolean flags:
request_based_filter
intent_based_filter
config_based_filter
A payment method is only added to the final response vector (
resp
) if it successfully passes all three of these filtering stages.Filtering Logic Breakdown
The filtering logic is composed of several helper functions, each responsible for a specific check:
1. Request-Based Filtering:
These filters operate on parameters directly from the
PaymentMethodsListRequest
.filter_recurring_based
: A straightforward check that compares therecurring_enabled
boolean in the request with the payment method's configuration.filter_amount_based
: Validates if the transactionamount
falls within theminimum_amount
andmaximum_amount
supported by the payment method. It correctly handlesNone
amounts and allows zero-amount transactions to pass.filter_card_network_based
: ForCredit
andDebit
payment methods, this ensures that the card networks specified in the request are a subset of the networks configured for the payment method.2. Payment Intent-Based Filtering:
These checks are performed only if a
PaymentIntent
object is available for the transaction.filter_country_based
&filter_currency_based
: These functions validate the transaction's country (frombilling_address
) and currency against the payment method'saccepted_countries
andaccepted_currencies
configurations. These configurations support both allow-lists (EnableOnly
) and deny-lists (DisableOnly
).filter_zero_mandate_based
: This implements specialized logic for zero-amount transactions intended for future use (setup_future_usage: OffSession
). It consults thesettings.zero_mandates.supported_payment_methods
configuration to verify if the specific payment method type, subtype, and connector are explicitly enabled for zero-value mandates.filter_allowed_payment_method_types_based
: Checks if the current payment method's type is included in theallowed_payment_method_types
list within thePaymentIntent
.3. Configuration-Based Filtering:
This stage applies system-wide rules defined in the application settings.
filter_config_based
: This function retrieves filtering rules fromsettings.pm_filters
. It first looks for a configuration block matching the connector name (e.g.,"stripe"
) and falls back to a"default"
configuration if a connector-specific one is not found. The lookup within this configuration is performed using thePaymentMethodType
.filter_config_country_currency_based
: Once a configuration is found, this helper applies the country and currency rules defined in the correspondingCurrencyCountryFlowFilter
, ensuring the transaction's context matches the defined constraints.Additional Changes
Motivation and Context
How did you test it?
Tested through Postman:
Create an MCA (Adyen) with below body:
Scenarios:
Case 1: Filter based on country currency:
Create a payment intent with country as DE and currency as EUR
Do a payment method list call, following should be the response
Case 2: Filter based on card_network:
Create the following intent
Create a PML request with the following request parameters (card_networks=Visa,AmericanExpress):
Following should be the response
Case 3: Filter based on amount:
Create a payment intent with amount=30 and country as NL and currency as EUR
Do a payment method list call, following should be the response
Cretae a payment intent with amount=80 and country as NL and currency as EUR
Do a payment method list call, following should be the response
Case 4: Filter based on zero mandates:
Create a payment intent with amount=0 and setup_future_usage=off_session
Do a payment method list call, following should be the response
Checklist
cargo +nightly fmt --all
cargo clippy