Skip to content

Commit

Permalink
refactor: Move trait ConnectorIntegration to crate hyperswitch_interf…
Browse files Browse the repository at this point in the history
…aces (#4946)

Co-authored-by: Deepanshu Bansal <deepanshu.bansal@Deepanshu-Bansal-K3PYF02LFW.local>
  • Loading branch information
deepanshu-iiitu and Deepanshu Bansal committed Jun 18, 2024
1 parent a0f3887 commit cbe3a6d
Show file tree
Hide file tree
Showing 19 changed files with 635 additions and 509 deletions.
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions crates/hyperswitch_interfaces/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,28 @@ rust-version.workspace = true
readme = "README.md"
license.workspace = true

[features]
default = ["dummy_connector", "payouts"]
dummy_connector = []
payouts = []

[dependencies]
async-trait = "0.1.79"
bytes = "1.6.0"
dyn-clone = "1.0.17"
http = "0.2.12"
mime = "0.3.17"
once_cell = "1.19.0"
reqwest = "0.11.27"
serde = { version = "1.0.197", features = ["derive"] }
serde_json = "1.0.115"
thiserror = "1.0.58"
time = "0.3.35"

# First party crates
common_utils = { version = "0.1.0", path = "../common_utils" }
hyperswitch_domain_models = { version = "0.1.0", path = "../hyperswitch_domain_models", default-features = false }
masking = { version = "0.1.0", path = "../masking" }
router_derive = { version = "0.1.0", path = "../router_derive" }
router_env = { version = "0.1.0", path = "../router_env" }
storage_impl = { version = "0.1.0", path = "../storage_impl", default-features = false }
183 changes: 183 additions & 0 deletions crates/hyperswitch_interfaces/src/api.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
//! API interface

use common_utils::{
errors::CustomResult,
request::{Method, Request, RequestContent},
};
use hyperswitch_domain_models::router_data::{ErrorResponse, RouterData};
use masking::Maskable;
use serde_json::json;

use crate::{
configs::Connectors, errors, events::connector_api_logs::ConnectorEvent, metrics, types,
};

/// type BoxedConnectorIntegration
pub type BoxedConnectorIntegration<'a, T, Req, Resp> =
Box<&'a (dyn ConnectorIntegration<T, Req, Resp> + Send + Sync)>;

/// trait ConnectorIntegrationAny
pub trait ConnectorIntegrationAny<T, Req, Resp>: Send + Sync + 'static {
/// fn get_connector_integration
fn get_connector_integration(&self) -> BoxedConnectorIntegration<'_, T, Req, Resp>;
}

impl<S, T, Req, Resp> ConnectorIntegrationAny<T, Req, Resp> for S
where
S: ConnectorIntegration<T, Req, Resp> + Send + Sync,
{
fn get_connector_integration(&self) -> BoxedConnectorIntegration<'_, T, Req, Resp> {
Box::new(self)
}
}

/// trait ConnectorIntegration
pub trait ConnectorIntegration<T, Req, Resp>: ConnectorIntegrationAny<T, Req, Resp> + Sync {
/// fn get_headers
fn get_headers(
&self,
_req: &RouterData<T, Req, Resp>,
_connectors: &Connectors,
) -> CustomResult<Vec<(String, Maskable<String>)>, errors::ConnectorError> {
Ok(vec![])
}

/// fn get_content_type
fn get_content_type(&self) -> &'static str {
mime::APPLICATION_JSON.essence_str()
}

/// primarily used when creating signature based on request method of payment flow
fn get_http_method(&self) -> Method {
Method::Post
}

/// fn get_url
fn get_url(
&self,
_req: &RouterData<T, Req, Resp>,
_connectors: &Connectors,
) -> CustomResult<String, errors::ConnectorError> {
Ok(String::new())
}

