feat: ACH transfers (#905)

This commit is contained in:
Sangamesh Kulkarni
2023-05-19 15:14:29 +05:30
committed by GitHub
parent 39405bb478
commit 23bca66b81
39 changed files with 1247 additions and 66 deletions

View File

@ -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)