pub mod types; use actix_web::{web, HttpRequest, HttpResponse}; use api_models::payments as payment_types; use error_stack::report; use router_env::{instrument, tracing, Flow}; use crate::{ compatibility::{stripe::errors, wrap}, core::payments, routes, services::{api, authentication as auth}, types::api::{self as api_types}, }; #[instrument(skip_all, fields(flow = ?Flow::PaymentsCreate))] pub async fn payment_intents_create( state: web::Data, qs_config: web::Data, req: HttpRequest, form_payload: web::Bytes, ) -> HttpResponse { let payload: types::StripePaymentIntentRequest = match qs_config .deserialize_bytes(&form_payload) .map_err(|err| report!(errors::StripeErrorCode::from(err))) { Ok(p) => p, Err(err) => return api::log_and_return_error_response(err), }; let create_payment_req: payment_types::PaymentsRequest = match payload.try_into() { Ok(req) => req, Err(err) => return api::log_and_return_error_response(err), }; let flow = Flow::PaymentsCreate; wrap::compatibility_api_wrap::< _, _, _, _, _, _, types::StripePaymentIntentResponse, errors::StripeErrorCode, >( flow, state.get_ref(), &req, create_payment_req, |state, auth, req| { payments::payments_core::( state, auth.merchant_account, auth.key_store, payments::PaymentCreate, req, api::AuthFlow::Merchant, payments::CallConnectorAction::Trigger, ) }, &auth::ApiKeyAuth, ) .await } #[instrument(skip_all, fields(flow = ?Flow::PaymentsRetrieve))] pub async fn payment_intents_retrieve( state: web::Data, req: HttpRequest, path: web::Path, query_payload: web::Query, ) -> HttpResponse { let payload = payment_types::PaymentsRetrieveRequest { resource_id: api_types::PaymentIdType::PaymentIntentId(path.to_string()), merchant_id: None, force_sync: true, connector: None, param: None, merchant_connector_details: None, client_secret: query_payload.client_secret.clone(), }; let (auth_type, auth_flow) = match auth::check_client_secret_and_get_auth(req.headers(), &payload) { Ok(auth) => auth, Err(err) => return api::log_and_return_error_response(report!(err)), }; let flow = Flow::PaymentsRetrieve; wrap::compatibility_api_wrap::< _, _, _, _, _, _, types::StripePaymentIntentResponse, errors::StripeErrorCode, >( flow, state.get_ref(), &req, payload, |state, auth, payload| { payments::payments_core::( state, auth.merchant_account, auth.key_store, payments::PaymentStatus, payload, auth_flow, payments::CallConnectorAction::Trigger, ) }, &*auth_type, ) .await } #[instrument(skip_all, fields(flow = ?Flow::PaymentsRetrieve))] pub async fn payment_intents_retrieve_with_gateway_creds( state: web::Data, qs_config: web::Data, req: HttpRequest, form_payload: web::Bytes, ) -> HttpResponse { let json_payload: payment_types::PaymentRetrieveBodyWithCredentials = match qs_config .deserialize_bytes(&form_payload) .map_err(|err| report!(errors::StripeErrorCode::from(err))) { Ok(p) => p, Err(err) => return api::log_and_return_error_response(err), }; let payload = payment_types::PaymentsRetrieveRequest { resource_id: payment_types::PaymentIdType::PaymentIntentId( json_payload.payment_id.to_string(), ), merchant_id: json_payload.merchant_id.clone(), force_sync: json_payload.force_sync.unwrap_or(false), merchant_connector_details: json_payload.merchant_connector_details.clone(), ..Default::default() }; let (auth_type, _auth_flow) = match auth::get_auth_type_and_flow(req.headers()) { Ok(auth) => auth, Err(err) => return api::log_and_return_error_response(report!(err)), }; let flow = Flow::PaymentsRetrieve; wrap::compatibility_api_wrap::< _, _, _, _, _, _, types::StripePaymentIntentResponse, errors::StripeErrorCode, >( flow, state.get_ref(), &req, payload, |state, auth, req| { payments::payments_core::( state, auth.merchant_account, auth.key_store, payments::PaymentStatus, req, api::AuthFlow::Merchant, payments::CallConnectorAction::Trigger, ) }, &*auth_type, ) .await } #[instrument(skip_all, fields(flow = ?Flow::PaymentsUpdate))] pub async fn payment_intents_update( state: web::Data, qs_config: web::Data, req: HttpRequest, form_payload: web::Bytes, path: web::Path, ) -> HttpResponse { let payment_id = path.into_inner(); let stripe_payload: types::StripePaymentIntentRequest = match qs_config .deserialize_bytes(&form_payload) { Ok(p) => p, Err(err) => { return api::log_and_return_error_response(report!(errors::StripeErrorCode::from(err))) } }; let mut payload: payment_types::PaymentsRequest = match stripe_payload.try_into() { Ok(req) => req, Err(err) => return api::log_and_return_error_response(err), }; payload.payment_id = Some(api_types::PaymentIdType::PaymentIntentId(payment_id)); let (auth_type, auth_flow) = match auth::get_auth_type_and_flow(req.headers()) { Ok(auth) => auth, Err(err) => return api::log_and_return_error_response(report!(err)), }; let flow = Flow::PaymentsUpdate; wrap::compatibility_api_wrap::< _, _, _, _, _, _, types::StripePaymentIntentResponse, errors::StripeErrorCode, >( flow, state.get_ref(), &req, payload, |state, auth, req| { payments::payments_core::( state, auth.merchant_account, auth.key_store, payments::PaymentUpdate, req, auth_flow, payments::CallConnectorAction::Trigger, ) }, &*auth_type, ) .await } #[instrument(skip_all, fields(flow = ?Flow::PaymentsConfirm))] pub async fn payment_intents_confirm( state: web::Data, qs_config: web::Data, req: HttpRequest, form_payload: web::Bytes, path: web::Path, ) -> HttpResponse { let payment_id = path.into_inner(); let stripe_payload: types::StripePaymentIntentRequest = match qs_config .deserialize_bytes(&form_payload) { Ok(p) => p, Err(err) => { return api::log_and_return_error_response(report!(errors::StripeErrorCode::from(err))) } }; let mut payload: payment_types::PaymentsRequest = match stripe_payload.try_into() { Ok(req) => req, Err(err) => return api::log_and_return_error_response(err), }; payload.payment_id = Some(api_types::PaymentIdType::PaymentIntentId(payment_id)); payload.confirm = Some(true); let (auth_type, auth_flow) = match auth::check_client_secret_and_get_auth(req.headers(), &payload) { Ok(auth) => auth, Err(err) => return api::log_and_return_error_response(err), }; let flow = Flow::PaymentsConfirm; wrap::compatibility_api_wrap::< _, _, _, _, _, _, types::StripePaymentIntentResponse, errors::StripeErrorCode, >( flow, state.get_ref(), &req, payload, |state, auth, req| { payments::payments_core::( state, auth.merchant_account, auth.key_store, payments::PaymentConfirm, req, auth_flow, payments::CallConnectorAction::Trigger, ) }, &*auth_type, ) .await } #[instrument(skip_all, fields(flow = ?Flow::PaymentsCapture))] pub async fn payment_intents_capture( state: web::Data, qs_config: web::Data, req: HttpRequest, form_payload: web::Bytes, path: web::Path, ) -> HttpResponse { let stripe_payload: payment_types::PaymentsCaptureRequest = match qs_config .deserialize_bytes(&form_payload) { Ok(p) => p, Err(err) => { return api::log_and_return_error_response(report!(errors::StripeErrorCode::from(err))) } }; let capture_payload = payment_types::PaymentsCaptureRequest { payment_id: Some(path.into_inner()), ..stripe_payload }; let flow = Flow::PaymentsCapture; wrap::compatibility_api_wrap::< _, _, _, _, _, _, types::StripePaymentIntentResponse, errors::StripeErrorCode, >( flow, state.get_ref(), &req, capture_payload, |state, auth, payload| { payments::payments_core::( state, auth.merchant_account, auth.key_store, payments::PaymentCapture, payload, api::AuthFlow::Merchant, payments::CallConnectorAction::Trigger, ) }, &auth::ApiKeyAuth, ) .await } #[instrument(skip_all, fields(flow = ?Flow::PaymentsCancel))] pub async fn payment_intents_cancel( state: web::Data, qs_config: web::Data, req: HttpRequest, form_payload: web::Bytes, path: web::Path, ) -> HttpResponse { let payment_id = path.into_inner(); let stripe_payload: types::StripePaymentCancelRequest = match qs_config .deserialize_bytes(&form_payload) { Ok(p) => p, Err(err) => { return api::log_and_return_error_response(report!(errors::StripeErrorCode::from(err))) } }; let mut payload: payment_types::PaymentsCancelRequest = stripe_payload.into(); payload.payment_id = payment_id; let (auth_type, auth_flow) = match auth::get_auth_type_and_flow(req.headers()) { Ok(auth) => auth, Err(err) => return api::log_and_return_error_response(report!(err)), }; let flow = Flow::PaymentsCancel; wrap::compatibility_api_wrap::< _, _, _, _, _, _, types::StripePaymentIntentResponse, errors::StripeErrorCode, >( flow, state.get_ref(), &req, payload, |state, auth, req| { payments::payments_core::( state, auth.merchant_account, auth.key_store, payments::PaymentCancel, req, auth_flow, payments::CallConnectorAction::Trigger, ) }, &*auth_type, ) .await } #[instrument(skip_all, fields(flow = ?Flow::PaymentsList))] #[cfg(feature = "olap")] pub async fn payment_intent_list( state: web::Data, req: HttpRequest, payload: web::Query, ) -> HttpResponse { let payload = match payment_types::PaymentListConstraints::try_from(payload.into_inner()) { Ok(p) => p, Err(err) => return api::log_and_return_error_response(err), }; let flow = Flow::PaymentsList; wrap::compatibility_api_wrap::< _, _, _, _, _, _, types::StripePaymentIntentListResponse, errors::StripeErrorCode, >( flow, state.get_ref(), &req, payload, |state, auth, req| payments::list_payments(&*state.store, auth.merchant_account, req), &auth::ApiKeyAuth, ) .await }