WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
322 changes: 206 additions & 116 deletions crates/hyperswitch_connectors/src/connectors/paysafe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ use hyperswitch_domain_models::{
access_token_auth::AccessTokenAuth,
payments::{
Authorize, Capture, CompleteAuthorize, CreateConnectorCustomer, PSync,
PaymentMethodToken, PreProcessing, Session, SetupMandate, Void,
PaymentMethodToken, Session, SetupMandate, Void,
},
refunds::{Execute, RSync},
PreProcessing,
},
router_request_types::{
AccessTokenRequestData, CompleteAuthorizeData, ConnectorCustomerData,
Expand All @@ -37,7 +38,7 @@ use hyperswitch_domain_models::{
ConnectorCustomerRouterData, PaymentsAuthorizeRouterData, PaymentsCancelRouterData,
PaymentsCaptureRouterData, PaymentsCompleteAuthorizeRouterData,
PaymentsPreProcessingRouterData, PaymentsSyncRouterData, RefundSyncRouterData,
RefundsRouterData,
RefundsRouterData, TokenizationRouterData,
},
};
use hyperswitch_interfaces::{
Expand All @@ -48,7 +49,7 @@ use hyperswitch_interfaces::{
configs::Connectors,
errors,
events::connector_api_logs::ConnectorEvent,
types::{self, Response},
types::{self, Response, TokenizationType},
webhooks,
};
use masking::{Mask, PeekInterface};
Expand All @@ -58,8 +59,8 @@ use crate::{
constants::headers,
types::ResponseRouterData,
utils::{
self, PaymentMethodDataType, PaymentsAuthorizeRequestData,
PaymentsPreProcessingRequestData, PaymentsSyncRequestData,
self, PaymentMethodDataType, PaymentMethodTokenizationRequestData,
PaymentsAuthorizeRequestData, PaymentsPreProcessingRequestData, PaymentsSyncRequestData,
RefundsRequestData as OtherRefundsRequestData, RouterData as _,
},
};
Expand Down Expand Up @@ -90,10 +91,208 @@ impl api::RefundExecute for Paysafe {}
impl api::RefundSync for Paysafe {}
impl api::PaymentToken for Paysafe {}
impl api::ConnectorCustomer for Paysafe {}
impl api::PaymentsPreProcessing for Paysafe {}

impl ConnectorIntegration<PreProcessing, PaymentsPreProcessingData, PaymentsResponseData>
for Paysafe
{
fn get_headers(
&self,
req: &PaymentsPreProcessingRouterData,
connectors: &Connectors,
) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
self.build_headers(req, connectors)
}

fn get_content_type(&self) -> &'static str {
self.common_get_content_type()
}

fn get_url(
&self,
req: &PaymentsPreProcessingRouterData,
connectors: &Connectors,
) -> CustomResult<String, errors::ConnectorError> {
let base_url = self.base_url(connectors);
if req.request.is_customer_initiated_mandate_payment() {
let customer_id = req.get_connector_customer_id()?.to_string();
Ok(format!(
"{base_url}v1/customers/{customer_id}/paymenthandles"
))
} else {
Ok(format!("{}v1/paymenthandles", self.base_url(connectors)))
}
}

fn get_request_body(
&self,
req: &PaymentsPreProcessingRouterData,
_connectors: &Connectors,
) -> CustomResult<RequestContent, errors::ConnectorError> {
let minor_amount =
req.request
.minor_amount
.ok_or(errors::ConnectorError::MissingRequiredField {
field_name: "minor_amount",
})?;
let currency =
req.request
.currency
.ok_or(errors::ConnectorError::MissingRequiredField {
field_name: "currency",
})?;
let amount = utils::convert_amount(self.amount_converter, minor_amount, currency)?;

let connector_router_data = paysafe::PaysafeRouterData::from((amount, req));
let connector_req = paysafe::PaysafePaymentHandleRequest::try_from(&connector_router_data)?;
Ok(RequestContent::Json(Box::new(connector_req)))
}

