feat(connector): Add support for passive churn recovery webhooks (#7109)

Co-authored-by: Chikke Srujan <chikke.srujan@Chikke-Srujan-N7WRTY72X7.local>
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
chikke srujan
2025-02-23 02:28:10 +05:30
committed by GitHub
parent 11ff437456
commit 0688972814
32 changed files with 992 additions and 36 deletions

View File

@ -1511,8 +1511,8 @@ pub struct PaymentAttemptResponse {
pub payment_method_subtype: Option<api_enums::PaymentMethodType>,
/// A unique identifier for a payment provided by the connector
#[schema(value_type = Option<String>, example = "993672945374576J")]
pub connector_payment_id: Option<String>,
#[schema(value_type = String)]
pub connector_payment_id: Option<common_utils::types::ConnectorTransactionId>,
/// Identifier for Payment Method used for the payment attempt
#[schema(value_type = Option<String>, example = "12345_pm_01926c58bc6e77c09e809964e72af8c8")]
@ -1522,6 +1522,24 @@ pub struct PaymentAttemptResponse {
pub client_source: Option<String>,
/// Value passed in X-CLIENT-VERSION header during payments confirm request by the client
pub client_version: Option<String>,
/// Additional data that might be required by hyperswitch, to enable some specific features.
pub feature_metadata: Option<PaymentAttemptFeatureMetadata>,
}
#[cfg(feature = "v2")]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, PartialEq, ToSchema)]
pub struct PaymentAttemptFeatureMetadata {
/// Revenue recovery metadata that might be required by hyperswitch.
pub revenue_recovery: Option<PaymentAttemptRevenueRecoveryData>,
}
#[cfg(feature = "v2")]
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, PartialEq, ToSchema)]
pub struct PaymentAttemptRevenueRecoveryData {
/// Flag to find out whether an attempt was created by external or internal system.
#[schema(value_type = Option<TriggeredBy>, example = "internal")]
pub attempt_triggered_by: common_enums::TriggeredBy,
}
#[derive(
@ -5563,6 +5581,26 @@ pub struct PaymentsRetrieveResponse {
pub attempts: Option<Vec<PaymentAttemptResponse>>,
}
#[cfg(feature = "v2")]
impl PaymentsRetrieveResponse {
pub fn find_attempt_in_attempts_list_using_connector_transaction_id(
self,
connector_transaction_id: &common_utils::types::ConnectorTransactionId,
) -> Option<PaymentAttemptResponse> {
self.attempts
.as_ref()
.and_then(|attempts| {
attempts.iter().find(|attempt| {
attempt
.connector_payment_id
.as_ref()
.is_some_and(|txn_id| txn_id == connector_transaction_id)
})
})
.cloned()
}
}
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
#[cfg(feature = "v2")]
pub struct PaymentStartRedirectionRequest {

View File

@ -57,6 +57,14 @@ pub enum IncomingWebhookEvent {
PayoutExpired,
#[cfg(feature = "payouts")]
PayoutReversed,
#[cfg(all(feature = "revenue_recovery", feature = "v2"))]
RecoveryPaymentFailure,
#[cfg(all(feature = "revenue_recovery", feature = "v2"))]
RecoveryPaymentSuccess,
#[cfg(all(feature = "revenue_recovery", feature = "v2"))]
RecoveryPaymentPending,
#[cfg(all(feature = "revenue_recovery", feature = "v2"))]
RecoveryInvoiceCancel,
}
pub enum WebhookFlow {
@ -71,6 +79,8 @@ pub enum WebhookFlow {
Mandate,
ExternalAuthentication,
FraudCheck,
#[cfg(all(feature = "revenue_recovery", feature = "v2"))]
Recovery,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
@ -197,6 +207,11 @@ impl From<IncomingWebhookEvent> for WebhookFlow {
| IncomingWebhookEvent::PayoutCreated
| IncomingWebhookEvent::PayoutExpired
| IncomingWebhookEvent::PayoutReversed => Self::Payout,
#[cfg(all(feature = "revenue_recovery", feature = "v2"))]
IncomingWebhookEvent::RecoveryInvoiceCancel
| IncomingWebhookEvent::RecoveryPaymentFailure
| IncomingWebhookEvent::RecoveryPaymentPending
| IncomingWebhookEvent::RecoveryPaymentSuccess => Self::Recovery,
}
}
}
@ -236,6 +251,14 @@ pub enum ObjectReferenceId {
ExternalAuthenticationID(AuthenticationIdType),
#[cfg(feature = "payouts")]
PayoutId(PayoutIdType),
#[cfg(all(feature = "revenue_recovery", feature = "v2"))]
InvoiceId(InvoiceIdType),
}
#[cfg(all(feature = "revenue_recovery", feature = "v2"))]
#[derive(Clone)]
pub enum InvoiceIdType {
ConnectorInvoiceId(String),
}
pub struct IncomingWebhookDetails {
@ -303,3 +326,15 @@ pub struct ConnectorWebhookSecrets {
pub secret: Vec<u8>,
pub additional_secret: Option<masking::Secret<String>>,
}
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
impl IncomingWebhookEvent {
pub fn is_recovery_transaction_event(&self) -> bool {
matches!(
self,
Self::RecoveryPaymentFailure
| Self::RecoveryPaymentSuccess
| Self::RecoveryPaymentPending
)
}
}