feat(router): Return psp_tokenization_enabled in Customer PML (#7519)

This commit is contained in:
Anurag Thakur
2025-03-20 15:02:07 +05:30
committed by GitHub
parent a5be11498f
commit a341e82d4a
8 changed files with 130 additions and 12 deletions

View File

@ -2834,7 +2834,7 @@
}
},
"/v2/customers/{id}/saved-payment-methods": {
"delete": {
"get": {
"tags": [
"Payment Methods"
],
@ -7666,6 +7666,7 @@
"prophetpay",
"rapyd",
"razorpay",
"recurly",
"shift4",
"square",
"stax",
@ -8651,7 +8652,8 @@
"recurring_enabled",
"created",
"requires_cvv",
"is_default"
"is_default",
"psp_tokenization_enabled"
],
"properties": {
"id": {
@ -8730,6 +8732,10 @@
}
],
"nullable": true
},
"psp_tokenization_enabled": {
"type": "boolean",
"description": "Whether psp_tokenization is enabled for the payment_method, this will be true when at least\none multi-use token with status `Active` is available for the payment method"
}
}
},
@ -11603,7 +11609,7 @@
"product_type": {
"allOf": [
{
"$ref": "#/components/schemas/api_enums.MerchantProductType"
"$ref": "#/components/schemas/MerchantProductType"
}
],
"nullable": true
@ -11745,7 +11751,7 @@
"product_type": {
"allOf": [
{
"$ref": "#/components/schemas/api_enums.MerchantProductType"
"$ref": "#/components/schemas/MerchantProductType"
}
],
"nullable": true
@ -12359,6 +12365,17 @@
},
"additionalProperties": false
},
"MerchantProductType": {
"type": "string",
"enum": [
"orchestration",
"vault",
"recon",
"recovery",
"cost_observability",
"dynamic_routing"
]
},
"MerchantRecipientData": {
"oneOf": [
{
@ -12581,6 +12598,69 @@
}
}
},
"NetworkTokenDetailsPaymentMethod": {
"type": "object",
"properties": {
"last4_digits": {
"type": "string",
"nullable": true
},
"issuer_country": {
"type": "string",
"nullable": true
},
"network_token_expiry_month": {
"type": "string",
"nullable": true
},
"network_token_expiry_year": {
"type": "string",
"nullable": true
},
"nick_name": {
"type": "string",
"nullable": true
},
"card_holder_name": {
"type": "string",
"nullable": true
},
"card_isin": {
"type": "string",
"nullable": true
},
"card_issuer": {
"type": "string",
"nullable": true
},
"card_network": {
"allOf": [
{
"$ref": "#/components/schemas/CardNetwork"
}
],
"nullable": true
},
"card_type": {
"type": "string",
"nullable": true
},
"saved_to_locker": {
"type": "boolean"
}
}
},
"NetworkTokenResponse": {
"type": "object",
"required": [
"payment_method_data"
],
"properties": {
"payment_method_data": {
"$ref": "#/components/schemas/NetworkTokenDetailsPaymentMethod"
}
}
},
"NetworkTokenization": {
"type": "object",
"description": "The network tokenization configuration for creating the payment method session",
@ -13968,7 +14048,7 @@
"PaymentConnectorTransmission": {
"type": "string",
"enum": [
"ConnectorCallFailed",
"ConnectorCallUnsuccessful",
"ConnectorCallSucceeded"
]
},
@ -20385,6 +20465,7 @@
"prophetpay",
"rapyd",
"razorpay",
"recurly",
"riskified",
"shift4",
"signifyd",

View File

@ -9765,6 +9765,7 @@
"prophetpay",
"rapyd",
"razorpay",
"recurly",
"shift4",
"square",
"stax",
@ -13933,7 +13934,7 @@
"product_type": {
"allOf": [
{
"$ref": "#/components/schemas/api_enums.MerchantProductType"
"$ref": "#/components/schemas/MerchantProductType"
}
],
"nullable": true
@ -14174,7 +14175,7 @@
"product_type": {
"allOf": [
{
"$ref": "#/components/schemas/api_enums.MerchantProductType"
"$ref": "#/components/schemas/MerchantProductType"
}
],
"nullable": true
@ -15089,6 +15090,17 @@
},
"additionalProperties": false
},
"MerchantProductType": {
"type": "string",
"enum": [
"orchestration",
"vault",
"recon",
"recovery",
"cost_observability",
"dynamic_routing"
]
},
"MerchantRecipientData": {
"oneOf": [
{
@ -24881,6 +24893,7 @@
"prophetpay",
"rapyd",
"razorpay",
"recurly",
"riskified",
"shift4",
"signifyd",

View File

@ -113,7 +113,7 @@ pub struct MerchantAccountCreate {
pub pm_collect_link_config: Option<BusinessCollectLinkConfig>,
/// Product Type of this merchant account
#[schema(value_type = Option<api_enums::MerchantProductType>)]
#[schema(value_type = Option<MerchantProductType>)]
pub product_type: Option<api_enums::MerchantProductType>,
}
@ -198,6 +198,7 @@ pub struct MerchantAccountCreateWithoutOrgId {
#[schema(value_type = Option<Object>, example = r#"{ "city": "NY", "unit": "245" }"#)]
pub metadata: Option<pii::SecretSerdeValue>,
#[schema(value_type = Option<MerchantProductType>)]
pub product_type: Option<api_enums::MerchantProductType>,
}
@ -560,7 +561,7 @@ pub struct MerchantAccountResponse {
pub pm_collect_link_config: Option<BusinessCollectLinkConfig>,
/// Product Type of this merchant account
#[schema(value_type = Option<api_enums::MerchantProductType>)]
#[schema(value_type = Option<MerchantProductType>)]
pub product_type: Option<api_enums::MerchantProductType>,
}
@ -596,7 +597,7 @@ pub struct MerchantAccountResponse {
pub recon_status: api_enums::ReconStatus,
/// Product Type of this merchant account
#[schema(value_type = Option<api_enums::MerchantProductType>)]
#[schema(value_type = Option<MerchantProductType>)]
pub product_type: Option<api_enums::MerchantProductType>,
}

View File

@ -980,16 +980,21 @@ pub struct CardDetailsPaymentMethod {
pub saved_to_locker: bool,
}
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, ToSchema)]
pub struct NetworkTokenDetailsPaymentMethod {
pub last4_digits: Option<String>,
pub issuer_country: Option<String>,
#[schema(value_type = Option<String>)]
pub network_token_expiry_month: Option<masking::Secret<String>>,
#[schema(value_type = Option<String>)]
pub network_token_expiry_year: Option<masking::Secret<String>>,
#[schema(value_type = Option<String>)]
pub nick_name: Option<masking::Secret<String>>,
#[schema(value_type = Option<String>)]
pub card_holder_name: Option<masking::Secret<String>>,
pub card_isin: Option<String>,
pub card_issuer: Option<String>,
#[schema(value_type = Option<CardNetwork>)]
pub card_network: Option<api_enums::CardNetwork>,
pub card_type: Option<String>,
#[serde(default = "saved_in_locker_default")]
@ -2019,6 +2024,10 @@ pub struct CustomerPaymentMethod {
///The network token details for the payment method
pub network_tokenization: Option<NetworkTokenResponse>,
/// Whether psp_tokenization is enabled for the payment_method, this will be true when at least
/// one multi-use token with status `Active` is available for the payment method
pub psp_tokenization_enabled: bool,
}
#[cfg(all(feature = "v2", feature = "payment_methods_v2"))]

View File

@ -320,6 +320,7 @@ Never share your secret api keys. Keep them guarded and secure.
api_models::enums::PaymentLinkDetailsLayout,
api_models::enums::PaymentMethodStatus,
api_models::enums::UIWidgetFormLayout,
api_models::enums::MerchantProductType,
api_models::enums::PaymentConnectorCategory,
api_models::enums::CardDiscovery,
api_models::enums::FeatureStatus,

View File

@ -259,6 +259,7 @@ Never share your secret api keys. Keep them guarded and secure.
api_models::enums::PaymentMethod,
api_models::enums::PaymentMethodIssuerCode,
api_models::enums::MandateStatus,
api_models::enums::MerchantProductType,
api_models::enums::PaymentExperience,
api_models::enums::BankNames,
api_models::enums::BankType,
@ -527,6 +528,8 @@ Never share your secret api keys. Keep them guarded and secure.
api_models::payment_methods::PaymentMethodSessionRequest,
api_models::payment_methods::PaymentMethodSessionResponse,
api_models::payment_methods::PaymentMethodsSessionUpdateRequest,
api_models::payment_methods::NetworkTokenResponse,
api_models::payment_methods::NetworkTokenDetailsPaymentMethod,
api_models::payment_methods::TokenizeCardRequest,
api_models::payment_methods::TokenizeDataRequest,
api_models::payment_methods::TokenizePaymentMethodRequest,

View File

@ -326,7 +326,7 @@ pub async fn payment_method_delete_api() {}
///
/// List the payment methods saved for a customer
#[utoipa::path(
delete,
get,
path = "/v2/customers/{id}/saved-payment-methods",
params (
("id" = String, Path, description = "The unique identifier for the customer"),

View File

@ -985,6 +985,15 @@ impl transformers::ForeignTryFrom<domain::PaymentMethod> for api::CustomerPaymen
// TODO: check how we can get this field
let recurring_enabled = true;
let psp_tokenization_enabled = item.connector_mandate_details.and_then(|details| {
details.payments.map(|payments| {
payments.values().any(|connector_token_reference| {
connector_token_reference.connector_token_status
== api_enums::ConnectorTokenStatus::Active
})
})
});
Ok(Self {
id: item.id,
customer_id: item.customer_id,
@ -999,6 +1008,7 @@ impl transformers::ForeignTryFrom<domain::PaymentMethod> for api::CustomerPaymen
is_default: false,
billing: payment_method_billing,
network_tokenization: network_token_resp,
psp_tokenization_enabled: psp_tokenization_enabled.unwrap_or(false),
})
}
}