/// fn get_request_body
fn get_request_body(
&self,
_req: &RouterData<T, Req, Resp>,
_connectors: &Connectors,
) -> CustomResult<RequestContent, errors::ConnectorError> {
Ok(RequestContent::Json(Box::new(json!(r#"{}"#))))
}

/// fn get_request_form_data
fn get_request_form_data(
&self,
_req: &RouterData<T, Req, Resp>,
) -> CustomResult<Option<reqwest::multipart::Form>, errors::ConnectorError> {
Ok(None)
}

/// fn build_request
fn build_request(
&self,
req: &RouterData<T, Req, Resp>,
_connectors: &Connectors,
) -> CustomResult<Option<Request>, errors::ConnectorError> {
metrics::UNIMPLEMENTED_FLOW.add(
&metrics::CONTEXT,
1,
&[metrics::add_attributes("connector", req.connector.clone())],
);
Ok(None)
}

/// fn handle_response
fn handle_response(
&self,
data: &RouterData<T, Req, Resp>,
event_builder: Option<&mut ConnectorEvent>,
_res: types::Response,
) -> CustomResult<RouterData<T, Req, Resp>, errors::ConnectorError>
where
T: Clone,
Req: Clone,
Resp: Clone,
{
event_builder.map(|e| e.set_error(json!({"error": "Not Implemented"})));
Ok(data.clone())
}

/// fn get_error_response
fn get_error_response(
&self,
res: types::Response,
event_builder: Option<&mut ConnectorEvent>,
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
event_builder.map(|event| event.set_error(json!({"error": res.response.escape_ascii().to_string(), "status_code": res.status_code})));
Ok(ErrorResponse::get_not_implemented())
}

/// fn get_5xx_error_response
fn get_5xx_error_response(
&self,
res: types::Response,
event_builder: Option<&mut ConnectorEvent>,
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
event_builder.map(|event| event.set_error(json!({"error": res.response.escape_ascii().to_string(), "status_code": res.status_code})));
let error_message = match res.status_code {
500 => "internal_server_error",
501 => "not_implemented",
502 => "bad_gateway",
503 => "service_unavailable",
504 => "gateway_timeout",
505 => "http_version_not_supported",
506 => "variant_also_negotiates",
507 => "insufficient_storage",
508 => "loop_detected",
510 => "not_extended",
511 => "network_authentication_required",
_ => "unknown_error",
};
Ok(ErrorResponse {
code: res.status_code.to_string(),
message: error_message.to_string(),
reason: String::from_utf8(res.response.to_vec()).ok(),
status_code: res.status_code,
attempt_status: None,
connector_transaction_id: None,
})
}

/// whenever capture sync is implemented at the connector side, this method should be overridden
fn get_multiple_capture_sync_method(
&self,
) -> CustomResult<CaptureSyncMethod, errors::ConnectorError> {
Err(errors::ConnectorError::NotImplemented("multiple capture sync".into()).into())
}

/// fn get_certificate
fn get_certificate(
&self,
_req: &RouterData<T, Req, Resp>,
) -> CustomResult<Option<String>, errors::ConnectorError> {
Ok(None)
}

/// fn get_certificate_key
fn get_certificate_key(
&self,
_req: &RouterData<T, Req, Resp>,
) -> CustomResult<Option<String>, errors::ConnectorError> {
Ok(None)
}
}

/// Sync Methods for multiple captures
#[derive(Debug)]
pub enum CaptureSyncMethod {
/// For syncing multiple captures individually
Individual,
/// For syncing multiple captures together
Bulk,
}
132 changes: 132 additions & 0 deletions crates/hyperswitch_interfaces/src/configs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
//! Configs interface
use router_derive;
use serde::Deserialize;
use storage_impl::errors::ApplicationError;

// struct Connectors
#[allow(missing_docs, missing_debug_implementations)]
#[derive(Debug, Deserialize, Clone, Default, router_derive::ConfigValidate)]
#[serde(default)]
pub struct Connectors {
pub aci: ConnectorParams,
#[cfg(feature = "payouts")]
pub adyen: ConnectorParamsWithSecondaryBaseUrl,
pub adyenplatform: ConnectorParams,
#[cfg(not(feature = "payouts"))]
pub adyen: ConnectorParams,
pub airwallex: ConnectorParams,
pub applepay: ConnectorParams,
pub authorizedotnet: ConnectorParams,
pub bambora: ConnectorParams,
pub bankofamerica: ConnectorParams,
pub billwerk: ConnectorParams,
pub bitpay: ConnectorParams,
pub bluesnap: ConnectorParamsWithSecondaryBaseUrl,
pub boku: ConnectorParams,
pub braintree: ConnectorParams,
pub cashtocode: ConnectorParams,
pub checkout: ConnectorParams,
pub coinbase: ConnectorParams,
pub cryptopay: ConnectorParams,
pub cybersource: ConnectorParams,
pub datatrans: ConnectorParams,
pub dlocal: ConnectorParams,
#[cfg(feature = "dummy_connector")]
pub dummyconnector: ConnectorParams,
pub ebanx: ConnectorParams,
pub fiserv: ConnectorParams,
pub forte: ConnectorParams,
pub globalpay: ConnectorParams,
pub globepay: ConnectorParams,
pub gocardless: ConnectorParams,
pub gpayments: ConnectorParams,
pub helcim: ConnectorParams,
pub iatapay: ConnectorParams,
pub klarna: ConnectorParams,
pub mifinity: ConnectorParams,
pub mollie: ConnectorParams,
pub multisafepay: ConnectorParams,
pub netcetera: ConnectorParams,
pub nexinets: ConnectorParams,
pub nmi: ConnectorParams,
pub noon: ConnectorParamsWithModeType,
pub nuvei: ConnectorParams,
pub opayo: ConnectorParams,
pub opennode: ConnectorParams,
pub payeezy: ConnectorParams,
pub payme: ConnectorParams,
pub payone: ConnectorParams,
pub paypal: ConnectorParams,
pub payu: ConnectorParams,
pub placetopay: ConnectorParams,
pub powertranz: ConnectorParams,
pub prophetpay: ConnectorParams,
pub rapyd: ConnectorParams,
pub riskified: ConnectorParams,
pub shift4: ConnectorParams,
pub signifyd: ConnectorParams,
pub square: ConnectorParams,
pub stax: ConnectorParams,
pub stripe: ConnectorParamsWithFileUploadUrl,
pub threedsecureio: ConnectorParams,
pub trustpay: ConnectorParamsWithMoreUrls,
pub tsys: ConnectorParams,
pub volt: ConnectorParams,
pub wise: ConnectorParams,
pub worldline: ConnectorParams,
pub worldpay: ConnectorParams,
pub zen: ConnectorParams,
pub zsl: ConnectorParams,
}

/// struct ConnectorParams
#[derive(Debug, Deserialize, Clone, Default, router_derive::ConfigValidate)]
#[serde(default)]
pub struct ConnectorParams {
/// base url
pub base_url: String,
/// secondary base url
pub secondary_base_url: Option<String>,
}

/// struct ConnectorParamsWithModeType
#[derive(Debug, Deserialize, Clone, Default, router_derive::ConfigValidate)]
#[serde(default)]
pub struct ConnectorParamsWithModeType {
/// base url
pub base_url: String,
/// secondary base url
pub secondary_base_url: Option<String>,
/// Can take values like Test or Live for Noon
pub key_mode: String,
}

/// struct ConnectorParamsWithMoreUrls
#[derive(Debug, Deserialize, Clone, Default, router_derive::ConfigValidate)]
#[serde(default)]
pub struct ConnectorParamsWithMoreUrls {
/// base url
pub base_url: String,
/// base url for bank redirects
pub base_url_bank_redirects: String,
}

/// struct ConnectorParamsWithFileUploadUrl
#[derive(Debug, Deserialize, Clone, Default, router_derive::ConfigValidate)]
#[serde(default)]
pub struct ConnectorParamsWithFileUploadUrl {
/// base url
pub base_url: String,
/// base url for file upload
pub base_url_file_upload: String,
}

/// struct ConnectorParamsWithSecondaryBaseUrl
#[derive(Debug, Deserialize, Clone, Default, router_derive::ConfigValidate)]
#[serde(default)]
pub struct ConnectorParamsWithSecondaryBaseUrl {
/// base url
pub base_url: String,
/// secondary base url
pub secondary_base_url: String,
}
Loading

0 comments on commit cbe3a6d

Please sign in to comment.