feat: Session flow for Apple Pay trustpay (#1155)

This commit is contained in:
Sangamesh Kulkarni
2023-06-07 20:27:19 +05:30
committed by GitHub
parent d21fcc7bfc
commit a6e91a828b
23 changed files with 541 additions and 115 deletions

View File

@ -8,10 +8,10 @@ pub mod transformers;
use std::{fmt::Debug, marker::PhantomData, ops::Deref, time::Instant};
use actix_web::ResponseError;
use api_models::payments::Metadata;
use common_utils::pii::Email;
use error_stack::{IntoReport, ResultExt};
use futures::future::join_all;
use masking::Secret;
use router_env::{instrument, tracing};
use storage_models::ephemeral_key;
@ -29,11 +29,10 @@ use self::{
use crate::{
configs::settings::PaymentMethodTypeTokenFilter,
core::{
errors::{self, CustomResult, RouterResponse, RouterResult},
errors::{self, CustomResult, RouterResponse, RouterResult, StorageErrorExt},
payment_methods::vault,
},
db::StorageInterface,
logger,
routes::{metrics, AppState},
scheduler::utils as pt_utils,
services::{self, api::Authenticate},
@ -177,7 +176,7 @@ where
}
api::ConnectorCallType::Multiple(connectors) => {
call_multiple_connectors_service(
get_session_tokens_and_persist_if_required(
state,
&merchant_account,
connectors,
@ -564,7 +563,7 @@ where
router_data_res
}
pub async fn call_multiple_connectors_service<F, Op, Req>(
pub async fn get_session_tokens_and_persist_if_required<F, Op, Req>(
state: &AppState,
merchant_account: &domain::MerchantAccount,
connectors: Vec<api::SessionConnectorData>,
@ -596,36 +595,52 @@ where
.construct_router_data(state, connector_id, merchant_account, customer)
.await?;
let res = router_data.decide_flows(
state,
&session_connector_data.connector,
customer,
CallConnectorAction::Trigger,
merchant_account,
);
let res = router_data
.decide_flows(
state,
&session_connector_data.connector,
customer,
CallConnectorAction::Trigger,
merchant_account,
)
.await;
join_handlers.push(res);
let router_res = match res {
Ok(router_result) => Ok(router_result),
Err(error) => {
let err = error.current_context();
Err(errors::ApiErrorResponse::ExternalConnectorError {
code: err.error_code(),
message: err.error_message(),
connector: connector_id.to_string(),
status_code: err.status_code().into(),
reason: None,
})
}
}?;
join_handlers.push(router_res.response.clone());
if connector_id == "trustpay" && payment_data.delayed_session_token.unwrap_or(false) {
//Fix: Add post update tracker for payment_session operation
let response_id = router_res.response.ok().and_then(|res| match res {
types::PaymentsResponseData::SessionResponse { response_id, .. } => response_id,
_ => None,
});
update_connector_txn_id_in_payment_attempt(
state,
merchant_account,
&payment_data,
response_id,
)
.await?;
};
}
let result = join_all(join_handlers).await;
for (connector_res, session_connector) in result.into_iter().zip(connectors) {
let connector_name = session_connector.connector.connector_name.to_string();
match connector_res {
Ok(connector_response) => {
if let Ok(types::PaymentsResponseData::SessionResponse { session_token }) =
connector_response.response
{
payment_data.sessions_token.push(session_token);
}
}
Err(connector_error) => {
logger::error!(
"sessions_connector_error {} {:?}",
connector_name,
connector_error
);
}
for connector_res in join_handlers.into_iter().flatten() {
if let types::PaymentsResponseData::SessionResponse { session_token, .. } = connector_res {
payment_data.sessions_token.push(session_token);
}
}
@ -637,6 +652,31 @@ where
Ok(payment_data)
}
pub async fn update_connector_txn_id_in_payment_attempt<F>(
state: &AppState,
merchant_account: &domain::MerchantAccount,
payment_data: &PaymentData<F>,
response_id: Option<String>,
) -> RouterResult<()>
where
F: Clone,
{
let payment_attempt_update = storage::PaymentAttemptUpdate::SessionUpdate {
connector_transaction_id: response_id,
};
let db = &*state.store;
db.update_payment_attempt_with_attempt_id(
payment_data.payment_attempt.to_owned(),
payment_attempt_update,
merchant_account.storage_scheme,
)
.await
.to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;
Ok(())
}
pub async fn call_create_connector_customer_if_required<F, Req>(
state: &AppState,
customer: &Option<domain::Customer>,
@ -975,6 +1015,7 @@ where
pub connector_customer_id: Option<String>,
pub ephemeral_key: Option<ephemeral_key::EphemeralKey>,
pub redirect_response: Option<api_models::payments::RedirectResponse>,
pub delayed_session_token: Option<bool>,
}
#[derive(Debug, Default)]
@ -1085,7 +1126,7 @@ pub async fn list_payments(
) -> RouterResponse<api::PaymentListResponse> {
use futures::stream::StreamExt;
use crate::{core::errors::utils::StorageErrorExt, types::transformers::ForeignFrom};
use crate::types::transformers::ForeignFrom;
helpers::validate_payment_list_request(&constraints)?;
let merchant_id = &merchant.merchant_id;