fn build_request(
&self,
req: &PaymentsPreProcessingRouterData,
connectors: &Connectors,
) -> CustomResult<Option<Request>, errors::ConnectorError> {
Ok(Some(
RequestBuilder::new()
.method(Method::Post)
.url(&types::PaymentsPreProcessingType::get_url(
self, req, connectors,
)?)
.attach_default_headers()
.headers(types::PaymentsPreProcessingType::get_headers(
self, req, connectors,
)?)
.set_body(types::PaymentsPreProcessingType::get_request_body(
self, req, connectors,
)?)
.build(),
))
}

fn handle_response(
&self,
data: &PaymentsPreProcessingRouterData,
event_builder: Option<&mut ConnectorEvent>,
res: Response,
) -> CustomResult<PaymentsPreProcessingRouterData, errors::ConnectorError> {
let response: paysafe::PaysafePaymentHandleResponse = res
.response
.parse_struct("PaysafePaymentHandleResponse")
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;

event_builder.map(|i| i.set_response_body(&response));
router_env::logger::info!(connector_response=?response);

RouterData::try_from(ResponseRouterData {
response,
data: data.clone(),
http_code: res.status_code,
})
}

fn get_error_response(
&self,
res: Response,
event_builder: Option<&mut ConnectorEvent>,
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
self.build_error_response(res, event_builder)
}
}

impl ConnectorIntegration<PaymentMethodToken, PaymentMethodTokenizationData, PaymentsResponseData>
for Paysafe
{
fn get_headers(
&self,
req: &TokenizationRouterData,
connectors: &Connectors,
) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
self.build_headers(req, connectors)
}

fn get_content_type(&self) -> &'static str {
self.common_get_content_type()
}

fn get_url(
&self,
req: &TokenizationRouterData,
connectors: &Connectors,
) -> CustomResult<String, errors::ConnectorError> {
let base_url = self.base_url(connectors);
if req.request.is_customer_initiated_mandate_payment() {
let customer_id = req.get_connector_customer_id()?.to_string();
Ok(format!(
"{base_url}v1/customers/{customer_id}/paymenthandles"
))
} else {
Ok(format!("{}v1/paymenthandles", self.base_url(connectors)))
}
}

fn get_request_body(
&self,
req: &TokenizationRouterData,
_connectors: &Connectors,
) -> CustomResult<RequestContent, errors::ConnectorError> {
let amount_value =
req.request
.amount
.ok_or(errors::ConnectorError::MissingRequiredField {
field_name: "amount",
})?;
let amount = MinorUnit::new(amount_value);

let connector_router_data = paysafe::PaysafeRouterData::from((amount, req));
let connector_req = paysafe::PaysafePaymentHandleRequest::try_from(&connector_router_data)?;
Ok(RequestContent::Json(Box::new(connector_req)))
}

fn build_request(
&self,
req: &TokenizationRouterData,
connectors: &Connectors,
) -> CustomResult<Option<Request>, errors::ConnectorError> {
Ok(Some(
RequestBuilder::new()
.method(Method::Post)
.url(&TokenizationType::get_url(self, req, connectors)?)
.attach_default_headers()
.headers(TokenizationType::get_headers(self, req, connectors)?)
.set_body(TokenizationType::get_request_body(self, req, connectors)?)
.build(),
))
}

fn handle_response(
&self,
data: &TokenizationRouterData,
event_builder: Option<&mut ConnectorEvent>,
res: Response,
) -> CustomResult<TokenizationRouterData, errors::ConnectorError> {
let response: paysafe::PaysafePaymentHandleResponse = res
.response
.parse_struct("PaysafePaymentHandleResponse")
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;

event_builder.map(|i| i.set_response_body(&response));
router_env::logger::info!(connector_response=?response);

RouterData::try_from(ResponseRouterData {
response,
data: data.clone(),
http_code: res.status_code,
})
}

fn get_error_response(
&self,
res: Response,
event_builder: Option<&mut ConnectorEvent>,
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
self.build_error_response(res, event_builder)
}
}

impl<Flow, Request, Response> ConnectorCommonExt<Flow, Request, Response> for Paysafe
Expand Down Expand Up @@ -232,115 +431,6 @@ impl ConnectorIntegration<SetupMandate, SetupMandateRequestData, PaymentsRespons
}
}

impl api::PaymentsPreProcessing for Paysafe {}

