mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-27 19:46:48 +08:00
feat(router): use payment confirm for confirmed payments in payments create and update (#165)
Co-authored-by: Arun Raj M <jarnura47@gmail.com>
This commit is contained in:
@ -482,6 +482,7 @@ pub struct CustomerDetails {
|
||||
pub fn if_not_create_change_operation<'a, Op, F>(
|
||||
is_update: bool,
|
||||
status: storage_enums::IntentStatus,
|
||||
confirm: Option<bool>,
|
||||
current: &'a Op,
|
||||
) -> BoxedOperation<F, api::PaymentsRequest>
|
||||
where
|
||||
@ -489,17 +490,21 @@ where
|
||||
Op: Operation<F, api::PaymentsRequest> + Send + Sync,
|
||||
&'a Op: Operation<F, api::PaymentsRequest>,
|
||||
{
|
||||
match status {
|
||||
storage_enums::IntentStatus::RequiresConfirmation
|
||||
| storage_enums::IntentStatus::RequiresCustomerAction
|
||||
| storage_enums::IntentStatus::RequiresPaymentMethod => {
|
||||
if is_update {
|
||||
Box::new(&PaymentUpdate)
|
||||
} else {
|
||||
Box::new(current)
|
||||
if confirm.unwrap_or(false) {
|
||||
Box::new(PaymentConfirm)
|
||||
} else {
|
||||
match status {
|
||||
storage_enums::IntentStatus::RequiresConfirmation
|
||||
| storage_enums::IntentStatus::RequiresCustomerAction
|
||||
| storage_enums::IntentStatus::RequiresPaymentMethod => {
|
||||
if is_update {
|
||||
Box::new(&PaymentUpdate)
|
||||
} else {
|
||||
Box::new(current)
|
||||
}
|
||||
}
|
||||
_ => Box::new(&PaymentStatus),
|
||||
}
|
||||
_ => Box::new(&PaymentStatus),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -257,7 +257,7 @@ impl<F: Clone> UpdateTracker<F, PaymentData<F>, api::PaymentsRequest> for Paymen
|
||||
db: &dyn StorageInterface,
|
||||
_payment_id: &api::PaymentIdType,
|
||||
mut payment_data: PaymentData<F>,
|
||||
_customer: Option<storage::Customer>,
|
||||
customer: Option<storage::Customer>,
|
||||
storage_scheme: enums::MerchantStorageScheme,
|
||||
) -> RouterResult<(BoxedOperation<'b, F, api::PaymentsRequest>, PaymentData<F>)>
|
||||
where
|
||||
@ -285,8 +285,11 @@ impl<F: Clone> UpdateTracker<F, PaymentData<F>, api::PaymentsRequest> for Paymen
|
||||
.update_payment_attempt(
|
||||
payment_data.payment_attempt,
|
||||
storage::PaymentAttemptUpdate::ConfirmUpdate {
|
||||
amount: payment_data.amount.into(),
|
||||
currency: payment_data.currency,
|
||||
status: attempt_status,
|
||||
payment_method,
|
||||
authentication_type: None,
|
||||
browser_info,
|
||||
connector,
|
||||
payment_token,
|
||||
@ -303,11 +306,16 @@ impl<F: Clone> UpdateTracker<F, PaymentData<F>, api::PaymentsRequest> for Paymen
|
||||
payment_data.payment_intent.billing_address_id.clone(),
|
||||
);
|
||||
|
||||
let customer_id = customer.map(|c| c.customer_id);
|
||||
|
||||
payment_data.payment_intent = db
|
||||
.update_payment_intent(
|
||||
payment_data.payment_intent,
|
||||
storage::PaymentIntentUpdate::MerchantStatusUpdate {
|
||||
storage::PaymentIntentUpdate::Update {
|
||||
amount: payment_data.amount.into(),
|
||||
currency: payment_data.currency,
|
||||
status: intent_status,
|
||||
customer_id,
|
||||
shipping_address_id: shipping_address,
|
||||
billing_address_id: billing_address,
|
||||
},
|
||||
|
||||
@ -185,6 +185,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
|
||||
let operation = payments::if_not_create_change_operation::<_, F>(
|
||||
is_update,
|
||||
payment_intent.status,
|
||||
request.confirm,
|
||||
self,
|
||||
);
|
||||
|
||||
@ -280,10 +281,10 @@ impl<F: Clone + Send> Domain<F, api::PaymentsRequest> for PaymentCreate {
|
||||
#[instrument(skip_all)]
|
||||
async fn add_task_to_process_tracker<'a>(
|
||||
&'a self,
|
||||
state: &'a AppState,
|
||||
payment_attempt: &storage::PaymentAttempt,
|
||||
_state: &'a AppState,
|
||||
_payment_attempt: &storage::PaymentAttempt,
|
||||
) -> CustomResult<(), errors::ApiErrorResponse> {
|
||||
helpers::add_domain_task_to_pt(self, state, payment_attempt).await
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_connector<'a>(
|
||||
@ -388,6 +389,13 @@ impl<F: Send + Clone> ValidateRequest<F, api::PaymentsRequest> for PaymentCreate
|
||||
None => None,
|
||||
};
|
||||
|
||||
if let Some(true) = request.confirm {
|
||||
helpers::validate_pm_or_token_given(
|
||||
&request.payment_token,
|
||||
&request.payment_method_data,
|
||||
)?;
|
||||
}
|
||||
|
||||
let request_merchant_id = request.merchant_id.as_deref();
|
||||
helpers::validate_merchant_id(&merchant_account.merchant_id, request_merchant_id)
|
||||
.change_context(errors::ApiErrorResponse::MerchantAccountNotFound)?;
|
||||
|
||||
@ -126,6 +126,13 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
|
||||
.attach_printable("Database error when finding connector response")
|
||||
})?;
|
||||
|
||||
let next_operation: BoxedOperation<'a, F, api::PaymentsRequest> =
|
||||
if request.confirm.unwrap_or(false) {
|
||||
Box::new(operations::PaymentConfirm)
|
||||
} else {
|
||||
Box::new(self)
|
||||
};
|
||||
|
||||
match payment_intent.status {
|
||||
enums::IntentStatus::Succeeded | enums::IntentStatus::Failed => {
|
||||
Err(report!(errors::ApiErrorResponse::PreconditionFailed {
|
||||
@ -135,7 +142,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
|
||||
}))
|
||||
}
|
||||
_ => Ok((
|
||||
Box::new(self),
|
||||
next_operation,
|
||||
PaymentData {
|
||||
flow: PhantomData,
|
||||
payment_intent,
|
||||
@ -227,10 +234,10 @@ impl<F: Clone + Send> Domain<F, api::PaymentsRequest> for PaymentUpdate {
|
||||
#[instrument(skip_all)]
|
||||
async fn add_task_to_process_tracker<'a>(
|
||||
&'a self,
|
||||
state: &'a AppState,
|
||||
payment_attempt: &storage::PaymentAttempt,
|
||||
_state: &'a AppState,
|
||||
_payment_attempt: &storage::PaymentAttempt,
|
||||
) -> CustomResult<(), errors::ApiErrorResponse> {
|
||||
helpers::add_domain_task_to_pt(self, state, payment_attempt).await
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_connector<'a>(
|
||||
@ -352,6 +359,13 @@ impl<F: Send + Clone> ValidateRequest<F, api::PaymentsRequest> for PaymentUpdate
|
||||
None => None,
|
||||
};
|
||||
|
||||
if let Some(true) = request.confirm {
|
||||
helpers::validate_pm_or_token_given(
|
||||
&request.payment_token,
|
||||
&request.payment_method_data,
|
||||
)?;
|
||||
}
|
||||
|
||||
let request_merchant_id = request.merchant_id.as_deref();
|
||||
helpers::validate_merchant_id(&merchant_account.merchant_id, request_merchant_id)
|
||||
.change_context(errors::ApiErrorResponse::InvalidDataFormat {
|
||||
|
||||
@ -95,7 +95,10 @@ pub enum PaymentAttemptUpdate {
|
||||
authentication_type: storage_enums::AuthenticationType,
|
||||
},
|
||||
ConfirmUpdate {
|
||||
amount: i64,
|
||||
currency: storage_enums::Currency,
|
||||
status: storage_enums::AttemptStatus,
|
||||
authentication_type: Option<storage_enums::AuthenticationType>,
|
||||
payment_method: Option<storage_enums::PaymentMethodType>,
|
||||
browser_info: Option<serde_json::Value>,
|
||||
connector: Option<String>,
|
||||
@ -199,12 +202,18 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
|
||||
..Default::default()
|
||||
},
|
||||
PaymentAttemptUpdate::ConfirmUpdate {
|
||||
amount,
|
||||
currency,
|
||||
authentication_type,
|
||||
status,
|
||||
payment_method,
|
||||
browser_info,
|
||||
connector,
|
||||
payment_token,
|
||||
} => Self {
|
||||
amount: Some(amount),
|
||||
currency: Some(currency),
|
||||
authentication_type,
|
||||
status: Some(status),
|
||||
payment_method,
|
||||
modified_at: Some(common_utils::date_time::now()),
|
||||
|
||||
Reference in New Issue
Block a user