Skip to content

Commit c3e8c67

Browse files
feat: add routing support for v2 sdk session flow (#6763)
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
1 parent d586850 commit c3e8c67

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+3358
-3881
lines changed

.typos.toml

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ ws2tcpip = "ws2tcpip" # WinSock Extension
4343
ZAR = "ZAR" # South African Rand currency code
4444
JOD = "JOD" # Jordan currency code
4545
Payed = "Payed" # Paid status for digital virgo
46+
SessionConnectorDatas = "SessionConnectorDatas" # Wrapper for List of SessionConnectorData
4647
Alo = "Alo" # Is iso representation of a state in France
4748
alo = "alo" # Is iso representation of a state in France
4849
BRE = "BRE" # Is iso representation of Brittany

Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/api_models/src/admin.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -205,13 +205,14 @@ pub struct MerchantAccountCreateWithoutOrgId {
205205
// The following struct is only used internally, so we can reuse the common
206206
// part of `create_merchant_account` without duplicating its code for v2
207207
#[cfg(feature = "v2")]
208-
#[derive(Clone, Debug, Serialize)]
208+
#[derive(Clone, Debug, Serialize, ToSchema)]
209209
pub struct MerchantAccountCreate {
210210
pub merchant_name: Secret<common_utils::new_type::MerchantName>,
211211
pub merchant_details: Option<MerchantDetails>,
212212
pub metadata: Option<pii::SecretSerdeValue>,
213213
pub organization_id: id_type::OrganizationId,
214214
/// Product Type of this merchant account
215+
#[schema(value_type = Option<MerchantProductType>)]
215216
pub product_type: Option<api_enums::MerchantProductType>,
216217
}
217218

crates/api_models/src/routing.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ impl EuclidAnalysable for ConnectorSelection {
161161
}
162162
}
163163

164-
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
164+
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema, PartialEq)]
165165
pub struct ConnectorVolumeSplit {
166166
pub connector: RoutableConnectorChoice,
167167
pub split: u8,
@@ -178,7 +178,7 @@ pub struct RoutableConnectorChoice {
178178
pub merchant_connector_id: Option<common_utils::id_type::MerchantConnectorAccountId>,
179179
}
180180

181-
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize, ToSchema)]
181+
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize, ToSchema, PartialEq)]
182182
pub enum RoutableChoiceKind {
183183
OnlyConnector,
184184
FullStruct,
@@ -337,7 +337,7 @@ impl TryFrom<RoutingAlgorithmSerde> for RoutingAlgorithm {
337337
}
338338
}
339339

340-
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
340+
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema, PartialEq)]
341341
#[serde(
342342
tag = "type",
343343
content = "data",

crates/common_enums/src/connector_enums.rs

