feat(session): ability to request session token for specific wallets (#280)

Co-authored-by: Arun Raj M <jarnura47@gmail.com>
This commit is contained in:
Narayan Bhat
2023-01-11 12:47:52 +05:30
committed by GitHub
parent 9ad56703c4
commit 5809408cf9
18 changed files with 90 additions and 96 deletions

View File

@ -509,6 +509,15 @@ pub enum Connector {
Worldpay,
}
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
#[serde(rename_all = "snake_case")]
pub enum SupportedWallets {
Paypal,
ApplePay,
Klarna,
Gpay,
}
impl From<AttemptStatus> for IntentStatus {
fn from(s: AttemptStatus) -> Self {
match s {

View File

@ -751,15 +751,6 @@ pub struct PaymentsRetrieveRequest {
pub connector: Option<String>,
}
#[derive(Debug, serde::Deserialize, Clone)]
#[serde(rename_all = "snake_case")]
pub enum SupportedWallets {
Paypal,
ApplePay,
Klarna,
Gpay,
}
#[derive(Debug, Default, Eq, PartialEq, serde::Deserialize, serde::Serialize, Clone)]
pub struct OrderDetails {
pub product_name: String,
@ -777,6 +768,7 @@ pub struct Metadata {
pub struct PaymentsSessionRequest {
pub payment_id: String,
pub client_secret: String,
pub wallets: Vec<api_enums::SupportedWallets>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]

View File

@ -47,14 +47,12 @@ pub async fn payment_intents_create(
&req,
create_payment_req,
|state, merchant_account, req| {
let connector = req.connector;
payments::payments_core::<api_types::Authorize, api_types::PaymentsResponse, _, _, _>(
state,
merchant_account,
payments::PaymentCreate,
req,
api::AuthFlow::Merchant,
connector,
payments::CallConnectorAction::Trigger,
)
},
@ -102,7 +100,6 @@ pub async fn payment_intents_retrieve(
payments::PaymentStatus,
payload,
auth_flow,
None,
payments::CallConnectorAction::Trigger,
)
},
@ -155,14 +152,12 @@ pub async fn payment_intents_update(
&req,
payload,
|state, merchant_account, req| {
let connector = req.connector;
payments::payments_core::<api_types::Authorize, api_types::PaymentsResponse, _, _, _>(
state,
merchant_account,
payments::PaymentUpdate,
req,
auth_flow,
connector,
payments::CallConnectorAction::Trigger,
)
},
@ -217,14 +212,12 @@ pub async fn payment_intents_confirm(
&req,
payload,
|state, merchant_account, req| {
let connector = req.connector;
payments::payments_core::<api_types::Authorize, api_types::PaymentsResponse, _, _, _>(
state,
merchant_account,
payments::PaymentConfirm,
req,
auth_flow,
connector,
payments::CallConnectorAction::Trigger,
)
},
@ -274,7 +267,6 @@ pub async fn payment_intents_capture(
payments::PaymentCapture,
payload,
api::AuthFlow::Merchant,
None,
payments::CallConnectorAction::Trigger,
)
},
@ -329,7 +321,6 @@ pub async fn payment_intents_cancel(
payments::PaymentCancel,
req,
auth_flow,
None,
payments::CallConnectorAction::Trigger,
)
},

View File

@ -44,14 +44,12 @@ pub async fn setup_intents_create(
&req,
create_payment_req,
|state, merchant_account, req| {
let connector = req.connector;
payments::payments_core::<api_types::Verify, api_types::PaymentsResponse, _, _, _>(
state,
merchant_account,
payments::PaymentCreate,
req,
api::AuthFlow::Merchant,
connector,
payments::CallConnectorAction::Trigger,
)
},
@ -99,7 +97,6 @@ pub async fn setup_intents_retrieve(
payments::PaymentStatus,
payload,
auth_flow,
None,
payments::CallConnectorAction::Trigger,
)
},
@ -149,14 +146,12 @@ pub async fn setup_intents_update(
&req,
payload,
|state, merchant_account, req| {
let connector = req.connector;
payments::payments_core::<api_types::Verify, api_types::PaymentsResponse, _, _, _>(
state,
merchant_account,
payments::PaymentUpdate,
req,
auth_flow,
connector,
payments::CallConnectorAction::Trigger,
)
},
@ -207,14 +202,12 @@ pub async fn setup_intents_confirm(
&req,
payload,
|state, merchant_account, req| {
let connector = req.connector;
payments::payments_core::<api_types::Verify, api_types::PaymentsResponse, _, _, _>(
state,
merchant_account,
payments::PaymentConfirm,
req,
auth_flow,
connector,
payments::CallConnectorAction::Trigger,
)
},

View File

@ -28,8 +28,7 @@ use crate::{
scheduler::utils as pt_utils,
services,
types::{
self,
api::{self, enums as api_enums},
self, api,
storage::{self, enums as storage_enums},
transformers::ForeignInto,
},
@ -42,7 +41,6 @@ pub async fn payments_operation_core<F, Req, Op, FData>(
merchant_account: storage::MerchantAccount,
operation: Op,
req: Req,
use_connector: Option<api_enums::Connector>,
call_connector_action: CallConnectorAction,
) -> RouterResult<(PaymentData<F>, Req, Option<storage::Customer>)>
where
@ -100,7 +98,7 @@ where
let connector_details = operation
.to_domain()?
.get_connector(&merchant_account, state, use_connector)
.get_connector(&merchant_account, state, &req)
.await?;
if let api::ConnectorCallType::Single(ref connector) = connector_details {
@ -163,7 +161,6 @@ pub async fn payments_core<F, Res, Req, Op, FData>(
operation: Op,
req: Req,
auth_flow: services::AuthFlow,
use_connector: Option<api_enums::Connector>,
call_connector_action: CallConnectorAction,
) -> RouterResponse<Res>
where
@ -188,7 +185,6 @@ where
merchant_account,
operation.clone(),
req,
use_connector,
call_connector_action,
)
.await?;
@ -276,7 +272,6 @@ pub async fn payments_response_for_redirection_flows<'a>(
PaymentStatus,
req,
services::api::AuthFlow::Merchant,
None,
flow_type,
)
.await

View File

@ -26,8 +26,7 @@ use crate::{
db::StorageInterface,
routes::AppState,
types::{
self,
api::{self, enums as api_enums},
self, api,
storage::{self, enums},
PaymentsResponseData,
},
@ -125,7 +124,7 @@ pub trait Domain<F: Clone, R>: Send + Sync {
&'a self,
merchant_account: &storage::MerchantAccount,
state: &AppState,
request_connector: Option<api_enums::Connector>,
request: &R,
) -> CustomResult<api::ConnectorCallType, errors::ApiErrorResponse>;
}
@ -192,9 +191,9 @@ where
&'a self,
merchant_account: &storage::MerchantAccount,
state: &AppState,
request_connector: Option<api_enums::Connector>,
_request: &api::PaymentsRetrieveRequest,
) -> CustomResult<api::ConnectorCallType, errors::ApiErrorResponse> {
helpers::get_connector_default(merchant_account, state, request_connector).await
helpers::get_connector_default(merchant_account, state, None).await
}
#[instrument(skip_all)]
@ -258,9 +257,9 @@ where
&'a self,
merchant_account: &storage::MerchantAccount,
state: &AppState,
request_connector: Option<api_enums::Connector>,
_request: &api::PaymentsCaptureRequest,
) -> CustomResult<api::ConnectorCallType, errors::ApiErrorResponse> {
helpers::get_connector_default(merchant_account, state, request_connector).await
helpers::get_connector_default(merchant_account, state, None).await
}
}
@ -312,8 +311,8 @@ where
&'a self,
merchant_account: &storage::MerchantAccount,
state: &AppState,
request_connector: Option<api_enums::Connector>,
_request: &api::PaymentsCancelRequest,
) -> CustomResult<api::ConnectorCallType, errors::ApiErrorResponse> {
helpers::get_connector_default(merchant_account, state, request_connector).await
helpers::get_connector_default(merchant_account, state, None).await
}
}

View File

@ -16,7 +16,7 @@ use crate::{
routes::AppState,
types::{
self,
api::{self, enums as api_enums, PaymentIdTypeExt},
api::{self, PaymentIdTypeExt},
storage::{self, enums},
transformers::ForeignInto,
},
@ -254,9 +254,9 @@ impl<F: Clone + Send> Domain<F, api::PaymentsRequest> for PaymentConfirm {
&'a self,
merchant_account: &storage::MerchantAccount,
state: &AppState,
request_connector: Option<api_enums::Connector>,
request: &api::PaymentsRequest,
) -> CustomResult<api::ConnectorCallType, errors::ApiErrorResponse> {
helpers::get_connector_default(merchant_account, state, request_connector).await
helpers::get_connector_default(merchant_account, state, request.connector).await
}
}

View File

@ -19,7 +19,7 @@ use crate::{
routes::AppState,
types::{
self,
api::{self, enums as api_enums, PaymentIdTypeExt},
api::{self, PaymentIdTypeExt},
storage::{
self,
enums::{self, IntentStatus},
@ -256,9 +256,9 @@ impl<F: Clone + Send> Domain<F, api::PaymentsRequest> for PaymentCreate {
&'a self,
merchant_account: &storage::MerchantAccount,
state: &AppState,
request_connector: Option<api_enums::Connector>,
request: &api::PaymentsRequest,
) -> CustomResult<api::ConnectorCallType, errors::ApiErrorResponse> {
helpers::get_connector_default(merchant_account, state, request_connector).await
helpers::get_connector_default(merchant_account, state, request.connector).await
}
}

View File

@ -252,9 +252,9 @@ where
&'a self,
merchant_account: &storage::MerchantAccount,
state: &AppState,
request_connector: Option<api_enums::Connector>,
_request: &api::VerifyRequest,
) -> CustomResult<api::ConnectorCallType, errors::ApiErrorResponse> {
helpers::get_connector_default(merchant_account, state, request_connector).await
helpers::get_connector_default(merchant_account, state, None).await
}
}

View File

@ -1,4 +1,4 @@
use std::marker::PhantomData;
use std::{collections::HashSet, marker::PhantomData};
use async_trait::async_trait;
use common_utils::ext_traits::ValueExt;
@ -268,7 +268,7 @@ where
&'a self,
merchant_account: &storage::MerchantAccount,
state: &AppState,
_request_connector: Option<api_enums::Connector>,
request: &api::PaymentsSessionRequest,
) -> RouterResult<api::ConnectorCallType> {
let connectors = &state.conf.connectors;
let db = &state.store;
@ -287,10 +287,10 @@ where
supported_connectors.contains(&connector_account.connector_name)
})
.map(|filtered_connector| filtered_connector.connector_name.clone())
.collect::<Vec<String>>();
.collect::<HashSet<String>>();
// Parse the payment methods enabled to check if the merchant has enabled gpay ( wallet )
// through that connector this parsing from Value to payment method is costly and has to be done for every connector
// through that connector. This parsing from serde_json::Value to payment method is costly and has to be done for every connector
// for sure looks like an area of optimization
let session_token_from_metadata_connectors = connector_accounts
.iter()
@ -310,8 +310,35 @@ where
})
})
.map(|filtered_connector| filtered_connector.connector_name.clone())
.collect::<Vec<String>>();
.collect::<HashSet<String>>();
let given_wallets = request.wallets.clone();
let connectors_data = if !given_wallets.is_empty() {
// Create connectors for provided wallets
let mut connectors_data = Vec::with_capacity(supported_connectors.len());
for wallet in given_wallets {
let (connector_name, connector_type) = match wallet {
api_enums::SupportedWallets::Gpay => ("adyen", api::GetToken::Metadata),
api_enums::SupportedWallets::ApplePay => ("applepay", api::GetToken::Connector),
api_enums::SupportedWallets::Paypal => ("braintree", api::GetToken::Connector),
api_enums::SupportedWallets::Klarna => ("klarna", api::GetToken::Connector),
};
// Check if merchant has enabled the required merchant connector account
if session_token_from_metadata_connectors.contains(connector_name)
|| normal_connector_names.contains(connector_name)
{
connectors_data.push(api::ConnectorData::get_connector_by_name(
connectors,
connector_name,
connector_type,
)?);
}
}
connectors_data
} else {
// Create connectors for all enabled wallets
let mut connectors_data = Vec::with_capacity(
normal_connector_names.len() + session_token_from_metadata_connectors.len(),
);
@ -333,6 +360,8 @@ where
)?;
connectors_data.push(connector_data);
}
connectors_data
};
Ok(api::ConnectorCallType::Multiple(connectors_data))
}

