fix(router): allow inferring payment method from payment token (#422)

This commit is contained in:
ItsMeShashank
2023-01-19 15:53:16 +05:30
committed by GitHub
parent 749c83a8e6
commit 5924e93413

View File

@ -673,17 +673,21 @@ pub async fn make_pm_data<'a, F: Clone, R>(
state: &'a AppState, state: &'a AppState,
payment_data: &mut PaymentData<F>, payment_data: &mut PaymentData<F>,
) -> RouterResult<(BoxedOperation<'a, F, R>, Option<api::PaymentMethod>)> { ) -> RouterResult<(BoxedOperation<'a, F, R>, Option<api::PaymentMethod>)> {
let payment_method_type = payment_data.payment_attempt.payment_method;
let request = &payment_data.payment_method_data; let request = &payment_data.payment_method_data;
let token = payment_data.token.clone(); let token = payment_data.token.clone();
let card_cvc = payment_data.card_cvc.clone(); let card_cvc = payment_data.card_cvc.clone();
// TODO: Handle case where payment method and token both are present in request properly.
let payment_method = match (request, token) { let payment_method = match (request, token) {
(_, Some(token)) => Ok::<_, error_stack::Report<errors::ApiErrorResponse>>( (_, Some(token)) => {
if payment_method_type == Some(storage_enums::PaymentMethodType::Card) { let (pm, supplementary_data) = vault::Vault::get_payment_method_data_from_locker(
// TODO: Handle token expiry state, &token,
let (pm, supplementary_data) = )
vault::Vault::get_payment_method_data_from_locker(state, &token).await?; .await
.attach_printable(
"Payment method for given token not found or there was a problem fetching it",
)?;
utils::when( utils::when(
supplementary_data supplementary_data
.customer_id .customer_id
@ -692,11 +696,14 @@ pub async fn make_pm_data<'a, F: Clone, R>(
Err(errors::ApiErrorResponse::PreconditionFailed { message: "customer associated with payment method and customer passed in payment are not same".into() }) Err(errors::ApiErrorResponse::PreconditionFailed { message: "customer associated with payment method and customer passed in payment are not same".into() })
}, },
)?; )?;
payment_data.token = Some(token.to_string());
match (pm.clone(), card_cvc) { Ok::<_, error_stack::Report<errors::ApiErrorResponse>>(match pm.clone() {
(Some(api::PaymentMethod::Card(card)), Some(card_cvc)) => { Some(api::PaymentMethod::Card(card)) => {
payment_data.payment_attempt.payment_method =
Some(storage_enums::PaymentMethodType::Card);
if let Some(cvc) = card_cvc {
let mut updated_card = card; let mut updated_card = card;
updated_card.card_cvc = card_cvc; updated_card.card_cvc = cvc;
let updated_pm = api::PaymentMethod::Card(updated_card); let updated_pm = api::PaymentMethod::Card(updated_card);
vault::Vault::store_payment_method_data_in_locker( vault::Vault::store_payment_method_data_in_locker(
state, state,
@ -706,24 +713,15 @@ pub async fn make_pm_data<'a, F: Clone, R>(
) )
.await?; .await?;
Some(updated_pm) Some(updated_pm)
} else {
pm
} }
(_, _) => pm,
} }
} else if payment_method_type == Some(storage_enums::PaymentMethodType::Wallet) {
let (pm, supplementary_data) =
vault::Vault::get_payment_method_data_from_locker(state, &token).await?;
utils::when(
supplementary_data
.customer_id
.ne(&payment_data.payment_intent.customer_id),
|| {
Err(errors::ApiErrorResponse::PreconditionFailed { message: "customer associated with payment method and customer passed in payment are not same".into() })
},
)?;
payment_data.token = Some(token.to_string());
match pm.clone() {
Some(api::PaymentMethod::Wallet(wallet_data)) => { Some(api::PaymentMethod::Wallet(wallet_data)) => {
payment_data.payment_attempt.payment_method =
Some(storage_enums::PaymentMethodType::Wallet);
// TODO: Remove redundant update from wallets.
if wallet_data.token.is_some() { if wallet_data.token.is_some() {
let updated_pm = api::PaymentMethod::Wallet(wallet_data); let updated_pm = api::PaymentMethod::Wallet(wallet_data);
vault::Vault::store_payment_method_data_in_locker( vault::Vault::store_payment_method_data_in_locker(
@ -738,18 +736,16 @@ pub async fn make_pm_data<'a, F: Clone, R>(
pm pm
} }
} }
_ => pm,
} Some(_) => Err(errors::ApiErrorResponse::InternalServerError)
} else { .into_report()
utils::when(payment_method_type.is_none(), || { .attach_printable(
Err(errors::ApiErrorResponse::MissingRequiredField { "Payment method received from locker is unsupported by locker",
field_name: "payment_method_type".to_owned(), )?,
None => None,
}) })
})?; }
// [#195]: Implement token flow for other payment methods
None
},
),
(pm_opt @ Some(pm @ api::PaymentMethod::Card(_)), _) => { (pm_opt @ Some(pm @ api::PaymentMethod::Card(_)), _) => {
let token = vault::Vault::store_payment_method_data_in_locker( let token = vault::Vault::store_payment_method_data_in_locker(
state, state,
@ -840,7 +836,9 @@ pub(crate) fn validate_payment_method_fields_present(
)?; )?;
utils::when( utils::when(
req.payment_method.is_some() && req.payment_method_data.is_none(), req.payment_method.is_some()
&& req.payment_method_data.is_none()
&& req.payment_token.is_none(),
|| { || {
Err(errors::ApiErrorResponse::MissingRequiredField { Err(errors::ApiErrorResponse::MissingRequiredField {
field_name: "payment_method_data".to_string(), field_name: "payment_method_data".to_string(),