mirror of
				https://github.com/juspay/hyperswitch.git
				synced 2025-10-31 10:06:32 +08:00 
			
		
		
		
	feat: ACH transfers (#905)
This commit is contained in:
		 Sangamesh Kulkarni
					Sangamesh Kulkarni
				
			
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			 GitHub
						GitHub
					
				
			
						parent
						
							39405bb478
						
					
				
				
					commit
					23bca66b81
				
			| @ -1,7 +1,7 @@ | ||||
| pub mod transformers; | ||||
| pub mod utils; | ||||
|  | ||||
| use error_stack::{IntoReport, ResultExt}; | ||||
| use error_stack::{report, IntoReport, ResultExt}; | ||||
| use masking::ExposeInterface; | ||||
| use router_env::{instrument, tracing}; | ||||
|  | ||||
| @ -197,7 +197,7 @@ pub async fn refunds_incoming_webhook_flow<W: api::OutgoingWebhookType>( | ||||
| } | ||||
|  | ||||
| pub async fn get_payment_attempt_from_object_reference_id( | ||||
|     state: AppState, | ||||
|     state: &AppState, | ||||
|     object_reference_id: api_models::webhooks::ObjectReferenceId, | ||||
|     merchant_account: &storage::MerchantAccount, | ||||
| ) -> CustomResult<storage_models::payment_attempt::PaymentAttempt, errors::WebhooksFlowError> { | ||||
| @ -219,6 +219,14 @@ pub async fn get_payment_attempt_from_object_reference_id( | ||||
|             ) | ||||
|             .await | ||||
|             .change_context(errors::WebhooksFlowError::ResourceNotFound), | ||||
|         api::ObjectReferenceId::PaymentId(api::PaymentIdType::PreprocessingId(ref id)) => db | ||||
|             .find_payment_attempt_by_preprocessing_id_merchant_id( | ||||
|                 id, | ||||
|                 &merchant_account.merchant_id, | ||||
|                 merchant_account.storage_scheme, | ||||
|             ) | ||||
|             .await | ||||
|             .change_context(errors::WebhooksFlowError::ResourceNotFound), | ||||
|         _ => Err(errors::WebhooksFlowError::ResourceNotFound).into_report(), | ||||
|     } | ||||
| } | ||||
| @ -311,7 +319,7 @@ pub async fn disputes_incoming_webhook_flow<W: api::OutgoingWebhookType>( | ||||
|             .get_dispute_details(request_details) | ||||
|             .change_context(errors::WebhooksFlowError::WebhookEventObjectCreationFailed)?; | ||||
|         let payment_attempt = get_payment_attempt_from_object_reference_id( | ||||
|             state.clone(), | ||||
|             &state, | ||||
|             webhook_details.object_reference_id, | ||||
|             &merchant_account, | ||||
|         ) | ||||
| @ -359,6 +367,76 @@ pub async fn disputes_incoming_webhook_flow<W: api::OutgoingWebhookType>( | ||||
|     } | ||||
| } | ||||
|  | ||||
| async fn bank_transfer_webhook_flow<W: api::OutgoingWebhookType>( | ||||
|     state: AppState, | ||||
|     merchant_account: storage::MerchantAccount, | ||||
|     webhook_details: api::IncomingWebhookDetails, | ||||
|     source_verified: bool, | ||||
| ) -> CustomResult<(), errors::WebhooksFlowError> { | ||||
|     let response = if source_verified { | ||||
|         let payment_attempt = get_payment_attempt_from_object_reference_id( | ||||
|             &state, | ||||
|             webhook_details.object_reference_id, | ||||
|             &merchant_account, | ||||
|         ) | ||||
|         .await?; | ||||
|         let payment_id = payment_attempt.payment_id; | ||||
|         let request = api::PaymentsRequest { | ||||
|             payment_id: Some(api_models::payments::PaymentIdType::PaymentIntentId( | ||||
|                 payment_id, | ||||
|             )), | ||||
|             payment_token: payment_attempt.payment_token, | ||||
|             ..Default::default() | ||||
|         }; | ||||
|         payments::payments_core::<api::Authorize, api::PaymentsResponse, _, _, _>( | ||||
|             &state, | ||||
|             merchant_account.to_owned(), | ||||
|             payments::PaymentConfirm, | ||||
|             request, | ||||
|             services::api::AuthFlow::Merchant, | ||||
|             payments::CallConnectorAction::Trigger, | ||||
|         ) | ||||
|         .await | ||||
|         .change_context(errors::WebhooksFlowError::PaymentsCoreFailed) | ||||
|     } else { | ||||
|         Err(report!( | ||||
|             errors::WebhooksFlowError::WebhookSourceVerificationFailed | ||||
|         )) | ||||
|     }; | ||||
|  | ||||
|     match response? { | ||||
|         services::ApplicationResponse::Json(payments_response) => { | ||||
|             let payment_id = payments_response | ||||
|                 .payment_id | ||||
|                 .clone() | ||||
|                 .get_required_value("payment_id") | ||||
|                 .change_context(errors::WebhooksFlowError::PaymentsCoreFailed)?; | ||||
|  | ||||
|             let event_type: enums::EventType = payments_response | ||||
|                 .status | ||||
|                 .foreign_try_into() | ||||
|                 .into_report() | ||||
|                 .change_context(errors::WebhooksFlowError::PaymentsCoreFailed)?; | ||||
|  | ||||
|             create_event_and_trigger_outgoing_webhook::<W>( | ||||
|                 state, | ||||
|                 merchant_account, | ||||
|                 event_type, | ||||
|                 enums::EventClass::Payments, | ||||
|                 None, | ||||
|                 payment_id, | ||||
|                 enums::EventObjectType::PaymentDetails, | ||||
|                 api::OutgoingWebhookContent::PaymentDetails(payments_response), | ||||
|             ) | ||||
|             .await?; | ||||
|         } | ||||
|  | ||||
|         _ => Err(errors::WebhooksFlowError::PaymentsCoreFailed).into_report()?, | ||||
|     } | ||||
|  | ||||
|     Ok(()) | ||||
| } | ||||
|  | ||||
| #[allow(clippy::too_many_arguments)] | ||||
| #[instrument(skip_all)] | ||||
| pub async fn create_event_and_trigger_outgoing_webhook<W: api::OutgoingWebhookType>( | ||||
| @ -601,6 +679,16 @@ pub async fn webhooks_core<W: api::OutgoingWebhookType>( | ||||
|             .change_context(errors::ApiErrorResponse::InternalServerError) | ||||
|             .attach_printable("Incoming webhook flow for disputes failed")?, | ||||
|  | ||||
|             api::WebhookFlow::BankTransfer => bank_transfer_webhook_flow::<W>( | ||||
|                 state.clone(), | ||||
|                 merchant_account, | ||||
|                 webhook_details, | ||||
|                 source_verified, | ||||
|             ) | ||||
|             .await | ||||
|             .change_context(errors::ApiErrorResponse::InternalServerError) | ||||
|             .attach_printable("Incoming bank-transfer webhook flow failed")?, | ||||
|  | ||||
|             api::WebhookFlow::ReturnResponse => {} | ||||
|  | ||||
|             _ => Err(errors::ApiErrorResponse::InternalServerError) | ||||
|  | ||||
		Reference in New Issue
	
	Block a user