View File

@ -16,7 +16,7 @@ use crate::{
pii::Secret,
routes::AppState,
types::{
api::{self, enums as api_enums, PaymentIdTypeExt},
api::{self, PaymentIdTypeExt},
storage::{self, enums},
transformers::ForeignInto,
},
@ -252,8 +252,8 @@ where
&'a self,
merchant_account: &storage::MerchantAccount,
state: &AppState,
request_connector: Option<api_enums::Connector>,
_request: &api::PaymentsStartRequest,
) -> CustomResult<api::ConnectorCallType, errors::ApiErrorResponse> {
helpers::get_connector_default(merchant_account, state, request_connector).await
helpers::get_connector_default(merchant_account, state, None).await
}
}

View File

@ -14,7 +14,7 @@ use crate::{
db::StorageInterface,
routes::AppState,
types::{
api::{self, enums as api_enums},
api,
storage::{self, enums},
transformers::ForeignInto,
},
@ -100,9 +100,9 @@ impl<F: Clone + Send> Domain<F, api::PaymentsRequest> for PaymentStatus {
&'a self,
merchant_account: &storage::MerchantAccount,
state: &AppState,
request_connector: Option<api_enums::Connector>,
_request: &api::PaymentsRequest,
) -> CustomResult<api::ConnectorCallType, errors::ApiErrorResponse> {
helpers::get_connector_default(merchant_account, state, request_connector).await
helpers::get_connector_default(merchant_account, state, None).await
}
}

