mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-29 00:49:42 +08:00
refactor: Move trait ConnectorIntegration to crate hyperswitch_interfaces (#4946)
Co-authored-by: Deepanshu Bansal <deepanshu.bansal@Deepanshu-Bansal-K3PYF02LFW.local>
This commit is contained in:
@ -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
crates/hyperswitch_interfaces/src/api.rs
Normal file
183
crates/hyperswitch_interfaces/src/api.rs
Normal file
@ -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
crates/hyperswitch_interfaces/src/configs.rs
Normal file
132
crates/hyperswitch_interfaces/src/configs.rs
Normal file
@ -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,
|
||||
}
|
||||
149
crates/hyperswitch_interfaces/src/errors.rs
Normal file
149
crates/hyperswitch_interfaces/src/errors.rs
Normal file
@ -0,0 +1,149 @@
|
||||
//! Errors interface
|
||||
|
||||
use common_utils::errors::ErrorSwitch;
|
||||
use hyperswitch_domain_models::errors::api_error_response::ApiErrorResponse;
|
||||
|
||||
/// Connector Errors
|
||||
#[allow(missing_docs, missing_debug_implementations)]
|
||||
#[derive(Debug, thiserror::Error, PartialEq)]
|
||||
pub enum ConnectorError {
|
||||
#[error("Error while obtaining URL for the integration")]
|
||||
FailedToObtainIntegrationUrl,
|
||||
#[error("Failed to encode connector request")]
|
||||
RequestEncodingFailed,
|
||||
#[error("Request encoding failed : {0}")]
|
||||
RequestEncodingFailedWithReason(String),
|
||||
#[error("Parsing failed")]
|
||||
ParsingFailed,
|
||||
#[error("Failed to deserialize connector response")]
|
||||
ResponseDeserializationFailed,
|
||||
#[error("Failed to execute a processing step: {0:?}")]
|
||||
ProcessingStepFailed(Option<bytes::Bytes>),
|
||||
#[error("The connector returned an unexpected response: {0:?}")]
|
||||
UnexpectedResponseError(bytes::Bytes),
|
||||
#[error("Failed to parse custom routing rules from merchant account")]
|
||||
RoutingRulesParsingError,
|
||||
#[error("Failed to obtain preferred connector from merchant account")]
|
||||
FailedToObtainPreferredConnector,
|
||||
#[error("An invalid connector name was provided")]
|
||||
InvalidConnectorName,
|
||||
#[error("An invalid Wallet was used")]
|
||||
InvalidWallet,
|
||||
#[error("Failed to handle connector response")]
|
||||
ResponseHandlingFailed,
|
||||
#[error("Missing required field: {field_name}")]
|
||||
MissingRequiredField { field_name: &'static str },
|
||||
#[error("Missing required fields: {field_names:?}")]
|
||||
MissingRequiredFields { field_names: Vec<&'static str> },
|
||||
#[error("Failed to obtain authentication type")]
|
||||
FailedToObtainAuthType,
|
||||
#[error("Failed to obtain certificate")]
|
||||
FailedToObtainCertificate,
|
||||
#[error("Connector meta data not found")]
|
||||
NoConnectorMetaData,
|
||||
#[error("Failed to obtain certificate key")]
|
||||
FailedToObtainCertificateKey,
|
||||
#[error("This step has not been implemented for: {0}")]
|
||||
NotImplemented(String),
|
||||
#[error("{message} is not supported by {connector}")]
|
||||
NotSupported {
|
||||
message: String,
|
||||
connector: &'static str,
|
||||
},
|
||||
#[error("{flow} flow not supported by {connector} connector")]
|
||||
FlowNotSupported { flow: String, connector: String },
|
||||
#[error("Capture method not supported")]
|
||||
CaptureMethodNotSupported,
|
||||
#[error("Missing connector mandate ID")]
|
||||
MissingConnectorMandateID,
|
||||
#[error("Missing connector transaction ID")]
|
||||
MissingConnectorTransactionID,
|
||||
#[error("Missing connector refund ID")]
|
||||
MissingConnectorRefundID,
|
||||
#[error("Missing apple pay tokenization data")]
|
||||
MissingApplePayTokenData,
|
||||
#[error("Webhooks not implemented for this connector")]
|
||||
WebhooksNotImplemented,
|
||||
#[error("Failed to decode webhook event body")]
|
||||
WebhookBodyDecodingFailed,
|
||||
#[error("Signature not found for incoming webhook")]
|
||||
WebhookSignatureNotFound,
|
||||
#[error("Failed to verify webhook source")]
|
||||
WebhookSourceVerificationFailed,
|
||||
#[error("Could not find merchant secret in DB for incoming webhook source verification")]
|
||||
WebhookVerificationSecretNotFound,
|
||||
#[error("Merchant secret found for incoming webhook source verification is invalid")]
|
||||
WebhookVerificationSecretInvalid,
|
||||
#[error("Incoming webhook object reference ID not found")]
|
||||
WebhookReferenceIdNotFound,
|
||||
#[error("Incoming webhook event type not found")]
|
||||
WebhookEventTypeNotFound,
|
||||
#[error("Incoming webhook event resource object not found")]
|
||||
WebhookResourceObjectNotFound,
|
||||
#[error("Could not respond to the incoming webhook event")]
|
||||
WebhookResponseEncodingFailed,
|
||||
#[error("Invalid Date/time format")]
|
||||
InvalidDateFormat,
|
||||
#[error("Date Formatting Failed")]
|
||||
DateFormattingFailed,
|
||||
#[error("Invalid Data format")]
|
||||
InvalidDataFormat { field_name: &'static str },
|
||||
#[error("Payment Method data / Payment Method Type / Payment Experience Mismatch ")]
|
||||
MismatchedPaymentData,
|
||||
#[error("Failed to parse {wallet_name} wallet token")]
|
||||
InvalidWalletToken { wallet_name: String },
|
||||
#[error("Missing Connector Related Transaction ID")]
|
||||
MissingConnectorRelatedTransactionID { id: String },
|
||||
#[error("File Validation failed")]
|
||||
FileValidationFailed { reason: String },
|
||||
#[error("Missing 3DS redirection payload: {field_name}")]
|
||||
MissingConnectorRedirectionPayload { field_name: &'static str },
|
||||
#[error("Failed at connector's end with code '{code}'")]
|
||||
FailedAtConnector { message: String, code: String },
|
||||
#[error("Payment Method Type not found")]
|
||||
MissingPaymentMethodType,
|
||||
#[error("Balance in the payment method is low")]
|
||||
InSufficientBalanceInPaymentMethod,
|
||||
#[error("Server responded with Request Timeout")]
|
||||
RequestTimeoutReceived,
|
||||
#[error("The given currency method is not configured with the given connector")]
|
||||
CurrencyNotSupported {
|
||||
message: String,
|
||||
connector: &'static str,
|
||||
},
|
||||
#[error("Invalid Configuration")]
|
||||
InvalidConnectorConfig { config: &'static str },
|
||||
#[error("Failed to convert amount to required type")]
|
||||
AmountConversionFailed,
|
||||
}
|
||||
|
||||
impl ConnectorError {
|
||||
/// fn is_connector_timeout
|
||||
pub fn is_connector_timeout(&self) -> bool {
|
||||
self == &Self::RequestTimeoutReceived
|
||||
}
|
||||
}
|
||||
|
||||
impl ErrorSwitch<ConnectorError> for common_utils::errors::ParsingError {
|
||||
fn switch(&self) -> ConnectorError {
|
||||
ConnectorError::ParsingFailed
|
||||
}
|
||||
}
|
||||
|
||||
impl ErrorSwitch<ApiErrorResponse> for ConnectorError {
|
||||
fn switch(&self) -> ApiErrorResponse {
|
||||
match self {
|
||||
Self::WebhookSourceVerificationFailed => ApiErrorResponse::WebhookAuthenticationFailed,
|
||||
Self::WebhookSignatureNotFound
|
||||
| Self::WebhookReferenceIdNotFound
|
||||
| Self::WebhookResourceObjectNotFound
|
||||
| Self::WebhookBodyDecodingFailed
|
||||
| Self::WebhooksNotImplemented => ApiErrorResponse::WebhookBadRequest,
|
||||
Self::WebhookEventTypeNotFound => ApiErrorResponse::WebhookUnprocessableEntity,
|
||||
Self::WebhookVerificationSecretInvalid => {
|
||||
ApiErrorResponse::WebhookInvalidMerchantSecret
|
||||
}
|
||||
_ => ApiErrorResponse::InternalServerError,
|
||||
}
|
||||
}
|
||||
}
|
||||
3
crates/hyperswitch_interfaces/src/events.rs
Normal file
3
crates/hyperswitch_interfaces/src/events.rs
Normal file
@ -0,0 +1,3 @@
|
||||
//! Events interface
|
||||
|
||||
pub mod connector_api_logs;
|
||||
@ -0,0 +1,96 @@
|
||||
//! Connector API logs interface
|
||||
|
||||
use common_utils::request::Method;
|
||||
use router_env::tracing_actix_web::RequestId;
|
||||
use serde::Serialize;
|
||||
use serde_json::json;
|
||||
use time::OffsetDateTime;
|
||||
|
||||
/// struct ConnectorEvent
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct ConnectorEvent {
|
||||
connector_name: String,
|
||||
flow: String,
|
||||
request: String,
|
||||
masked_response: Option<String>,
|
||||
error: Option<String>,
|
||||
url: String,
|
||||
method: String,
|
||||
payment_id: String,
|
||||
merchant_id: String,
|
||||
created_at: i128,
|
||||
/// Connector Event Request ID
|
||||
pub request_id: String,
|
||||
latency: u128,
|
||||
refund_id: Option<String>,
|
||||
dispute_id: Option<String>,
|
||||
status_code: u16,
|
||||
}
|
||||
|
||||
impl ConnectorEvent {
|
||||
/// fn new ConnectorEvent
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
connector_name: String,
|
||||
flow: &str,
|
||||
request: serde_json::Value,
|
||||
url: String,
|
||||
method: Method,
|
||||
payment_id: String,
|
||||
merchant_id: String,
|
||||
request_id: Option<&RequestId>,
|
||||
latency: u128,
|
||||
refund_id: Option<String>,
|
||||
dispute_id: Option<String>,
|
||||
status_code: u16,
|
||||
) -> Self {
|
||||
Self {
|
||||
connector_name,
|
||||
flow: flow
|
||||
.rsplit_once("::")
|
||||
.map(|(_, s)| s)
|
||||
.unwrap_or(flow)
|
||||
.to_string(),
|
||||
request: request.to_string(),
|
||||
masked_response: None,
|
||||
error: None,
|
||||
url,
|
||||
method: method.to_string(),
|
||||
payment_id,
|
||||
merchant_id,
|
||||
created_at: OffsetDateTime::now_utc().unix_timestamp_nanos() / 1_000_000,
|
||||
request_id: request_id
|
||||
.map(|i| i.as_hyphenated().to_string())
|
||||
.unwrap_or("NO_REQUEST_ID".to_string()),
|
||||
latency,
|
||||
refund_id,
|
||||
dispute_id,
|
||||
status_code,
|
||||
}
|
||||
}
|
||||
|
||||
/// fn set_response_body
|
||||
pub fn set_response_body<T: Serialize>(&mut self, response: &T) {
|
||||
match masking::masked_serialize(response) {
|
||||
Ok(masked) => {
|
||||
self.masked_response = Some(masked.to_string());
|
||||
}
|
||||
Err(er) => self.set_error(json!({"error": er.to_string()})),
|
||||
}
|
||||
}
|
||||
|
||||
/// fn set_error_response_body
|
||||
pub fn set_error_response_body<T: Serialize>(&mut self, response: &T) {
|
||||
match masking::masked_serialize(response) {
|
||||
Ok(masked) => {
|
||||
self.error = Some(masked.to_string());
|
||||
}
|
||||
Err(er) => self.set_error(json!({"error": er.to_string()})),
|
||||
}
|
||||
}
|
||||
|
||||
/// fn set_error
|
||||
pub fn set_error(&mut self, error: serde_json::Value) {
|
||||
self.error = Some(error.to_string());
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,11 @@
|
||||
//! Hyperswitch interface
|
||||
|
||||
#![warn(missing_docs, missing_debug_implementations)]
|
||||
|
||||
pub mod secrets_interface;
|
||||
|
||||
pub mod api;
|
||||
pub mod configs;
|
||||
pub mod encryption_interface;
|
||||
pub mod errors;
|
||||
pub mod events;
|
||||
pub mod metrics;
|
||||
pub mod secrets_interface;
|
||||
pub mod types;
|
||||
|
||||
16
crates/hyperswitch_interfaces/src/metrics.rs
Normal file
16
crates/hyperswitch_interfaces/src/metrics.rs
Normal file
@ -0,0 +1,16 @@
|
||||
//! Metrics interface
|
||||
|
||||
use router_env::{counter_metric, global_meter, metrics_context, opentelemetry};
|
||||
|
||||
metrics_context!(CONTEXT);
|
||||
global_meter!(GLOBAL_METER, "ROUTER_API");
|
||||
|
||||
counter_metric!(UNIMPLEMENTED_FLOW, GLOBAL_METER);
|
||||
|
||||
/// fn add attributes
|
||||
pub fn add_attributes<T: Into<opentelemetry::Value>>(
|
||||
key: &'static str,
|
||||
value: T,
|
||||
) -> opentelemetry::KeyValue {
|
||||
opentelemetry::KeyValue::new(key, value)
|
||||
}
|
||||
12
crates/hyperswitch_interfaces/src/types.rs
Normal file
12
crates/hyperswitch_interfaces/src/types.rs
Normal file
@ -0,0 +1,12 @@
|
||||
//! Types interface
|
||||
|
||||
/// struct Response
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Response {
|
||||
/// headers
|
||||
pub headers: Option<http::HeaderMap>,
|
||||
/// response
|
||||
pub response: bytes::Bytes,
|
||||
/// status code
|
||||
pub status_code: u16,
|
||||
}
|
||||
Reference in New Issue
Block a user