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:
ItsMeShashank
2022-12-21 14:36:37 +05:30
committed by GitHub
parent 60d1ad52b1
commit 47741b47fa
5 changed files with 62 additions and 18 deletions

View File

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

View File

@ -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,
},

View File

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

View File

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

View File

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