View File

@ -16,7 +16,7 @@ use crate::{
db::StorageInterface,
routes::AppState,
types::{
api::{self, enums as api_enums, PaymentIdTypeExt},
api::{self, PaymentIdTypeExt},
storage::{self, enums},
transformers::ForeignInto,
},
@ -271,9 +271,9 @@ impl<F: Clone + Send> Domain<F, api::PaymentsRequest> for PaymentUpdate {
&'a self,
merchant_account: &storage::MerchantAccount,
state: &AppState,
request_connector: Option<api_enums::Connector>,
_request: &api::PaymentsRequest,
) -> CustomResult<api::ConnectorCallType, errors::ApiErrorResponse> {
helpers::get_connector_default(merchant_account, state, request_connector).await
helpers::get_connector_default(merchant_account, state, None).await
}
}

View File

@ -52,7 +52,6 @@ async fn payments_incoming_webhook_flow(
param: None,
},
services::AuthFlow::Merchant,
None,
consume_or_trigger_flow,
)
.await

View File

@ -63,7 +63,6 @@ pub async fn payments_start(
payments::operations::PaymentStart,
req,
api::AuthFlow::Client,
None,
payments::CallConnectorAction::Trigger,
)
},
@ -103,7 +102,6 @@ pub async fn payments_retrieve(
payments::PaymentStatus,
req,
api::AuthFlow::Merchant,
None,
payments::CallConnectorAction::Trigger,
)
},
@ -219,7 +217,6 @@ pub async fn payments_capture(
payments::PaymentCapture,
payload,
api::AuthFlow::Merchant,
None,
payments::CallConnectorAction::Trigger,
)
},
@ -253,7 +250,6 @@ pub async fn payments_connector_session(
payments::PaymentSession,
payload,
api::AuthFlow::Client,
None,
payments::CallConnectorAction::Trigger,
)
},
@ -317,7 +313,6 @@ pub async fn payments_cancel(
payments::PaymentCancel,
req,
api::AuthFlow::Merchant,
None,
payments::CallConnectorAction::Trigger,
)
},
@ -366,7 +361,6 @@ where
// the operation are flow agnostic, and the flow is only required in the post_update_tracker
// Thus the flow can be generated just before calling the connector instead of explicitly passing it here.
let connector = req.connector;
match req.amount.as_ref() {
Some(api_types::Amount::Value(_)) | None => payments::payments_core::<
api_types::Authorize,
@ -380,7 +374,6 @@ where
operation,
req,
auth_flow,
connector,
payments::CallConnectorAction::Trigger,
)
.await,
@ -392,7 +385,6 @@ where
operation,
req,
auth_flow,
connector,
payments::CallConnectorAction::Trigger,
)
.await

View File

@ -41,7 +41,6 @@ impl ProcessTrackerWorkflow for PaymentsSyncWorkflow {
merchant_account.clone(),
operations::PaymentStatus,
tracking_data.clone(),
None,
payment_flows::CallConnectorAction::Trigger,
)
.await?;

View File

@ -355,7 +355,6 @@ async fn payments_create_core() {
payments::PaymentCreate,
req,
services::AuthFlow::Merchant,
None,
payments::CallConnectorAction::Trigger,
)
.await
@ -513,7 +512,6 @@ async fn payments_create_core_adyen_no_redirect() {
payments::PaymentCreate,
req,
services::AuthFlow::Merchant,
None,
payments::CallConnectorAction::Trigger,
)
.await

View File

@ -106,7 +106,6 @@ async fn payments_create_core() {
payments::PaymentCreate,
req,
services::AuthFlow::Merchant,
None,
payments::CallConnectorAction::Trigger,
)
.await
@ -267,7 +266,6 @@ async fn payments_create_core_adyen_no_redirect() {
payments::PaymentCreate,
req,
services::AuthFlow::Merchant,
None,
payments::CallConnectorAction::Trigger,
)
.await