refactor(router): add revenue_recovery_metadata to payment intent in diesel and api model for v2 flow (#7176)

Co-authored-by: Nishanth Challa <nishanth.challa@Nishanth-Challa-C0WGKCFHLF.local>
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
CHALLA NISHANTH BABU
2025-02-14 16:19:58 +05:30
committed by GitHub
parent fbbbe3eb90
commit 2ee22cdf8a
6 changed files with 285 additions and 3 deletions

View File

@ -5793,6 +5793,23 @@
} }
} }
}, },
"BillingConnectorPaymentDetails": {
"type": "object",
"required": [
"payment_processor_token",
"connector_customer_id"
],
"properties": {
"payment_processor_token": {
"type": "string",
"description": "Payment Processor Token to process the Revenue Recovery Payment"
},
"connector_customer_id": {
"type": "string",
"description": "Billing Connector's Customer Id"
}
}
},
"BlikBankRedirectAdditionalData": { "BlikBankRedirectAdditionalData": {
"type": "object", "type": "object",
"properties": { "properties": {
@ -9025,6 +9042,14 @@
} }
], ],
"nullable": true "nullable": true
},
"payment_revenue_recovery_metadata": {
"allOf": [
{
"$ref": "#/components/schemas/PaymentRevenueRecoveryMetadata"
}
],
"nullable": true
} }
} }
}, },
@ -13167,6 +13192,13 @@
"bank_acquirer" "bank_acquirer"
] ]
}, },
"PaymentConnectorTransmission": {
"type": "string",
"enum": [
"ConnectorCallFailed",
"ConnectorCallSucceeded"
]
},
"PaymentCreatePaymentLinkConfig": { "PaymentCreatePaymentLinkConfig": {
"allOf": [ "allOf": [
{ {
@ -14926,6 +14958,49 @@
} }
} }
}, },
"PaymentRevenueRecoveryMetadata": {
"type": "object",
"required": [
"total_retry_count",
"payment_connector_transmission",
"billing_connector_id",
"active_attempt_payment_connector_id",
"billing_connector_payment_details",
"payment_method_type",
"payment_method_subtype"
],
"properties": {
"total_retry_count": {
"type": "integer",
"format": "int32",
"description": "Total number of billing connector + recovery retries for a payment intent.",
"example": "1",
"minimum": 0
},
"payment_connector_transmission": {
"$ref": "#/components/schemas/PaymentConnectorTransmission"
},
"billing_connector_id": {
"type": "string",
"description": "Billing Connector Id to update the invoices",
"example": "mca_1234567890"
},
"active_attempt_payment_connector_id": {
"type": "string",
"description": "Payment Connector Id to retry the payments",
"example": "mca_1234567890"
},
"billing_connector_payment_details": {
"$ref": "#/components/schemas/BillingConnectorPaymentDetails"
},
"payment_method_type": {
"$ref": "#/components/schemas/PaymentMethod"
},
"payment_method_subtype": {
"$ref": "#/components/schemas/PaymentMethodType"
}
}
},
"PaymentType": { "PaymentType": {
"type": "string", "type": "string",
"description": "The type of the payment that differentiates between normal and various types of mandate payments. Use 'setup_mandate' in case of zero auth flow.", "description": "The type of the payment that differentiates between normal and various types of mandate payments. Use 'setup_mandate' in case of zero auth flow.",

View File

@ -5,6 +5,8 @@ use std::{
}; };
pub mod additional_info; pub mod additional_info;
use cards::CardNumber; use cards::CardNumber;
#[cfg(feature = "v2")]
use common_enums::enums::PaymentConnectorTransmission;
use common_enums::ProductType; use common_enums::ProductType;
#[cfg(feature = "v2")] #[cfg(feature = "v2")]
use common_utils::id_type::GlobalPaymentId; use common_utils::id_type::GlobalPaymentId;
@ -7111,12 +7113,28 @@ pub struct PaymentsStartRequest {
} }
/// additional data that might be required by hyperswitch /// additional data that might be required by hyperswitch
#[cfg(feature = "v2")]
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize, ToSchema)]
pub struct FeatureMetadata {
/// Redirection response coming in request as metadata field only for redirection scenarios
#[schema(value_type = Option<RedirectResponse>)]
pub redirect_response: Option<RedirectResponse>,
/// Additional tags to be used for global search
#[schema(value_type = Option<Vec<String>>)]
pub search_tags: Option<Vec<HashedString<WithType>>>,
/// Recurring payment details required for apple pay Merchant Token
pub apple_pay_recurring_details: Option<ApplePayRecurringDetails>,
/// revenue recovery data for payment intent
pub payment_revenue_recovery_metadata: Option<PaymentRevenueRecoveryMetadata>,
}
/// additional data that might be required by hyperswitch
#[cfg(feature = "v1")]
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize, ToSchema)] #[derive(Debug, Clone, serde::Deserialize, serde::Serialize, ToSchema)]
pub struct FeatureMetadata { pub struct FeatureMetadata {
/// Redirection response coming in request as metadata field only for redirection scenarios /// Redirection response coming in request as metadata field only for redirection scenarios
#[schema(value_type = Option<RedirectResponse>)] #[schema(value_type = Option<RedirectResponse>)]
pub redirect_response: Option<RedirectResponse>, pub redirect_response: Option<RedirectResponse>,
// TODO: Convert this to hashedstrings to avoid PII sensitive data
/// Additional tags to be used for global search /// Additional tags to be used for global search
#[schema(value_type = Option<Vec<String>>)] #[schema(value_type = Option<Vec<String>>)]
pub search_tags: Option<Vec<HashedString<WithType>>>, pub search_tags: Option<Vec<HashedString<WithType>>>,
@ -7977,3 +7995,36 @@ mod billing_from_payment_method_data {
assert!(billing_details.is_none()); assert!(billing_details.is_none());
} }
} }
#[cfg(feature = "v2")]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct PaymentRevenueRecoveryMetadata {
/// Total number of billing connector + recovery retries for a payment intent.
#[schema(value_type = u16,example = "1")]
pub total_retry_count: u16,
/// Flag for the payment connector's call
pub payment_connector_transmission: PaymentConnectorTransmission,
/// Billing Connector Id to update the invoices
#[schema(value_type = String, example = "mca_1234567890")]
pub billing_connector_id: id_type::MerchantConnectorAccountId,
/// Payment Connector Id to retry the payments
#[schema(value_type = String, example = "mca_1234567890")]
pub active_attempt_payment_connector_id: id_type::MerchantConnectorAccountId,
/// Billing Connector Payment Details
#[schema(value_type = BillingConnectorPaymentDetails)]
pub billing_connector_payment_details: BillingConnectorPaymentDetails,
/// Payment Method Type
#[schema(example = "pay_later", value_type = PaymentMethod)]
pub payment_method_type: common_enums::PaymentMethod,
/// PaymentMethod Subtype
#[schema(example = "klarna", value_type = PaymentMethodType)]
pub payment_method_subtype: common_enums::PaymentMethodType,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[cfg(feature = "v2")]
pub struct BillingConnectorPaymentDetails {
/// Payment Processor Token to process the Revenue Recovery Payment
pub payment_processor_token: String,
/// Billing Connector's Customer Id
pub connector_customer_id: String,
}

