Skip to content

Commit

Permalink
feat: add support for sdk session call in v2 (#6502)
Browse files Browse the repository at this point in the history
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
  • Loading branch information
hrithikesh026 and hyperswitch-bot[bot] authored Nov 28, 2024
1 parent 93459fd commit 707f48c
Show file tree
Hide file tree
Showing 18 changed files with 1,029 additions and 61 deletions.
5 changes: 0 additions & 5 deletions api-reference-v2/openapi_spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -15344,18 +15344,13 @@
"type": "object",
"required": [
"payment_id",
"client_secret",
"session_token"
],
"properties": {
"payment_id": {
"type": "string",
"description": "The identifier for the payment"
},
"client_secret": {
"type": "string",
"description": "This is a token which expires after 15 minutes, used from the client to authenticate and create sessions from the SDK"
},
"session_token": {
"type": "array",
"items": {
Expand Down
1 change: 0 additions & 1 deletion crates/api_models/src/events/payment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,6 @@ impl ApiEventMetric for PaymentsManualUpdateResponse {
}
}

#[cfg(feature = "v1")]
impl ApiEventMetric for PaymentsSessionResponse {
fn get_api_event_type(&self) -> Option<ApiEventsType> {
Some(ApiEventsType::Payment {
Expand Down
11 changes: 11 additions & 0 deletions crates/api_models/src/payments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6084,6 +6084,7 @@ pub struct ApplepayErrorResponse {
pub status_message: String,
}

#[cfg(feature = "v1")]
#[derive(Default, Debug, serde::Serialize, Clone, ToSchema)]
pub struct PaymentsSessionResponse {
/// The identifier for the payment
Expand All @@ -6096,6 +6097,16 @@ pub struct PaymentsSessionResponse {
pub session_token: Vec<SessionToken>,
}

#[cfg(feature = "v2")]
#[derive(Debug, serde::Serialize, Clone, ToSchema)]
pub struct PaymentsSessionResponse {
/// The identifier for the payment
#[schema(value_type = String)]
pub payment_id: id_type::GlobalPaymentId,
/// The list of session token object
pub session_token: Vec<SessionToken>,
}

#[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)]
pub struct PaymentRetrieveBody {
/// The identifier for the Merchant Account.
Expand Down
35 changes: 35 additions & 0 deletions crates/common_utils/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,41 @@ mod id_type {
}
}

/// Create new generic list wrapper
#[macro_export]
macro_rules! create_list_wrapper {
(
$wrapper_name:ident,
$type_name: ty,
impl_functions: {
$($function_def: tt)*
}
) => {
pub struct $wrapper_name(Vec<$type_name>);
impl $wrapper_name {
pub fn new(list: Vec<$type_name>) -> Self {
Self(list)
}
pub fn iter(&self) -> std::slice::Iter<'_, $type_name> {
self.0.iter()
}
$($function_def)*
}
impl Iterator for $wrapper_name {
type Item = $type_name;
fn next(&mut self) -> Option<Self::Item> {
self.0.pop()
}
}

impl FromIterator<$type_name> for $wrapper_name {
fn from_iter<T: IntoIterator<Item = $type_name>>(iter: T) -> Self {
Self(iter.into_iter().collect())
}
}
};
}

/// Get the type name for a type
#[macro_export]
macro_rules! type_name {
Expand Down
2 changes: 1 addition & 1 deletion crates/common_utils/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -845,7 +845,7 @@ mod client_secret_type {
Ok(row)
}
}

crate::impl_serializable_secret_id_type!(ClientSecret);
#[cfg(test)]
mod client_secret_tests {
#![allow(clippy::expect_used)]
Expand Down
123 changes: 97 additions & 26 deletions crates/hyperswitch_domain_models/src/merchant_connector_account.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
#[cfg(feature = "v2")]
use api_models::admin;
#[cfg(feature = "v2")]
use common_utils::ext_traits::ValueExt;
use common_utils::{
crypto::Encryptable,
date_time,
Expand All @@ -9,11 +13,15 @@ use common_utils::{
use diesel_models::{enums, merchant_connector_account::MerchantConnectorAccountUpdateInternal};
use error_stack::ResultExt;
use masking::{PeekInterface, Secret};
#[cfg(feature = "v2")]
use router_env::logger;
use rustc_hash::FxHashMap;
use serde_json::Value;

use super::behaviour;
#[cfg(feature = "v2")]
use crate::errors::api_error_response::ApiErrorResponse;
#[cfg(feature = "v2")]
use crate::router_data;
use crate::type_encryption::{crypto_operation, CryptoOperation};

Expand Down Expand Up @@ -90,6 +98,27 @@ impl MerchantConnectorAccount {
self.id.clone()
}

pub fn get_metadata(&self) -> Option<pii::SecretSerdeValue> {
self.metadata.clone()
}

pub fn get_parsed_payment_methods_enabled(
&self,
) -> Vec<CustomResult<admin::PaymentMethodsEnabled, ApiErrorResponse>> {
self.payment_methods_enabled
.clone()
.unwrap_or_default()
.into_iter()
.map(|payment_methods_enabled| {
payment_methods_enabled
.parse_value::<admin::PaymentMethodsEnabled>("payment_methods_enabled")
.change_context(ApiErrorResponse::InvalidDataValue {
field_name: "payment_methods_enabled",
})
})
.collect()
}

pub fn is_disabled(&self) -> bool {
self.disabled.unwrap_or(false)
}
Expand Down Expand Up @@ -530,31 +559,73 @@ impl From<MerchantConnectorAccountUpdate> for MerchantConnectorAccountUpdateInte
}
}

#[derive(Debug)]
pub struct MerchantConnectorAccounts(Vec<MerchantConnectorAccount>);

impl MerchantConnectorAccounts {
pub fn new(merchant_connector_accounts: Vec<MerchantConnectorAccount>) -> Self {
Self(merchant_connector_accounts)
}

pub fn is_merchant_connector_account_id_in_connector_mandate_details(
&self,
profile_id: Option<&id_type::ProfileId>,
connector_mandate_details: &diesel_models::PaymentsMandateReference,
) -> bool {
let mca_ids = self
.0
.iter()
.filter(|mca| {
mca.disabled.is_some_and(|disabled| !disabled)
&& profile_id.is_some_and(|profile_id| *profile_id == mca.profile_id)
})
.map(|mca| mca.get_id())
.collect::<std::collections::HashSet<_>>();
common_utils::create_list_wrapper!(
MerchantConnectorAccounts,
MerchantConnectorAccount,
impl_functions: {
#[cfg(feature = "v2")]
pub fn get_connector_and_supporting_payment_method_type_for_session_call(
&self,
) -> Vec<(&MerchantConnectorAccount, common_enums::PaymentMethodType)> {
let connector_and_supporting_payment_method_type = self.iter().flat_map(|connector_account| {
connector_account
.get_parsed_payment_methods_enabled()
// TODO: make payment_methods_enabled strict type in DB
.into_iter()
.filter_map(|parsed_payment_method_result| {
parsed_payment_method_result
.inspect_err(|err| {
logger::error!(session_token_parsing_error=?err);
})
.ok()
})
.flat_map(|parsed_payment_methods_enabled| {
parsed_payment_methods_enabled
.payment_method_types
.unwrap_or_default()
.into_iter()
.filter(|payment_method_type| {
let is_invoke_sdk_client = matches!(
payment_method_type.payment_experience,
Some(api_models::enums::PaymentExperience::InvokeSdkClient)
);
is_invoke_sdk_client
})
.map(|payment_method_type| {
(connector_account, payment_method_type.payment_method_type)
})
.collect::<Vec<_>>()
})
.collect::<Vec<_>>()
}).collect();
connector_and_supporting_payment_method_type
}
pub fn filter_based_on_profile_and_connector_type(
self,
profile_id: &id_type::ProfileId,
connector_type: common_enums::ConnectorType,
) -> Self {
self.into_iter()
.filter(|mca| &mca.profile_id == profile_id && mca.connector_type == connector_type)
.collect()
}
pub fn is_merchant_connector_account_id_in_connector_mandate_details(
&self,
profile_id: Option<&id_type::ProfileId>,
connector_mandate_details: &diesel_models::PaymentsMandateReference,
) -> bool {
let mca_ids = self
.iter()
.filter(|mca| {
mca.disabled.is_some_and(|disabled| !disabled)
&& profile_id.is_some_and(|profile_id| *profile_id == mca.profile_id)
})
.map(|mca| mca.get_id())
.collect::<std::collections::HashSet<_>>();

connector_mandate_details
.keys()
.any(|mca_id| mca_ids.contains(mca_id))
connector_mandate_details
.keys()
.any(|mca_id| mca_ids.contains(mca_id))
}
}
}
);
3 changes: 3 additions & 0 deletions crates/hyperswitch_domain_models/src/payments.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#[cfg(feature = "v2")]
use std::marker::PhantomData;

#[cfg(feature = "v2")]
use api_models::payments::SessionToken;
#[cfg(feature = "v2")]
use common_utils::ext_traits::ValueExt;
use common_utils::{
Expand Down Expand Up @@ -566,6 +568,7 @@ where
{
pub flow: PhantomData<F>,
pub payment_intent: PaymentIntent,
pub sessions_token: Vec<SessionToken>,
}

// TODO: Check if this can be merged with existing payment data
Expand Down
Loading

0 comments on commit 707f48c

Please sign in to comment.