mirror of
				https://github.com/juspay/hyperswitch.git
				synced 2025-10-31 10:06:32 +08:00 
			
		
		
		
	feat(connector): [Stripe] Add support for refund webhooks (#1488)
This commit is contained in:
		 Sangamesh Kulkarni
					Sangamesh Kulkarni
				
			
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			 GitHub
						GitHub
					
				
			
						parent
						
							82545555d7
						
					
				
				
					commit
					e6529b6a63
				
			| @ -41,21 +41,22 @@ pub enum WebhookFlow { | |||||||
| impl From<IncomingWebhookEvent> for WebhookFlow { | impl From<IncomingWebhookEvent> for WebhookFlow { | ||||||
|     fn from(evt: IncomingWebhookEvent) -> Self { |     fn from(evt: IncomingWebhookEvent) -> Self { | ||||||
|         match evt { |         match evt { | ||||||
|             IncomingWebhookEvent::PaymentIntentFailure => Self::Payment, |             IncomingWebhookEvent::PaymentIntentFailure | ||||||
|             IncomingWebhookEvent::PaymentIntentSuccess => Self::Payment, |             | IncomingWebhookEvent::PaymentIntentSuccess | ||||||
|             IncomingWebhookEvent::PaymentIntentProcessing => Self::Payment, |             | IncomingWebhookEvent::PaymentIntentProcessing | ||||||
|             IncomingWebhookEvent::PaymentActionRequired => Self::Payment, |             | IncomingWebhookEvent::PaymentActionRequired | ||||||
|             IncomingWebhookEvent::PaymentIntentPartiallyFunded => Self::Payment, |             | IncomingWebhookEvent::PaymentIntentPartiallyFunded => Self::Payment, | ||||||
|             IncomingWebhookEvent::EventNotSupported => Self::ReturnResponse, |             IncomingWebhookEvent::EventNotSupported => Self::ReturnResponse, | ||||||
|             IncomingWebhookEvent::RefundSuccess => Self::Refund, |             IncomingWebhookEvent::RefundSuccess | IncomingWebhookEvent::RefundFailure => { | ||||||
|             IncomingWebhookEvent::RefundFailure => Self::Refund, |                 Self::Refund | ||||||
|             IncomingWebhookEvent::DisputeOpened => Self::Dispute, |             } | ||||||
|             IncomingWebhookEvent::DisputeAccepted => Self::Dispute, |             IncomingWebhookEvent::DisputeOpened | ||||||
|             IncomingWebhookEvent::DisputeExpired => Self::Dispute, |             | IncomingWebhookEvent::DisputeAccepted | ||||||
|             IncomingWebhookEvent::DisputeCancelled => Self::Dispute, |             | IncomingWebhookEvent::DisputeExpired | ||||||
|             IncomingWebhookEvent::DisputeChallenged => Self::Dispute, |             | IncomingWebhookEvent::DisputeCancelled | ||||||
|             IncomingWebhookEvent::DisputeWon => Self::Dispute, |             | IncomingWebhookEvent::DisputeChallenged | ||||||
|             IncomingWebhookEvent::DisputeLost => Self::Dispute, |             | IncomingWebhookEvent::DisputeWon | ||||||
|  |             | IncomingWebhookEvent::DisputeLost => Self::Dispute, | ||||||
|             IncomingWebhookEvent::EndpointVerification => Self::ReturnResponse, |             IncomingWebhookEvent::EndpointVerification => Self::ReturnResponse, | ||||||
|             IncomingWebhookEvent::SourceChargeable |             IncomingWebhookEvent::SourceChargeable | ||||||
|             | IncomingWebhookEvent::SourceTransactionCreated => Self::BankTransfer, |             | IncomingWebhookEvent::SourceTransactionCreated => Self::BankTransfer, | ||||||
|  | |||||||
| @ -1744,6 +1744,13 @@ impl api::IncomingWebhook for Stripe { | |||||||
|                     ), |                     ), | ||||||
|                 ) |                 ) | ||||||
|             } |             } | ||||||
|  |             stripe::WebhookEventObjectType::Refund => { | ||||||
|  |                 api_models::webhooks::ObjectReferenceId::RefundId( | ||||||
|  |                     api_models::webhooks::RefundIdType::ConnectorRefundId( | ||||||
|  |                         details.event_data.event_object.id, | ||||||
|  |                     ), | ||||||
|  |                 ) | ||||||
|  |             } | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @ -1753,7 +1760,7 @@ impl api::IncomingWebhook for Stripe { | |||||||
|     ) -> CustomResult<api::IncomingWebhookEvent, errors::ConnectorError> { |     ) -> CustomResult<api::IncomingWebhookEvent, errors::ConnectorError> { | ||||||
|         let details: stripe::WebhookEventTypeBody = request |         let details: stripe::WebhookEventTypeBody = request | ||||||
|             .body |             .body | ||||||
|             .parse_struct("WebhookEvent") |             .parse_struct("WebhookEventTypeBody") | ||||||
|             .change_context(errors::ConnectorError::WebhookReferenceIdNotFound)?; |             .change_context(errors::ConnectorError::WebhookReferenceIdNotFound)?; | ||||||
|  |  | ||||||
|         Ok(match details.event_type { |         Ok(match details.event_type { | ||||||
| @ -1773,6 +1780,18 @@ impl api::IncomingWebhook for Stripe { | |||||||
|                     api::IncomingWebhookEvent::EventNotSupported |                     api::IncomingWebhookEvent::EventNotSupported | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |             stripe::WebhookEventType::ChargeRefundUpdated => details | ||||||
|  |                 .event_data | ||||||
|  |                 .event_object | ||||||
|  |                 .status | ||||||
|  |                 .map(|status| match status { | ||||||
|  |                     stripe::WebhookEventStatus::Succeeded => { | ||||||
|  |                         api::IncomingWebhookEvent::RefundSuccess | ||||||
|  |                     } | ||||||
|  |                     stripe::WebhookEventStatus::Failed => api::IncomingWebhookEvent::RefundFailure, | ||||||
|  |                     _ => api::IncomingWebhookEvent::EventNotSupported, | ||||||
|  |                 }) | ||||||
|  |                 .unwrap_or(api::IncomingWebhookEvent::EventNotSupported), | ||||||
|             stripe::WebhookEventType::SourceChargeable => { |             stripe::WebhookEventType::SourceChargeable => { | ||||||
|                 api::IncomingWebhookEvent::SourceChargeable |                 api::IncomingWebhookEvent::SourceChargeable | ||||||
|             } |             } | ||||||
| @ -1799,7 +1818,7 @@ impl api::IncomingWebhook for Stripe { | |||||||
|             | stripe::WebhookEventType::ChargeFailed |             | stripe::WebhookEventType::ChargeFailed | ||||||
|             | stripe::WebhookEventType::ChargePending |             | stripe::WebhookEventType::ChargePending | ||||||
|             | stripe::WebhookEventType::ChargeUpdated |             | stripe::WebhookEventType::ChargeUpdated | ||||||
|             | stripe::WebhookEventType::ChanrgeRefunded |             | stripe::WebhookEventType::ChargeRefunded | ||||||
|             | stripe::WebhookEventType::PaymentIntentCanceled |             | stripe::WebhookEventType::PaymentIntentCanceled | ||||||
|             | stripe::WebhookEventType::PaymentIntentCreated |             | stripe::WebhookEventType::PaymentIntentCreated | ||||||
|             | stripe::WebhookEventType::PaymentIntentProcessing |             | stripe::WebhookEventType::PaymentIntentProcessing | ||||||
|  | |||||||
| @ -571,6 +571,7 @@ pub enum StripeBankNames { | |||||||
|     Boz, |     Boz, | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // This is used only for Disputes | ||||||
| impl From<WebhookEventStatus> for api_models::webhooks::IncomingWebhookEvent { | impl From<WebhookEventStatus> for api_models::webhooks::IncomingWebhookEvent { | ||||||
|     fn from(value: WebhookEventStatus) -> Self { |     fn from(value: WebhookEventStatus) -> Self { | ||||||
|         match value { |         match value { | ||||||
| @ -590,6 +591,7 @@ impl From<WebhookEventStatus> for api_models::webhooks::IncomingWebhookEvent { | |||||||
|             | WebhookEventStatus::RequiresCapture |             | WebhookEventStatus::RequiresCapture | ||||||
|             | WebhookEventStatus::Canceled |             | WebhookEventStatus::Canceled | ||||||
|             | WebhookEventStatus::Chargeable |             | WebhookEventStatus::Chargeable | ||||||
|  |             | WebhookEventStatus::Failed | ||||||
|             | WebhookEventStatus::Unknown => Self::EventNotSupported, |             | WebhookEventStatus::Unknown => Self::EventNotSupported, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -2371,6 +2373,7 @@ pub enum WebhookEventObjectType { | |||||||
|     Dispute, |     Dispute, | ||||||
|     Charge, |     Charge, | ||||||
|     Source, |     Source, | ||||||
|  |     Refund, | ||||||
| } | } | ||||||
|  |  | ||||||
| #[derive(Debug, Deserialize)] | #[derive(Debug, Deserialize)] | ||||||
| @ -2399,12 +2402,14 @@ pub enum WebhookEventType { | |||||||
|     ChargePending, |     ChargePending, | ||||||
|     #[serde(rename = "charge.captured")] |     #[serde(rename = "charge.captured")] | ||||||
|     ChargeCaptured, |     ChargeCaptured, | ||||||
|  |     #[serde(rename = "charge.refund.updated")] | ||||||
|  |     ChargeRefundUpdated, | ||||||
|     #[serde(rename = "charge.succeeded")] |     #[serde(rename = "charge.succeeded")] | ||||||
|     ChargeSucceeded, |     ChargeSucceeded, | ||||||
|     #[serde(rename = "charge.updated")] |     #[serde(rename = "charge.updated")] | ||||||
|     ChargeUpdated, |     ChargeUpdated, | ||||||
|     #[serde(rename = "charge.refunded")] |     #[serde(rename = "charge.refunded")] | ||||||
|     ChanrgeRefunded, |     ChargeRefunded, | ||||||
|     #[serde(rename = "payment_intent.canceled")] |     #[serde(rename = "payment_intent.canceled")] | ||||||
|     PaymentIntentCanceled, |     PaymentIntentCanceled, | ||||||
|     #[serde(rename = "payment_intent.created")] |     #[serde(rename = "payment_intent.created")] | ||||||
| @ -2444,6 +2449,7 @@ pub enum WebhookEventStatus { | |||||||
|     RequiresCapture, |     RequiresCapture, | ||||||
|     Canceled, |     Canceled, | ||||||
|     Chargeable, |     Chargeable, | ||||||
|  |     Failed, | ||||||
|     #[serde(other)] |     #[serde(other)] | ||||||
|     Unknown, |     Unknown, | ||||||
| } | } | ||||||
|  | |||||||
| @ -117,9 +117,17 @@ pub async fn refunds_incoming_webhook_flow<W: api::OutgoingWebhookType>( | |||||||
|     let db = &*state.store; |     let db = &*state.store; | ||||||
|     //find refund by connector refund id |     //find refund by connector refund id | ||||||
|     let refund = match webhook_details.object_reference_id { |     let refund = match webhook_details.object_reference_id { | ||||||
|         api_models::webhooks::ObjectReferenceId::RefundId( |         api_models::webhooks::ObjectReferenceId::RefundId(refund_id_type) => match refund_id_type { | ||||||
|             api_models::webhooks::RefundIdType::ConnectorRefundId(id), |             api_models::webhooks::RefundIdType::RefundId(id) => db | ||||||
|         ) => db |                 .find_refund_by_merchant_id_refund_id( | ||||||
|  |                     &merchant_account.merchant_id, | ||||||
|  |                     &id, | ||||||
|  |                     merchant_account.storage_scheme, | ||||||
|  |                 ) | ||||||
|  |                 .await | ||||||
|  |                 .change_context(errors::ApiErrorResponse::WebhookResourceNotFound) | ||||||
|  |                 .attach_printable_lazy(|| "Failed fetching the refund")?, | ||||||
|  |             api_models::webhooks::RefundIdType::ConnectorRefundId(id) => db | ||||||
|                 .find_refund_by_merchant_id_connector_refund_id_connector( |                 .find_refund_by_merchant_id_connector_refund_id_connector( | ||||||
|                     &merchant_account.merchant_id, |                     &merchant_account.merchant_id, | ||||||
|                     &id, |                     &id, | ||||||
| @ -129,17 +137,7 @@ pub async fn refunds_incoming_webhook_flow<W: api::OutgoingWebhookType>( | |||||||
|                 .await |                 .await | ||||||
|                 .change_context(errors::ApiErrorResponse::WebhookResourceNotFound) |                 .change_context(errors::ApiErrorResponse::WebhookResourceNotFound) | ||||||
|                 .attach_printable_lazy(|| "Failed fetching the refund")?, |                 .attach_printable_lazy(|| "Failed fetching the refund")?, | ||||||
|         api_models::webhooks::ObjectReferenceId::RefundId( |         }, | ||||||
|             api_models::webhooks::RefundIdType::RefundId(id), |  | ||||||
|         ) => db |  | ||||||
|             .find_refund_by_merchant_id_refund_id( |  | ||||||
|                 &merchant_account.merchant_id, |  | ||||||
|                 &id, |  | ||||||
|                 merchant_account.storage_scheme, |  | ||||||
|             ) |  | ||||||
|             .await |  | ||||||
|             .change_context(errors::ApiErrorResponse::WebhookResourceNotFound) |  | ||||||
|             .attach_printable_lazy(|| "Failed fetching the refund")?, |  | ||||||
|         _ => Err(errors::ApiErrorResponse::WebhookProcessingFailure) |         _ => Err(errors::ApiErrorResponse::WebhookProcessingFailure) | ||||||
|             .into_report() |             .into_report() | ||||||
|             .attach_printable("received a non-refund id when processing refund webhooks")?, |             .attach_printable("received a non-refund id when processing refund webhooks")?, | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user