View File

@ -3768,3 +3768,12 @@ pub enum AdyenSplitType {
/// The value-added tax charged on the payment, booked to your platforms liable balance account. /// The value-added tax charged on the payment, booked to your platforms liable balance account.
Vat, Vat,
} }
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
#[serde(rename = "snake_case")]
pub enum PaymentConnectorTransmission {
/// Failed to call the payment connector
ConnectorCallFailed,
/// Payment Connector call succeeded
ConnectorCallSucceeded,
}

View File

@ -1,10 +1,12 @@
#[cfg(feature = "v2")]
use common_enums::{enums::PaymentConnectorTransmission, PaymentMethod, PaymentMethodType};
use common_utils::{hashing::HashedString, pii, types::MinorUnit}; use common_utils::{hashing::HashedString, pii, types::MinorUnit};
use diesel::{ use diesel::{
sql_types::{Json, Jsonb}, sql_types::{Json, Jsonb},
AsExpression, FromSqlRow, AsExpression, FromSqlRow,
}; };
use masking::{Secret, WithType}; use masking::{Secret, WithType};
use serde::{Deserialize, Serialize}; use serde::{self, Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, FromSqlRow, AsExpression)] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize, FromSqlRow, AsExpression)]
#[diesel(sql_type = Jsonb)] #[diesel(sql_type = Jsonb)]
pub struct OrderDetailsWithAmount { pub struct OrderDetailsWithAmount {
@ -40,12 +42,26 @@ impl masking::SerializableSecret for OrderDetailsWithAmount {}
common_utils::impl_to_sql_from_sql_json!(OrderDetailsWithAmount); common_utils::impl_to_sql_from_sql_json!(OrderDetailsWithAmount);
#[cfg(feature = "v2")]
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, FromSqlRow, AsExpression)]
#[diesel(sql_type = Json)]
pub struct FeatureMetadata {
/// Redirection response coming in request as metadata field only for redirection scenarios
pub redirect_response: Option<RedirectResponse>,
/// Additional tags to be used for global search
pub search_tags: Option<Vec<HashedString<WithType>>>,
/// Recurring payment details required for apple pay Merchant Token
pub apple_pay_recurring_details: Option<ApplePayRecurringDetails>,
/// revenue recovery data for payment intent
pub payment_revenue_recovery_metadata: Option<PaymentRevenueRecoveryMetadata>,
}
#[cfg(feature = "v1")]
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, FromSqlRow, AsExpression)] #[derive(Debug, Clone, PartialEq, Deserialize, Serialize, FromSqlRow, AsExpression)]
#[diesel(sql_type = Json)] #[diesel(sql_type = Json)]
pub struct FeatureMetadata { pub struct FeatureMetadata {
/// Redirection response coming in request as metadata field only for redirection scenarios /// Redirection response coming in request as metadata field only for redirection scenarios
pub redirect_response: Option<RedirectResponse>, pub redirect_response: Option<RedirectResponse>,
// TODO: Convert this to hashedstrings to avoid PII sensitive data
/// Additional tags to be used for global search /// Additional tags to be used for global search
pub search_tags: Option<Vec<HashedString<WithType>>>, pub search_tags: Option<Vec<HashedString<WithType>>>,
/// Recurring payment details required for apple pay Merchant Token /// Recurring payment details required for apple pay Merchant Token
@ -106,3 +122,31 @@ pub struct RedirectResponse {
} }
impl masking::SerializableSecret for RedirectResponse {} impl masking::SerializableSecret for RedirectResponse {}
common_utils::impl_to_sql_from_sql_json!(RedirectResponse); common_utils::impl_to_sql_from_sql_json!(RedirectResponse);
#[cfg(feature = "v2")]
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
pub struct PaymentRevenueRecoveryMetadata {
/// Total number of billing connector + recovery retries for a payment intent.
pub total_retry_count: u16,
/// Flag for the payment connector's call
pub payment_connector_transmission: PaymentConnectorTransmission,
/// Billing Connector Id to update the invoices
pub billing_connector_id: common_utils::id_type::MerchantConnectorAccountId,
/// Payment Connector Id to retry the payments
pub active_attempt_payment_connector_id: common_utils::id_type::MerchantConnectorAccountId,
/// Billing Connector Payment Details
pub billing_connector_payment_details: BillingConnectorPaymentDetails,
///Payment Method Type
pub payment_method_type: PaymentMethod,
/// PaymentMethod Subtype
pub payment_method_subtype: PaymentMethodType,
}
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
#[cfg(feature = "v2")]
pub struct BillingConnectorPaymentDetails {
/// Payment Processor Token to process the Revenue Recovery Payment
pub payment_processor_token: String,
/// Billing Connector's Customer Id
pub connector_customer_id: String,
}

View File

@ -40,10 +40,17 @@ use api_models::payments::{
RecurringPaymentIntervalUnit as ApiRecurringPaymentIntervalUnit, RecurringPaymentIntervalUnit as ApiRecurringPaymentIntervalUnit,
RedirectResponse as ApiRedirectResponse, RedirectResponse as ApiRedirectResponse,
}; };
#[cfg(feature = "v2")]
use api_models::payments::{
BillingConnectorPaymentDetails as ApiBillingConnectorPaymentDetails,
PaymentRevenueRecoveryMetadata as ApiRevenueRecoveryMetadata,
};
use diesel_models::types::{ use diesel_models::types::{
ApplePayRecurringDetails, ApplePayRegularBillingDetails, FeatureMetadata, ApplePayRecurringDetails, ApplePayRegularBillingDetails, FeatureMetadata,
OrderDetailsWithAmount, RecurringPaymentIntervalUnit, RedirectResponse, OrderDetailsWithAmount, RecurringPaymentIntervalUnit, RedirectResponse,
}; };
#[cfg(feature = "v2")]
use diesel_models::types::{BillingConnectorPaymentDetails, PaymentRevenueRecoveryMetadata};
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize)] #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize)]
pub enum RemoteStorageObject<T: ForeignIDRef> { pub enum RemoteStorageObject<T: ForeignIDRef> {
@ -78,6 +85,7 @@ pub trait ApiModelToDieselModelConvertor<F> {
fn convert_back(self) -> F; fn convert_back(self) -> F;
} }
#[cfg(feature = "v1")]
impl ApiModelToDieselModelConvertor<ApiFeatureMetadata> for FeatureMetadata { impl ApiModelToDieselModelConvertor<ApiFeatureMetadata> for FeatureMetadata {
fn convert_from(from: ApiFeatureMetadata) -> Self { fn convert_from(from: ApiFeatureMetadata) -> Self {
let ApiFeatureMetadata { let ApiFeatureMetadata {
@ -85,6 +93,7 @@ impl ApiModelToDieselModelConvertor<ApiFeatureMetadata> for FeatureMetadata {
search_tags, search_tags,
apple_pay_recurring_details, apple_pay_recurring_details,
} = from; } = from;
Self { Self {
redirect_response: redirect_response.map(RedirectResponse::convert_from), redirect_response: redirect_response.map(RedirectResponse::convert_from),
search_tags, search_tags,
@ -99,6 +108,7 @@ impl ApiModelToDieselModelConvertor<ApiFeatureMetadata> for FeatureMetadata {
search_tags, search_tags,
apple_pay_recurring_details, apple_pay_recurring_details,
} = self; } = self;
ApiFeatureMetadata { ApiFeatureMetadata {
redirect_response: redirect_response redirect_response: redirect_response
.map(|redirect_response| redirect_response.convert_back()), .map(|redirect_response| redirect_response.convert_back()),
@ -109,6 +119,46 @@ impl ApiModelToDieselModelConvertor<ApiFeatureMetadata> for FeatureMetadata {
} }
} }
#[cfg(feature = "v2")]
impl ApiModelToDieselModelConvertor<ApiFeatureMetadata> for FeatureMetadata {
fn convert_from(from: ApiFeatureMetadata) -> Self {
let ApiFeatureMetadata {
redirect_response,
search_tags,
apple_pay_recurring_details,
payment_revenue_recovery_metadata,
} = from;
Self {
redirect_response: redirect_response.map(RedirectResponse::convert_from),
search_tags,
apple_pay_recurring_details: apple_pay_recurring_details
.map(ApplePayRecurringDetails::convert_from),
payment_revenue_recovery_metadata: payment_revenue_recovery_metadata
.map(PaymentRevenueRecoveryMetadata::convert_from),
}
}
fn convert_back(self) -> ApiFeatureMetadata {
let Self {
redirect_response,
search_tags,
apple_pay_recurring_details,
payment_revenue_recovery_metadata,
} = self;
ApiFeatureMetadata {
redirect_response: redirect_response
.map(|redirect_response| redirect_response.convert_back()),
search_tags,
apple_pay_recurring_details: apple_pay_recurring_details
.map(|value| value.convert_back()),
payment_revenue_recovery_metadata: payment_revenue_recovery_metadata
.map(|value| value.convert_back()),
}
}
}
impl ApiModelToDieselModelConvertor<ApiRedirectResponse> for RedirectResponse { impl ApiModelToDieselModelConvertor<ApiRedirectResponse> for RedirectResponse {
fn convert_from(from: ApiRedirectResponse) -> Self { fn convert_from(from: ApiRedirectResponse) -> Self {
let ApiRedirectResponse { let ApiRedirectResponse {
@ -204,6 +254,56 @@ impl ApiModelToDieselModelConvertor<ApiApplePayRecurringDetails> for ApplePayRec
} }
} }
#[cfg(feature = "v2")]
impl ApiModelToDieselModelConvertor<ApiRevenueRecoveryMetadata> for PaymentRevenueRecoveryMetadata {
fn convert_from(from: ApiRevenueRecoveryMetadata) -> Self {
Self {
total_retry_count: from.total_retry_count,
payment_connector_transmission: from.payment_connector_transmission,
billing_connector_id: from.billing_connector_id,
active_attempt_payment_connector_id: from.active_attempt_payment_connector_id,
billing_connector_payment_details: BillingConnectorPaymentDetails::convert_from(
from.billing_connector_payment_details,
),
payment_method_type: from.payment_method_type,
payment_method_subtype: from.payment_method_subtype,
}
}
fn convert_back(self) -> ApiRevenueRecoveryMetadata {
ApiRevenueRecoveryMetadata {
total_retry_count: self.total_retry_count,
payment_connector_transmission: self.payment_connector_transmission,
billing_connector_id: self.billing_connector_id,
active_attempt_payment_connector_id: self.active_attempt_payment_connector_id,
billing_connector_payment_details: self
.billing_connector_payment_details
.convert_back(),
payment_method_type: self.payment_method_type,
payment_method_subtype: self.payment_method_subtype,
}
}
}
#[cfg(feature = "v2")]
impl ApiModelToDieselModelConvertor<ApiBillingConnectorPaymentDetails>
for BillingConnectorPaymentDetails
{
fn convert_from(from: ApiBillingConnectorPaymentDetails) -> Self {
Self {
payment_processor_token: from.payment_processor_token,
connector_customer_id: from.connector_customer_id,
}
}
fn convert_back(self) -> ApiBillingConnectorPaymentDetails {
ApiBillingConnectorPaymentDetails {
payment_processor_token: self.payment_processor_token,
connector_customer_id: self.connector_customer_id,
}
}
}
impl ApiModelToDieselModelConvertor<ApiOrderDetailsWithAmount> for OrderDetailsWithAmount { impl ApiModelToDieselModelConvertor<ApiOrderDetailsWithAmount> for OrderDetailsWithAmount {
fn convert_from(from: ApiOrderDetailsWithAmount) -> Self { fn convert_from(from: ApiOrderDetailsWithAmount) -> Self {
let ApiOrderDetailsWithAmount { let ApiOrderDetailsWithAmount {

View File

@ -466,6 +466,9 @@ Never share your secret api keys. Keep them guarded and secure.
api_models::payments::BacsBankTransferInstructions, api_models::payments::BacsBankTransferInstructions,
api_models::payments::RedirectResponse, api_models::payments::RedirectResponse,
api_models::payments::RequestSurchargeDetails, api_models::payments::RequestSurchargeDetails,
api_models::payments::PaymentRevenueRecoveryMetadata,
api_models::payments::BillingConnectorPaymentDetails,
api_models::enums::PaymentConnectorTransmission,
api_models::payments::PaymentAttemptResponse, api_models::payments::PaymentAttemptResponse,
api_models::payments::PaymentAttemptAmountDetails, api_models::payments::PaymentAttemptAmountDetails,
api_models::payments::CaptureResponse, api_models::payments::CaptureResponse,