+112
Original file line numberDiff line numberDiff line change
@@ -594,3 +594,115 @@ impl From<RoutableConnectors> for Connector {
594594
}
595595
}
596596
}
597+
598+
impl TryFrom<Connector> for RoutableConnectors {
599+
type Error = &'static str;
600+
601+
fn try_from(connector: Connector) -> Result<Self, Self::Error> {
602+
match connector {
603+
Connector::Adyenplatform => Ok(Self::Adyenplatform),
604+
#[cfg(feature = "dummy_connector")]
605+
Connector::DummyConnector1 => Ok(Self::DummyConnector1),
606+
#[cfg(feature = "dummy_connector")]
607+
Connector::DummyConnector2 => Ok(Self::DummyConnector2),
608+
#[cfg(feature = "dummy_connector")]
609+
Connector::DummyConnector3 => Ok(Self::DummyConnector3),
610+
#[cfg(feature = "dummy_connector")]
611+
Connector::DummyConnector4 => Ok(Self::DummyConnector4),
612+
#[cfg(feature = "dummy_connector")]
613+
Connector::DummyConnector5 => Ok(Self::DummyConnector5),
614+
#[cfg(feature = "dummy_connector")]
615+
Connector::DummyConnector6 => Ok(Self::DummyConnector6),
616+
#[cfg(feature = "dummy_connector")]
617+
Connector::DummyConnector7 => Ok(Self::DummyConnector7),
618+
Connector::Aci => Ok(Self::Aci),
619+
Connector::Adyen => Ok(Self::Adyen),
620+
Connector::Airwallex => Ok(Self::Airwallex),
621+
Connector::Authorizedotnet => Ok(Self::Authorizedotnet),
622+
Connector::Bankofamerica => Ok(Self::Bankofamerica),
623+
Connector::Billwerk => Ok(Self::Billwerk),
624+
Connector::Bitpay => Ok(Self::Bitpay),
625+
Connector::Bambora => Ok(Self::Bambora),
626+
Connector::Bamboraapac => Ok(Self::Bamboraapac),
627+
Connector::Bluesnap => Ok(Self::Bluesnap),
628+
Connector::Boku => Ok(Self::Boku),
629+
Connector::Braintree => Ok(Self::Braintree),
630+
Connector::Cashtocode => Ok(Self::Cashtocode),
631+
Connector::Chargebee => Ok(Self::Chargebee),
632+
Connector::Checkout => Ok(Self::Checkout),
633+
Connector::Coinbase => Ok(Self::Coinbase),
634+
Connector::Coingate => Ok(Self::Coingate),
635+
Connector::Cryptopay => Ok(Self::Cryptopay),
636+
Connector::Cybersource => Ok(Self::Cybersource),
637+
Connector::Datatrans => Ok(Self::Datatrans),
638+
Connector::Deutschebank => Ok(Self::Deutschebank),
639+
Connector::Digitalvirgo => Ok(Self::Digitalvirgo),
640+
Connector::Dlocal => Ok(Self::Dlocal),
641+
Connector::Ebanx => Ok(Self::Ebanx),
642+
Connector::Elavon => Ok(Self::Elavon),
643+
Connector::Fiserv => Ok(Self::Fiserv),
644+
Connector::Fiservemea => Ok(Self::Fiservemea),
645+
Connector::Fiuu => Ok(Self::Fiuu),
646+
Connector::Forte => Ok(Self::Forte),
647+
Connector::Globalpay => Ok(Self::Globalpay),
648+
Connector::Globepay => Ok(Self::Globepay),
649+
Connector::Gocardless => Ok(Self::Gocardless),
650+
Connector::Helcim => Ok(Self::Helcim),
651+
Connector::Iatapay => Ok(Self::Iatapay),
652+
Connector::Itaubank => Ok(Self::Itaubank),
653+
Connector::Jpmorgan => Ok(Self::Jpmorgan),
654+
Connector::Klarna => Ok(Self::Klarna),
655+
Connector::Mifinity => Ok(Self::Mifinity),
656+
Connector::Mollie => Ok(Self::Mollie),
657+
Connector::Moneris => Ok(Self::Moneris),
658+
Connector::Multisafepay => Ok(Self::Multisafepay),
659+
Connector::Nexinets => Ok(Self::Nexinets),
660+
Connector::Nexixpay => Ok(Self::Nexixpay),
661+
Connector::Nmi => Ok(Self::Nmi),
662+
Connector::Nomupay => Ok(Self::Nomupay),
663+
Connector::Noon => Ok(Self::Noon),
664+
Connector::Novalnet => Ok(Self::Novalnet),
665+
Connector::Nuvei => Ok(Self::Nuvei),
666+
Connector::Opennode => Ok(Self::Opennode),
667+
Connector::Paybox => Ok(Self::Paybox),
668+
Connector::Payme => Ok(Self::Payme),
669+
Connector::Payone => Ok(Self::Payone),
670+
Connector::Paypal => Ok(Self::Paypal),
671+
Connector::Paystack => Ok(Self::Paystack),
672+
Connector::Payu => Ok(Self::Payu),
673+
Connector::Placetopay => Ok(Self::Placetopay),
674+
Connector::Powertranz => Ok(Self::Powertranz),
675+
Connector::Prophetpay => Ok(Self::Prophetpay),
676+
Connector::Rapyd => Ok(Self::Rapyd),
677+
Connector::Razorpay => Ok(Self::Razorpay),
678+
Connector::Riskified => Ok(Self::Riskified),
679+
Connector::Shift4 => Ok(Self::Shift4),
680+
Connector::Signifyd => Ok(Self::Signifyd),
681+
Connector::Square => Ok(Self::Square),
682+
Connector::Stax => Ok(Self::Stax),
683+
Connector::Stripe => Ok(Self::Stripe),
684+
Connector::Trustpay => Ok(Self::Trustpay),
685+
Connector::Tsys => Ok(Self::Tsys),
686+
Connector::Volt => Ok(Self::Volt),
687+
Connector::Wellsfargo => Ok(Self::Wellsfargo),
688+
Connector::Wise => Ok(Self::Wise),
689+
Connector::Worldline => Ok(Self::Worldline),
690+
Connector::Worldpay => Ok(Self::Worldpay),
691+
Connector::Xendit => Ok(Self::Xendit),
692+
Connector::Zen => Ok(Self::Zen),
693+
Connector::Plaid => Ok(Self::Plaid),
694+
Connector::Zsl => Ok(Self::Zsl),
695+
Connector::Recurly => Ok(Self::Recurly),
696+
Connector::Getnet => Ok(Self::Getnet),
697+
Connector::Hipay => Ok(Self::Hipay),
698+
Connector::Inespay => Ok(Self::Inespay),
699+
Connector::Redsys => Ok(Self::Redsys),
700+
Connector::CtpMastercard
701+
| Connector::Gpayments
702+
| Connector::Juspaythreedsserver
703+
| Connector::Netcetera
704+
| Connector::Taxjar
705+
| Connector::Threedsecureio => Err("Invalid conversion. Not a routable connector"),
706+
}
707+
}
708+
}