impl ConnectorIntegration<PreProcessing, PaymentsPreProcessingData, PaymentsResponseData>
for Paysafe
{
fn get_headers(
&self,
req: &PaymentsPreProcessingRouterData,
connectors: &Connectors,
) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
self.build_headers(req, connectors)
}

fn get_content_type(&self) -> &'static str {
self.common_get_content_type()
}

fn get_url(
&self,
req: &PaymentsPreProcessingRouterData,
connectors: &Connectors,
) -> CustomResult<String, errors::ConnectorError> {
let base_url = self.base_url(connectors);
if req.request.is_customer_initiated_mandate_payment() {
let customer_id = req.get_connector_customer_id()?.to_string();
Ok(format!(
"{base_url}v1/customers/{customer_id}/paymenthandles"
))
} else {
Ok(format!("{}v1/paymenthandles", self.base_url(connectors)))
}
}

fn get_request_body(
&self,
req: &PaymentsPreProcessingRouterData,
_connectors: &Connectors,
) -> CustomResult<RequestContent, errors::ConnectorError> {
let minor_amount =
req.request
.minor_amount
.ok_or(errors::ConnectorError::MissingRequiredField {
field_name: "minor_amount",
})?;
let currency =
req.request
.currency
.ok_or(errors::ConnectorError::MissingRequiredField {
field_name: "currency",
})?;
let amount = utils::convert_amount(self.amount_converter, minor_amount, currency)?;

let connector_router_data = paysafe::PaysafeRouterData::from((amount, req));
let connector_req = paysafe::PaysafePaymentHandleRequest::try_from(&connector_router_data)?;
Ok(RequestContent::Json(Box::new(connector_req)))
}

fn build_request(
&self,
req: &PaymentsPreProcessingRouterData,
connectors: &Connectors,
) -> CustomResult<Option<Request>, errors::ConnectorError> {
Ok(Some(
RequestBuilder::new()
.method(Method::Post)
.url(&types::PaymentsPreProcessingType::get_url(
self, req, connectors,
)?)
.attach_default_headers()
.headers(types::PaymentsPreProcessingType::get_headers(
self, req, connectors,
)?)
.set_body(types::PaymentsPreProcessingType::get_request_body(
self, req, connectors,
)?)
.build(),
))
}

fn handle_response(
&self,
data: &PaymentsPreProcessingRouterData,
event_builder: Option<&mut ConnectorEvent>,
res: Response,
) -> CustomResult<PaymentsPreProcessingRouterData, errors::ConnectorError> {
let response: paysafe::PaysafePaymentHandleResponse = res
.response
.parse_struct("PaysafePaymentHandleResponse")
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;

event_builder.map(|i| i.set_response_body(&response));
router_env::logger::info!(connector_response=?response);

RouterData::try_from(ResponseRouterData {
response,
data: data.clone(),
http_code: res.status_code,
})
}

fn get_error_response(
&self,
res: Response,
event_builder: Option<&mut ConnectorEvent>,
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
self.build_error_response(res, event_builder)
}
}

impl ConnectorIntegration<CreateConnectorCustomer, ConnectorCustomerData, PaymentsResponseData>
for Paysafe
{
Expand Down Expand Up @@ -406,7 +496,7 @@ impl ConnectorIntegration<CreateConnectorCustomer, ConnectorCustomerData, Paymen
{
let response: paysafe::PaysafeCustomerResponse = res
.response
.parse_struct("Paysafe PaysafeCustomerResponse")
.parse_struct("PaysafeCustomerResponse")
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;

event_builder.map(|i| i.set_response_body(&response));
Expand Down Expand Up @@ -527,7 +617,7 @@ impl ConnectorIntegration<Authorize, PaymentsAuthorizeData, PaymentsResponseData
enums::PaymentMethod::Card if !data.is_three_ds() => {
let response: paysafe::PaysafePaymentsResponse = res
.response
.parse_struct("Paysafe PaymentsAuthorizeResponse")
.parse_struct("PaysafePaymentsAuthorizeResponse")
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
event_builder.map(|i| i.set_response_body(&response));
router_env::logger::info!(connector_response=?response);
Expand Down
Loading
Loading