crates/common_utils/src/macros.rs

+26-5
Original file line numberDiff line numberDiff line change
@@ -381,20 +381,41 @@ macro_rules! create_list_wrapper {
381381
$($function_def: tt)*
382382
}
383383
) => {
384+
#[derive(Clone, Debug)]
384385
pub struct $wrapper_name(Vec<$type_name>);
385386
impl $wrapper_name {
386387
pub fn new(list: Vec<$type_name>) -> Self {
387388
Self(list)
388389
}
389-
pub fn iter(&self) -> std::slice::Iter<'_, $type_name> {
390-
self.0.iter()
390+
pub fn with_capacity(size: usize) -> Self {
391+
Self(Vec::with_capacity(size))
391392
}
392393
$($function_def)*
393394
}
394-
impl Iterator for $wrapper_name {
395+
impl std::ops::Deref for $wrapper_name {
396+
type Target = Vec<$type_name>;
397+
fn deref(&self) -> &<Self as std::ops::Deref>::Target {
398+
&self.0
399+
}
400+
}
401+
impl std::ops::DerefMut for $wrapper_name {
402+
fn deref_mut(&mut self) -> &mut Self::Target {
403+
&mut self.0
404+
}
405+
}
406+
impl IntoIterator for $wrapper_name {
395407
type Item = $type_name;
396-
fn next(&mut self) -> Option<Self::Item> {
397-
self.0.pop()
408+
type IntoIter = std::vec::IntoIter<$type_name>;
409+
fn into_iter(self) -> Self::IntoIter {
410+
self.0.into_iter()
411+
}
412+
}
413+
414+
impl<'a> IntoIterator for &'a $wrapper_name {
415+
type Item = &'a $type_name;
416+
type IntoIter = std::slice::Iter<'a, $type_name>;
417+
fn into_iter(self) -> Self::IntoIter {
418+
self.0.iter()
398419
}
399420
}
400421

crates/diesel_models/src/payment_intent.rs

+1
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,7 @@ pub struct PaymentIntentUpdateFields {
559559
#[diesel(table_name = payment_intent)]
560560
pub struct PaymentIntentUpdateInternal {
561561
pub status: Option<storage_enums::IntentStatus>,
562+
pub prerouting_algorithm: Option<serde_json::Value>,
562563
pub amount_captured: Option<MinorUnit>,
563564
pub modified_at: PrimitiveDateTime,
564565
pub active_attempt_id: Option<Option<common_utils::id_type::GlobalAttemptId>>,

crates/hyperswitch_connectors/src/connectors/coinbase.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use common_utils::{
1111
};
1212
use error_stack::ResultExt;
1313
use hyperswitch_domain_models::{
14+
configs::Connectors,
1415
router_data::{AccessToken, ConnectorAuthType, ErrorResponse, RouterData},
1516
router_flow_types::{
1617
access_token_auth::AccessTokenAuth,
@@ -36,7 +37,6 @@ use hyperswitch_interfaces::{
3637
self, ConnectorCommon, ConnectorCommonExt, ConnectorIntegration, ConnectorSpecifications,
3738
ConnectorValidation,
3839
},
39-
configs::Connectors,
4040
errors,
4141
events::connector_api_logs::ConnectorEvent,
4242
types::{PaymentsAuthorizeType, PaymentsSyncType, Response},

crates/hyperswitch_connectors/src/connectors/helcim.rs

+46-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ use common_utils::{
1010
};
1111
use error_stack::{report, ResultExt};
1212
use hyperswitch_domain_models::{
13+
errors::api_error_response::ApiErrorResponse,
14+
payments::payment_attempt::PaymentAttempt,
1315
router_data::{AccessToken, ConnectorAuthType, ErrorResponse, RouterData},
1416
router_flow_types::{
1517
access_token_auth::AccessTokenAuth,
@@ -33,7 +35,7 @@ use hyperswitch_domain_models::{
3335
use hyperswitch_interfaces::{
3436
api::{
3537
self, ConnectorCommon, ConnectorCommonExt, ConnectorIntegration, ConnectorSpecifications,
36-
ConnectorValidation,
38+
ConnectorTransactionId, ConnectorValidation,
3739
},
3840
configs::Connectors,
3941
consts::NO_ERROR_CODE,
@@ -43,6 +45,8 @@ use hyperswitch_interfaces::{
4345
webhooks::{IncomingWebhook, IncomingWebhookRequestDetails},
4446
};
4547
use lazy_static::lazy_static;
48+
#[cfg(feature = "v2")]
49+
use masking::PeekInterface;
4650
use masking::{ExposeInterface, Mask};
4751
use transformers as helcim;
4852

@@ -917,3 +921,44 @@ impl ConnectorSpecifications for Helcim {
917921
Some(&*HELCIM_SUPPORTED_WEBHOOK_FLOWS)
918922
}
919923
}
924+
925+
impl ConnectorTransactionId for Helcim {
926+
#[cfg(feature = "v1")]
927+
fn connector_transaction_id(
928+
&self,
929+
payment_attempt: PaymentAttempt,
930+
) -> Result<Option<String>, ApiErrorResponse> {
931+
if payment_attempt.get_connector_payment_id().is_none() {
932+
let metadata =
933+
Self::connector_transaction_id(self, payment_attempt.connector_metadata.as_ref());
934+
metadata.map_err(|_| ApiErrorResponse::ResourceIdNotFound)
935+
} else {
936+
Ok(payment_attempt
937+
.get_connector_payment_id()
938+
.map(ToString::to_string))
939+
}
940+
}
941+
942+
#[cfg(feature = "v2")]
943+
fn connector_transaction_id(
944+
&self,
945+
payment_attempt: PaymentAttempt,
946+
) -> Result<Option<String>, ApiErrorResponse> {
947+
use hyperswitch_domain_models::errors::api_error_response::ApiErrorResponse;
948+
949+
if payment_attempt.get_connector_payment_id().is_none() {
950+
let metadata = Self::connector_transaction_id(
951+
self,
952+
payment_attempt
953+
.connector_metadata
954+
.as_ref()
955+
.map(|connector_metadata| connector_metadata.peek()),
956+
);
957+
metadata.map_err(|_| ApiErrorResponse::ResourceIdNotFound)
958+
} else {
959+
Ok(payment_attempt
960+
.get_connector_payment_id()
961+
.map(ToString::to_string))
962+
}
963+
}
964+
}

crates/hyperswitch_connectors/src/connectors/nexinets.rs

+34-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ use common_utils::{
99
};
1010
use error_stack::{report, ResultExt};
1111
use hyperswitch_domain_models::{
12+
errors::api_error_response::ApiErrorResponse,
1213
payment_method_data::PaymentMethodData,
14+
payments::payment_attempt::PaymentAttempt,
1315
router_data::{AccessToken, ConnectorAuthType, ErrorResponse, RouterData},
1416
router_flow_types::{
1517
access_token_auth::AccessTokenAuth,
@@ -30,7 +32,7 @@ use hyperswitch_domain_models::{
3032
use hyperswitch_interfaces::{
3133
api::{
3234
self, ConnectorCommon, ConnectorCommonExt, ConnectorIntegration, ConnectorSpecifications,
33-
ConnectorValidation,
35+
ConnectorTransactionId, ConnectorValidation,
3436
},
3537
configs::Connectors,
3638
errors,
@@ -42,6 +44,8 @@ use hyperswitch_interfaces::{
4244
webhooks::{IncomingWebhook, IncomingWebhookRequestDetails},
4345
};
4446
use masking::Mask;
47+
#[cfg(feature = "v2")]
48+
use masking::PeekInterface;
4549
use transformers as nexinets;
4650

4751
use crate::{
@@ -746,3 +750,32 @@ impl ConnectorIntegration<PaymentMethodToken, PaymentMethodTokenizationData, Pay
746750
}
747751

748752
impl ConnectorSpecifications for Nexinets {}
753+
754+
impl ConnectorTransactionId for Nexinets {
755+
#[cfg(feature = "v1")]
756+
fn connector_transaction_id(
757+
&self,
758+
payment_attempt: PaymentAttempt,
759+
) -> Result<Option<String>, ApiErrorResponse> {
760+
let metadata =
761+
Self::connector_transaction_id(self, payment_attempt.connector_metadata.as_ref());
762+
metadata.map_err(|_| ApiErrorResponse::ResourceIdNotFound)
763+
}
764+
765+
#[cfg(feature = "v2")]
766+
fn connector_transaction_id(
767+
&self,
768+
payment_attempt: PaymentAttempt,
769+
) -> Result<Option<String>, ApiErrorResponse> {
770+
use hyperswitch_domain_models::errors::api_error_response::ApiErrorResponse;
771+
772+
let metadata = Self::connector_transaction_id(
773+
self,
774+
payment_attempt
775+
.connector_metadata
776+
.as_ref()
777+
.map(|connector_metadata| connector_metadata.peek()),
778+
);
779+
metadata.map_err(|_| ApiErrorResponse::ResourceIdNotFound)
780+
}
781+
}

0 commit comments

Comments
 (0)