mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-28 04:04:55 +08:00
refactor(connector): implement amount converter framework for coinbase, dummyconnector and gocardless (#8915)
This commit is contained in:
@ -1,13 +1,12 @@
|
|||||||
pub mod transformers;
|
pub mod transformers;
|
||||||
|
|
||||||
use std::fmt::Debug;
|
|
||||||
|
|
||||||
use common_enums::enums;
|
use common_enums::enums;
|
||||||
use common_utils::{
|
use common_utils::{
|
||||||
crypto,
|
crypto,
|
||||||
errors::CustomResult,
|
errors::CustomResult,
|
||||||
ext_traits::ByteSliceExt,
|
ext_traits::ByteSliceExt,
|
||||||
request::{Method, Request, RequestBuilder, RequestContent},
|
request::{Method, Request, RequestBuilder, RequestContent},
|
||||||
|
types::{AmountConvertor, StringMajorUnit, StringMajorUnitForConnector},
|
||||||
};
|
};
|
||||||
use error_stack::ResultExt;
|
use error_stack::ResultExt;
|
||||||
use hyperswitch_domain_models::{
|
use hyperswitch_domain_models::{
|
||||||
@ -47,10 +46,24 @@ use masking::Mask;
|
|||||||
use transformers as coinbase;
|
use transformers as coinbase;
|
||||||
|
|
||||||
use self::coinbase::CoinbaseWebhookDetails;
|
use self::coinbase::CoinbaseWebhookDetails;
|
||||||
use crate::{constants::headers, types::ResponseRouterData, utils};
|
use crate::{
|
||||||
|
constants::headers,
|
||||||
|
types::ResponseRouterData,
|
||||||
|
utils::{self, convert_amount},
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Coinbase;
|
pub struct Coinbase {
|
||||||
|
amount_convertor: &'static (dyn AmountConvertor<Output = StringMajorUnit> + Sync),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Coinbase {
|
||||||
|
pub fn new() -> &'static Self {
|
||||||
|
&Self {
|
||||||
|
amount_convertor: &StringMajorUnitForConnector,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl api::Payment for Coinbase {}
|
impl api::Payment for Coinbase {}
|
||||||
impl api::PaymentToken for Coinbase {}
|
impl api::PaymentToken for Coinbase {}
|
||||||
@ -197,7 +210,14 @@ impl ConnectorIntegration<Authorize, PaymentsAuthorizeData, PaymentsResponseData
|
|||||||
req: &PaymentsAuthorizeRouterData,
|
req: &PaymentsAuthorizeRouterData,
|
||||||
_connectors: &Connectors,
|
_connectors: &Connectors,
|
||||||
) -> CustomResult<RequestContent, errors::ConnectorError> {
|
) -> CustomResult<RequestContent, errors::ConnectorError> {
|
||||||
let connector_req = coinbase::CoinbasePaymentsRequest::try_from(req)?;
|
let amount = convert_amount(
|
||||||
|
self.amount_convertor,
|
||||||
|
req.request.minor_amount,
|
||||||
|
req.request.currency,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let connector_router_data = coinbase::CoinbaseRouterData::from((amount, req));
|
||||||
|
let connector_req = coinbase::CoinbasePaymentsRequest::try_from(&connector_router_data)?;
|
||||||
Ok(RequestContent::Json(Box::new(connector_req)))
|
Ok(RequestContent::Json(Box::new(connector_req)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use common_enums::enums;
|
use common_enums::enums;
|
||||||
use common_utils::{pii, request::Method};
|
use common_utils::{pii, request::Method, types::StringMajorUnit};
|
||||||
use error_stack::ResultExt;
|
use error_stack::ResultExt;
|
||||||
use hyperswitch_domain_models::{
|
use hyperswitch_domain_models::{
|
||||||
router_data::{ConnectorAuthType, RouterData},
|
router_data::{ConnectorAuthType, RouterData},
|
||||||
router_flow_types::refunds::{Execute, RSync},
|
router_flow_types::refunds::{Execute, RSync},
|
||||||
router_request_types::ResponseId,
|
router_request_types::ResponseId,
|
||||||
router_response_types::{PaymentsResponseData, RedirectForm},
|
router_response_types::{PaymentsResponseData, RedirectForm},
|
||||||
types,
|
types::{self, PaymentsAuthorizeRouterData},
|
||||||
};
|
};
|
||||||
use hyperswitch_interfaces::errors;
|
use hyperswitch_interfaces::errors;
|
||||||
use masking::Secret;
|
use masking::Secret;
|
||||||
@ -21,9 +21,24 @@ use crate::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
pub struct CoinbaseRouterData<T> {
|
||||||
|
amount: StringMajorUnit,
|
||||||
|
router_data: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> From<(StringMajorUnit, T)> for CoinbaseRouterData<T> {
|
||||||
|
fn from((amount, item): (StringMajorUnit, T)) -> Self {
|
||||||
|
Self {
|
||||||
|
amount,
|
||||||
|
router_data: item,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Eq, PartialEq, Serialize)]
|
#[derive(Debug, Default, Eq, PartialEq, Serialize)]
|
||||||
pub struct LocalPrice {
|
pub struct LocalPrice {
|
||||||
pub amount: String,
|
pub amount: StringMajorUnit,
|
||||||
pub currency: String,
|
pub currency: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,9 +58,11 @@ pub struct CoinbasePaymentsRequest {
|
|||||||
pub cancel_url: String,
|
pub cancel_url: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<&types::PaymentsAuthorizeRouterData> for CoinbasePaymentsRequest {
|
impl TryFrom<&CoinbaseRouterData<&PaymentsAuthorizeRouterData>> for CoinbasePaymentsRequest {
|
||||||
type Error = error_stack::Report<errors::ConnectorError>;
|
type Error = error_stack::Report<errors::ConnectorError>;
|
||||||
fn try_from(item: &types::PaymentsAuthorizeRouterData) -> Result<Self, Self::Error> {
|
fn try_from(
|
||||||
|
item: &CoinbaseRouterData<&PaymentsAuthorizeRouterData>,
|
||||||
|
) -> Result<Self, Self::Error> {
|
||||||
get_crypto_specific_payment_data(item)
|
get_crypto_specific_payment_data(item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -263,23 +280,24 @@ impl TryFrom<&Option<pii::SecretSerdeValue>> for CoinbaseConnectorMeta {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_crypto_specific_payment_data(
|
fn get_crypto_specific_payment_data(
|
||||||
item: &types::PaymentsAuthorizeRouterData,
|
item: &CoinbaseRouterData<&PaymentsAuthorizeRouterData>,
|
||||||
) -> Result<CoinbasePaymentsRequest, error_stack::Report<errors::ConnectorError>> {
|
) -> Result<CoinbasePaymentsRequest, error_stack::Report<errors::ConnectorError>> {
|
||||||
let billing_address = item
|
let billing_address = item
|
||||||
|
.router_data
|
||||||
.get_billing()
|
.get_billing()
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(|billing_address| billing_address.address.as_ref());
|
.and_then(|billing_address| billing_address.address.as_ref());
|
||||||
let name =
|
let name =
|
||||||
billing_address.and_then(|add| add.get_first_name().ok().map(|name| name.to_owned()));
|
billing_address.and_then(|add| add.get_first_name().ok().map(|name| name.to_owned()));
|
||||||
let description = item.get_description().ok();
|
let description = item.router_data.get_description().ok();
|
||||||
let connector_meta = CoinbaseConnectorMeta::try_from(&item.connector_meta_data)
|
let connector_meta = CoinbaseConnectorMeta::try_from(&item.router_data.connector_meta_data)
|
||||||
.change_context(errors::ConnectorError::InvalidConnectorConfig {
|
.change_context(errors::ConnectorError::InvalidConnectorConfig {
|
||||||
config: "Merchant connector account metadata",
|
config: "Merchant connector account metadata",
|
||||||
})?;
|
})?;
|
||||||
let pricing_type = connector_meta.pricing_type;
|
let pricing_type = connector_meta.pricing_type;
|
||||||
let local_price = get_local_price(item);
|
let local_price = get_local_price(item);
|
||||||
let redirect_url = item.request.get_router_return_url()?;
|
let redirect_url = item.router_data.request.get_router_return_url()?;
|
||||||
let cancel_url = item.request.get_router_return_url()?;
|
let cancel_url = item.router_data.request.get_router_return_url()?;
|
||||||
|
|
||||||
Ok(CoinbasePaymentsRequest {
|
Ok(CoinbasePaymentsRequest {
|
||||||
name,
|
name,
|
||||||
@ -291,10 +309,10 @@ fn get_crypto_specific_payment_data(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_local_price(item: &types::PaymentsAuthorizeRouterData) -> LocalPrice {
|
fn get_local_price(item: &CoinbaseRouterData<&PaymentsAuthorizeRouterData>) -> LocalPrice {
|
||||||
LocalPrice {
|
LocalPrice {
|
||||||
amount: format!("{:?}", item.request.amount),
|
amount: item.amount.clone(),
|
||||||
currency: item.request.currency.to_string(),
|
currency: item.router_data.request.currency.to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -333,36 +351,42 @@ pub enum WebhookEventType {
|
|||||||
Unknown,
|
Unknown,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Serialize, Deserialize)]
|
||||||
|
pub struct Redirects {
|
||||||
|
cancel_url: Option<String>,
|
||||||
|
success_url: Option<String>,
|
||||||
|
will_redirect_after_success: bool,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Serialize, Deserialize)]
|
#[derive(Debug, Default, Serialize, Deserialize)]
|
||||||
pub struct CoinbasePaymentResponseData {
|
pub struct CoinbasePaymentResponseData {
|
||||||
pub id: String,
|
pub id: String,
|
||||||
pub code: String,
|
pub code: String,
|
||||||
pub name: Option<Secret<String>>,
|
pub name: Option<Secret<String>>,
|
||||||
pub utxo: bool,
|
pub utxo: Option<bool>,
|
||||||
pub pricing: HashMap<String, OverpaymentAbsoluteThreshold>,
|
pub pricing: HashMap<String, OverpaymentAbsoluteThreshold>,
|
||||||
pub fee_rate: f64,
|
pub fee_rate: Option<f64>,
|
||||||
pub logo_url: String,
|
pub logo_url: Option<String>,
|
||||||
pub metadata: Option<Metadata>,
|
pub metadata: Option<Metadata>,
|
||||||
pub payments: Vec<PaymentElement>,
|
pub payments: Vec<PaymentElement>,
|
||||||
pub resource: String,
|
pub resource: Option<String>,
|
||||||
pub timeline: Vec<Timeline>,
|
pub timeline: Vec<Timeline>,
|
||||||
pub pwcb_only: bool,
|
pub pwcb_only: bool,
|
||||||
pub cancel_url: String,
|
|
||||||
pub created_at: String,
|
pub created_at: String,
|
||||||
pub expires_at: String,
|
pub expires_at: String,
|
||||||
pub hosted_url: String,
|
pub hosted_url: String,
|
||||||
pub brand_color: String,
|
pub brand_color: String,
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
pub confirmed_at: Option<String>,
|
pub confirmed_at: Option<String>,
|
||||||
pub fees_settled: bool,
|
pub fees_settled: Option<bool>,
|
||||||
pub pricing_type: String,
|
pub pricing_type: String,
|
||||||
pub redirect_url: String,
|
pub redirects: Redirects,
|
||||||
pub support_email: pii::Email,
|
pub support_email: pii::Email,
|
||||||
pub brand_logo_url: String,
|
pub brand_logo_url: String,
|
||||||
pub offchain_eligible: bool,
|
pub offchain_eligible: Option<bool>,
|
||||||
pub organization_name: String,
|
pub organization_name: String,
|
||||||
pub payment_threshold: PaymentThreshold,
|
pub payment_threshold: Option<PaymentThreshold>,
|
||||||
pub coinbase_managed_merchant: bool,
|
pub coinbase_managed_merchant: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Default, Deserialize)]
|
#[derive(Debug, Serialize, Default, Deserialize)]
|
||||||
@ -375,7 +399,7 @@ pub struct PaymentThreshold {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Default, Deserialize, PartialEq, Eq)]
|
#[derive(Debug, Clone, Serialize, Default, Deserialize, PartialEq, Eq)]
|
||||||
pub struct OverpaymentAbsoluteThreshold {
|
pub struct OverpaymentAbsoluteThreshold {
|
||||||
pub amount: String,
|
pub amount: StringMajorUnit,
|
||||||
pub currency: String,
|
pub currency: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
pub mod transformers;
|
pub mod transformers;
|
||||||
|
|
||||||
use std::fmt::Debug;
|
|
||||||
|
|
||||||
use api_models::webhooks::{IncomingWebhookEvent, ObjectReferenceId};
|
use api_models::webhooks::{IncomingWebhookEvent, ObjectReferenceId};
|
||||||
use common_enums::{CaptureMethod, PaymentMethod, PaymentMethodType};
|
use common_enums::{CaptureMethod, PaymentMethod, PaymentMethodType};
|
||||||
use common_utils::{
|
use common_utils::{
|
||||||
@ -9,6 +7,7 @@ use common_utils::{
|
|||||||
errors::CustomResult,
|
errors::CustomResult,
|
||||||
ext_traits::BytesExt,
|
ext_traits::BytesExt,
|
||||||
request::{Method, Request, RequestBuilder, RequestContent},
|
request::{Method, Request, RequestBuilder, RequestContent},
|
||||||
|
types::{AmountConvertor, MinorUnit, MinorUnitForConnector},
|
||||||
};
|
};
|
||||||
use error_stack::{report, ResultExt};
|
use error_stack::{report, ResultExt};
|
||||||
use hyperswitch_domain_models::{
|
use hyperswitch_domain_models::{
|
||||||
@ -45,15 +44,26 @@ use hyperswitch_interfaces::{
|
|||||||
webhooks::{IncomingWebhook, IncomingWebhookRequestDetails},
|
webhooks::{IncomingWebhook, IncomingWebhookRequestDetails},
|
||||||
};
|
};
|
||||||
use masking::{Mask as _, Maskable};
|
use masking::{Mask as _, Maskable};
|
||||||
|
use transformers as dummyconnector;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
constants::headers,
|
constants::headers,
|
||||||
types::ResponseRouterData,
|
types::ResponseRouterData,
|
||||||
utils::{construct_not_supported_error_report, RefundsRequestData as _},
|
utils::{construct_not_supported_error_report, convert_amount, RefundsRequestData as _},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Clone)]
|
||||||
pub struct DummyConnector<const T: u8>;
|
pub struct DummyConnector<const T: u8> {
|
||||||
|
amount_converter: &'static (dyn AmountConvertor<Output = MinorUnit> + Sync),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const T: u8> DummyConnector<T> {
|
||||||
|
pub fn new() -> &'static Self {
|
||||||
|
&Self {
|
||||||
|
amount_converter: &MinorUnitForConnector,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<const T: u8> Payment for DummyConnector<T> {}
|
impl<const T: u8> Payment for DummyConnector<T> {}
|
||||||
impl<const T: u8> PaymentSession for DummyConnector<T> {}
|
impl<const T: u8> PaymentSession for DummyConnector<T> {}
|
||||||
@ -237,7 +247,15 @@ impl<const T: u8> ConnectorIntegration<Authorize, PaymentsAuthorizeData, Payment
|
|||||||
req: &PaymentsAuthorizeRouterData,
|
req: &PaymentsAuthorizeRouterData,
|
||||||
_connectors: &Connectors,
|
_connectors: &Connectors,
|
||||||
) -> CustomResult<RequestContent, ConnectorError> {
|
) -> CustomResult<RequestContent, ConnectorError> {
|
||||||
let connector_req = transformers::DummyConnectorPaymentsRequest::<T>::try_from(req)?;
|
let amount = convert_amount(
|
||||||
|
self.amount_converter,
|
||||||
|
req.request.minor_amount,
|
||||||
|
req.request.currency,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let connector_router_data = dummyconnector::DummyConnectorRouterData::from((amount, req));
|
||||||
|
let connector_req =
|
||||||
|
transformers::DummyConnectorPaymentsRequest::<T>::try_from(&connector_router_data)?;
|
||||||
Ok(RequestContent::Json(Box::new(connector_req)))
|
Ok(RequestContent::Json(Box::new(connector_req)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -480,7 +498,15 @@ impl<const T: u8> ConnectorIntegration<Execute, RefundsData, RefundsResponseData
|
|||||||
req: &RefundsRouterData<Execute>,
|
req: &RefundsRouterData<Execute>,
|
||||||
_connectors: &Connectors,
|
_connectors: &Connectors,
|
||||||
) -> CustomResult<RequestContent, ConnectorError> {
|
) -> CustomResult<RequestContent, ConnectorError> {
|
||||||
let connector_req = transformers::DummyConnectorRefundRequest::try_from(req)?;
|
let amount = convert_amount(
|
||||||
|
self.amount_converter,
|
||||||
|
req.request.minor_refund_amount,
|
||||||
|
req.request.currency,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let connector_router_data = dummyconnector::DummyConnectorRouterData::from((amount, req));
|
||||||
|
let connector_req =
|
||||||
|
transformers::DummyConnectorRefundRequest::try_from(&connector_router_data)?;
|
||||||
Ok(RequestContent::Json(Box::new(connector_req)))
|
Ok(RequestContent::Json(Box::new(connector_req)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
use common_enums::{AttemptStatus, Currency, RefundStatus};
|
use common_enums::{AttemptStatus, Currency, RefundStatus};
|
||||||
use common_utils::{pii, request::Method};
|
use common_utils::{pii, request::Method, types::MinorUnit};
|
||||||
use hyperswitch_domain_models::{
|
use hyperswitch_domain_models::{
|
||||||
payment_method_data::{
|
payment_method_data::{
|
||||||
Card, PayLaterData, PaymentMethodData, UpiCollectData, UpiData, WalletData,
|
Card, PayLaterData, PaymentMethodData, UpiCollectData, UpiData, WalletData,
|
||||||
@ -20,6 +20,21 @@ use crate::{
|
|||||||
utils::RouterData as _,
|
utils::RouterData as _,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
pub struct DummyConnectorRouterData<T> {
|
||||||
|
pub amount: MinorUnit,
|
||||||
|
pub router_data: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> From<(MinorUnit, T)> for DummyConnectorRouterData<T> {
|
||||||
|
fn from((amount, router_data): (MinorUnit, T)) -> Self {
|
||||||
|
Self {
|
||||||
|
amount,
|
||||||
|
router_data,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, strum::Display, Eq, PartialEq)]
|
#[derive(Debug, Serialize, strum::Display, Eq, PartialEq)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
#[strum(serialize_all = "snake_case")]
|
#[strum(serialize_all = "snake_case")]
|
||||||
@ -70,7 +85,7 @@ impl From<u8> for DummyConnectors {
|
|||||||
|
|
||||||
#[derive(Debug, Serialize, Eq, PartialEq)]
|
#[derive(Debug, Serialize, Eq, PartialEq)]
|
||||||
pub struct DummyConnectorPaymentsRequest<const T: u8> {
|
pub struct DummyConnectorPaymentsRequest<const T: u8> {
|
||||||
amount: i64,
|
amount: MinorUnit,
|
||||||
currency: Currency,
|
currency: Currency,
|
||||||
payment_method_data: DummyPaymentMethodData,
|
payment_method_data: DummyPaymentMethodData,
|
||||||
return_url: Option<String>,
|
return_url: Option<String>,
|
||||||
@ -176,13 +191,17 @@ impl TryFrom<PayLaterData> for DummyConnectorPayLater {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<const T: u8> TryFrom<&PaymentsAuthorizeRouterData> for DummyConnectorPaymentsRequest<T> {
|
impl<const T: u8> TryFrom<&DummyConnectorRouterData<&PaymentsAuthorizeRouterData>>
|
||||||
|
for DummyConnectorPaymentsRequest<T>
|
||||||
|
{
|
||||||
type Error = error_stack::Report<ConnectorError>;
|
type Error = error_stack::Report<ConnectorError>;
|
||||||
fn try_from(item: &PaymentsAuthorizeRouterData) -> Result<Self, Self::Error> {
|
fn try_from(
|
||||||
|
item: &DummyConnectorRouterData<&PaymentsAuthorizeRouterData>,
|
||||||
|
) -> Result<Self, Self::Error> {
|
||||||
let payment_method_data: Result<DummyPaymentMethodData, Self::Error> =
|
let payment_method_data: Result<DummyPaymentMethodData, Self::Error> =
|
||||||
match item.request.payment_method_data {
|
match item.router_data.request.payment_method_data {
|
||||||
PaymentMethodData::Card(ref req_card) => {
|
PaymentMethodData::Card(ref req_card) => {
|
||||||
let card_holder_name = item.get_optional_billing_full_name();
|
let card_holder_name = item.router_data.get_optional_billing_full_name();
|
||||||
Ok(DummyPaymentMethodData::Card(DummyConnectorCard::try_from(
|
Ok(DummyPaymentMethodData::Card(DummyConnectorCard::try_from(
|
||||||
(req_card.clone(), card_holder_name),
|
(req_card.clone(), card_holder_name),
|
||||||
)?))
|
)?))
|
||||||
@ -204,10 +223,10 @@ impl<const T: u8> TryFrom<&PaymentsAuthorizeRouterData> for DummyConnectorPaymen
|
|||||||
_ => Err(ConnectorError::NotImplemented("Payment methods".to_string()).into()),
|
_ => Err(ConnectorError::NotImplemented("Payment methods".to_string()).into()),
|
||||||
};
|
};
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
amount: item.request.amount,
|
amount: item.router_data.request.minor_amount,
|
||||||
currency: item.request.currency,
|
currency: item.router_data.request.currency,
|
||||||
payment_method_data: payment_method_data?,
|
payment_method_data: payment_method_data?,
|
||||||
return_url: item.request.router_return_url.clone(),
|
return_url: item.router_data.request.router_return_url.clone(),
|
||||||
connector: Into::<DummyConnectors>::into(T),
|
connector: Into::<DummyConnectors>::into(T),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -254,7 +273,7 @@ impl From<DummyConnectorPaymentStatus> for AttemptStatus {
|
|||||||
pub struct PaymentsResponse {
|
pub struct PaymentsResponse {
|
||||||
status: DummyConnectorPaymentStatus,
|
status: DummyConnectorPaymentStatus,
|
||||||
id: String,
|
id: String,
|
||||||
amount: i64,
|
amount: MinorUnit,
|
||||||
currency: Currency,
|
currency: Currency,
|
||||||
created: String,
|
created: String,
|
||||||
payment_method_type: PaymentMethodType,
|
payment_method_type: PaymentMethodType,
|
||||||
@ -322,14 +341,16 @@ impl DummyConnectorNextAction {
|
|||||||
// Type definition for RefundRequest
|
// Type definition for RefundRequest
|
||||||
#[derive(Default, Debug, Serialize)]
|
#[derive(Default, Debug, Serialize)]
|
||||||
pub struct DummyConnectorRefundRequest {
|
pub struct DummyConnectorRefundRequest {
|
||||||
pub amount: i64,
|
pub amount: MinorUnit,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F> TryFrom<&RefundsRouterData<F>> for DummyConnectorRefundRequest {
|
impl<F> TryFrom<&DummyConnectorRouterData<&RefundsRouterData<F>>> for DummyConnectorRefundRequest {
|
||||||
type Error = error_stack::Report<ConnectorError>;
|
type Error = error_stack::Report<ConnectorError>;
|
||||||
fn try_from(item: &RefundsRouterData<F>) -> Result<Self, Self::Error> {
|
fn try_from(
|
||||||
|
item: &DummyConnectorRouterData<&RefundsRouterData<F>>,
|
||||||
|
) -> Result<Self, Self::Error> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
amount: item.request.refund_amount,
|
amount: item.router_data.request.minor_refund_amount,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -363,8 +384,8 @@ pub struct RefundResponse {
|
|||||||
status: DummyRefundStatus,
|
status: DummyRefundStatus,
|
||||||
currency: Currency,
|
currency: Currency,
|
||||||
created: String,
|
created: String,
|
||||||
payment_amount: i64,
|
payment_amount: MinorUnit,
|
||||||
refund_amount: i64,
|
refund_amount: MinorUnit,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<RefundsResponseRouterData<Execute, RefundResponse>> for RefundsRouterData<Execute> {
|
impl TryFrom<RefundsResponseRouterData<Execute, RefundResponse>> for RefundsRouterData<Execute> {
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
pub mod transformers;
|
pub mod transformers;
|
||||||
|
|
||||||
use std::fmt::Debug;
|
|
||||||
|
|
||||||
use api_models::webhooks::{IncomingWebhookEvent, ObjectReferenceId};
|
use api_models::webhooks::{IncomingWebhookEvent, ObjectReferenceId};
|
||||||
use common_enums::enums;
|
use common_enums::enums;
|
||||||
use common_utils::{
|
use common_utils::{
|
||||||
@ -9,6 +7,7 @@ use common_utils::{
|
|||||||
errors::CustomResult,
|
errors::CustomResult,
|
||||||
ext_traits::{ByteSliceExt, BytesExt},
|
ext_traits::{ByteSliceExt, BytesExt},
|
||||||
request::{Method, Request, RequestBuilder, RequestContent},
|
request::{Method, Request, RequestBuilder, RequestContent},
|
||||||
|
types::{AmountConvertor, MinorUnit, MinorUnitForConnector},
|
||||||
};
|
};
|
||||||
use error_stack::ResultExt;
|
use error_stack::ResultExt;
|
||||||
use hyperswitch_domain_models::{
|
use hyperswitch_domain_models::{
|
||||||
@ -52,11 +51,21 @@ use transformers as gocardless;
|
|||||||
use crate::{
|
use crate::{
|
||||||
constants::headers,
|
constants::headers,
|
||||||
types::ResponseRouterData,
|
types::ResponseRouterData,
|
||||||
utils::{is_mandate_supported, PaymentMethodDataType},
|
utils::{self, is_mandate_supported, PaymentMethodDataType},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Gocardless;
|
pub struct Gocardless {
|
||||||
|
amount_converter: &'static (dyn AmountConvertor<Output = MinorUnit> + Sync),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Gocardless {
|
||||||
|
pub fn new() -> &'static Self {
|
||||||
|
&Self {
|
||||||
|
amount_converter: &MinorUnitForConnector,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl api::Payment for Gocardless {}
|
impl api::Payment for Gocardless {}
|
||||||
impl api::PaymentSession for Gocardless {}
|
impl api::PaymentSession for Gocardless {}
|
||||||
@ -471,12 +480,13 @@ impl ConnectorIntegration<Authorize, PaymentsAuthorizeData, PaymentsResponseData
|
|||||||
req: &PaymentsAuthorizeRouterData,
|
req: &PaymentsAuthorizeRouterData,
|
||||||
_connectors: &Connectors,
|
_connectors: &Connectors,
|
||||||
) -> CustomResult<RequestContent, errors::ConnectorError> {
|
) -> CustomResult<RequestContent, errors::ConnectorError> {
|
||||||
let connector_router_data = gocardless::GocardlessRouterData::try_from((
|
let amount = utils::convert_amount(
|
||||||
&self.get_currency_unit(),
|
self.amount_converter,
|
||||||
|
req.request.minor_amount,
|
||||||
req.request.currency,
|
req.request.currency,
|
||||||
req.request.amount,
|
)?;
|
||||||
req,
|
|
||||||
))?;
|
let connector_router_data = gocardless::GocardlessRouterData::from((amount, req));
|
||||||
let connector_req =
|
let connector_req =
|
||||||
gocardless::GocardlessPaymentsRequest::try_from(&connector_router_data)?;
|
gocardless::GocardlessPaymentsRequest::try_from(&connector_router_data)?;
|
||||||
Ok(RequestContent::Json(Box::new(connector_req)))
|
Ok(RequestContent::Json(Box::new(connector_req)))
|
||||||
@ -637,12 +647,14 @@ impl ConnectorIntegration<Execute, RefundsData, RefundsResponseData> for Gocardl
|
|||||||
req: &RefundsRouterData<Execute>,
|
req: &RefundsRouterData<Execute>,
|
||||||
_connectors: &Connectors,
|
_connectors: &Connectors,
|
||||||
) -> CustomResult<RequestContent, errors::ConnectorError> {
|
) -> CustomResult<RequestContent, errors::ConnectorError> {
|
||||||
let connector_router_data = gocardless::GocardlessRouterData::try_from((
|
let refund_amount = utils::convert_amount(
|
||||||
&self.get_currency_unit(),
|
self.amount_converter,
|
||||||
|
req.request.minor_refund_amount,
|
||||||
req.request.currency,
|
req.request.currency,
|
||||||
req.request.refund_amount,
|
)?;
|
||||||
req,
|
|
||||||
))?;
|
let connector_router_data = gocardless::GocardlessRouterData::from((refund_amount, req));
|
||||||
|
|
||||||
let connector_req = gocardless::GocardlessRefundRequest::try_from(&connector_router_data)?;
|
let connector_req = gocardless::GocardlessRefundRequest::try_from(&connector_router_data)?;
|
||||||
Ok(RequestContent::Json(Box::new(connector_req)))
|
Ok(RequestContent::Json(Box::new(connector_req)))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ use common_enums::{enums, CountryAlpha2, UsStatesAbbreviation};
|
|||||||
use common_utils::{
|
use common_utils::{
|
||||||
id_type,
|
id_type,
|
||||||
pii::{self, IpAddress},
|
pii::{self, IpAddress},
|
||||||
|
types::MinorUnit,
|
||||||
};
|
};
|
||||||
use hyperswitch_domain_models::{
|
use hyperswitch_domain_models::{
|
||||||
address::AddressDetails,
|
address::AddressDetails,
|
||||||
@ -15,7 +16,7 @@ use hyperswitch_domain_models::{
|
|||||||
router_response_types::{MandateReference, PaymentsResponseData, RefundsResponseData},
|
router_response_types::{MandateReference, PaymentsResponseData, RefundsResponseData},
|
||||||
types,
|
types,
|
||||||
};
|
};
|
||||||
use hyperswitch_interfaces::{api, errors};
|
use hyperswitch_interfaces::errors;
|
||||||
use masking::{ExposeInterface, Secret};
|
use masking::{ExposeInterface, Secret};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
@ -28,19 +29,16 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub struct GocardlessRouterData<T> {
|
pub struct GocardlessRouterData<T> {
|
||||||
pub amount: i64, // The type of amount that a connector accepts, for example, String, i64, f64, etc.
|
pub amount: MinorUnit,
|
||||||
pub router_data: T,
|
pub router_data: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> TryFrom<(&api::CurrencyUnit, enums::Currency, i64, T)> for GocardlessRouterData<T> {
|
impl<T> From<(MinorUnit, T)> for GocardlessRouterData<T> {
|
||||||
type Error = error_stack::Report<errors::ConnectorError>;
|
fn from((amount, item): (MinorUnit, T)) -> Self {
|
||||||
fn try_from(
|
Self {
|
||||||
(_currency_unit, _currency, amount, item): (&api::CurrencyUnit, enums::Currency, i64, T),
|
|
||||||
) -> Result<Self, Self::Error> {
|
|
||||||
Ok(Self {
|
|
||||||
amount,
|
amount,
|
||||||
router_data: item,
|
router_data: item,
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -547,7 +545,7 @@ pub struct GocardlessPaymentsRequest {
|
|||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
pub struct GocardlessPayment {
|
pub struct GocardlessPayment {
|
||||||
amount: i64,
|
amount: MinorUnit,
|
||||||
currency: enums::Currency,
|
currency: enums::Currency,
|
||||||
description: Option<String>,
|
description: Option<String>,
|
||||||
metadata: PaymentMetaData,
|
metadata: PaymentMetaData,
|
||||||
@ -583,7 +581,7 @@ impl TryFrom<&GocardlessRouterData<&types::PaymentsAuthorizeRouterData>>
|
|||||||
.into())
|
.into())
|
||||||
}?;
|
}?;
|
||||||
let payments = GocardlessPayment {
|
let payments = GocardlessPayment {
|
||||||
amount: item.router_data.request.amount,
|
amount: item.router_data.request.minor_amount,
|
||||||
currency: item.router_data.request.currency,
|
currency: item.router_data.request.currency,
|
||||||
description: item.router_data.description.clone(),
|
description: item.router_data.description.clone(),
|
||||||
metadata: PaymentMetaData {
|
metadata: PaymentMetaData {
|
||||||
@ -733,7 +731,7 @@ pub struct GocardlessRefundRequest {
|
|||||||
|
|
||||||
#[derive(Default, Debug, Serialize)]
|
#[derive(Default, Debug, Serialize)]
|
||||||
pub struct GocardlessRefund {
|
pub struct GocardlessRefund {
|
||||||
amount: i64,
|
amount: MinorUnit,
|
||||||
metadata: RefundMetaData,
|
metadata: RefundMetaData,
|
||||||
links: RefundLink,
|
links: RefundLink,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -173,7 +173,7 @@ impl ConnectorData {
|
|||||||
Ok(ConnectorEnum::Old(Box::new(connector::Checkout::new())))
|
Ok(ConnectorEnum::Old(Box::new(connector::Checkout::new())))
|
||||||
}
|
}
|
||||||
enums::Connector::Coinbase => {
|
enums::Connector::Coinbase => {
|
||||||
Ok(ConnectorEnum::Old(Box::new(&connector::Coinbase)))
|
Ok(ConnectorEnum::Old(Box::new(connector::Coinbase::new())))
|
||||||
}
|
}
|
||||||
enums::Connector::Coingate => {
|
enums::Connector::Coingate => {
|
||||||
Ok(ConnectorEnum::Old(Box::new(connector::Coingate::new())))
|
Ok(ConnectorEnum::Old(Box::new(connector::Coingate::new())))
|
||||||
@ -207,35 +207,35 @@ impl ConnectorData {
|
|||||||
}
|
}
|
||||||
#[cfg(feature = "dummy_connector")]
|
#[cfg(feature = "dummy_connector")]
|
||||||
enums::Connector::DummyConnector1 => Ok(ConnectorEnum::Old(Box::new(
|
enums::Connector::DummyConnector1 => Ok(ConnectorEnum::Old(Box::new(
|
||||||
&connector::DummyConnector::<1>,
|
connector::DummyConnector::<1>::new(),
|
||||||
))),
|
))),
|
||||||
#[cfg(feature = "dummy_connector")]
|
#[cfg(feature = "dummy_connector")]
|
||||||
enums::Connector::DummyConnector2 => Ok(ConnectorEnum::Old(Box::new(
|
enums::Connector::DummyConnector2 => Ok(ConnectorEnum::Old(Box::new(
|
||||||
&connector::DummyConnector::<2>,
|
connector::DummyConnector::<2>::new(),
|
||||||
))),
|
))),
|
||||||
#[cfg(feature = "dummy_connector")]
|
#[cfg(feature = "dummy_connector")]
|
||||||
enums::Connector::DummyConnector3 => Ok(ConnectorEnum::Old(Box::new(
|
enums::Connector::DummyConnector3 => Ok(ConnectorEnum::Old(Box::new(
|
||||||
&connector::DummyConnector::<3>,
|
connector::DummyConnector::<3>::new(),
|
||||||
))),
|
))),
|
||||||
#[cfg(feature = "dummy_connector")]
|
#[cfg(feature = "dummy_connector")]
|
||||||
enums::Connector::DummyConnector4 => Ok(ConnectorEnum::Old(Box::new(
|
enums::Connector::DummyConnector4 => Ok(ConnectorEnum::Old(Box::new(
|
||||||
&connector::DummyConnector::<4>,
|
connector::DummyConnector::<4>::new(),
|
||||||
))),
|
))),
|
||||||
#[cfg(feature = "dummy_connector")]
|
#[cfg(feature = "dummy_connector")]
|
||||||
enums::Connector::DummyConnector5 => Ok(ConnectorEnum::Old(Box::new(
|
enums::Connector::DummyConnector5 => Ok(ConnectorEnum::Old(Box::new(
|
||||||
&connector::DummyConnector::<5>,
|
connector::DummyConnector::<5>::new(),
|
||||||
))),
|
))),
|
||||||
#[cfg(feature = "dummy_connector")]
|
#[cfg(feature = "dummy_connector")]
|
||||||
enums::Connector::DummyConnector6 => Ok(ConnectorEnum::Old(Box::new(
|
enums::Connector::DummyConnector6 => Ok(ConnectorEnum::Old(Box::new(
|
||||||
&connector::DummyConnector::<6>,
|
connector::DummyConnector::<6>::new(),
|
||||||
))),
|
))),
|
||||||
#[cfg(feature = "dummy_connector")]
|
#[cfg(feature = "dummy_connector")]
|
||||||
enums::Connector::DummyConnector7 => Ok(ConnectorEnum::Old(Box::new(
|
enums::Connector::DummyConnector7 => Ok(ConnectorEnum::Old(Box::new(
|
||||||
&connector::DummyConnector::<7>,
|
connector::DummyConnector::<7>::new(),
|
||||||
))),
|
))),
|
||||||
#[cfg(feature = "dummy_connector")]
|
#[cfg(feature = "dummy_connector")]
|
||||||
enums::Connector::DummyBillingConnector => Ok(ConnectorEnum::Old(Box::new(
|
enums::Connector::DummyBillingConnector => Ok(ConnectorEnum::Old(Box::new(
|
||||||
&connector::DummyConnector::<8>,
|
connector::DummyConnector::<8>::new(),
|
||||||
))),
|
))),
|
||||||
// enums::Connector::Dwolla => {
|
// enums::Connector::Dwolla => {
|
||||||
// Ok(ConnectorEnum::Old(Box::new(connector::Dwolla::new())))
|
// Ok(ConnectorEnum::Old(Box::new(connector::Dwolla::new())))
|
||||||
@ -272,7 +272,7 @@ impl ConnectorData {
|
|||||||
Ok(ConnectorEnum::Old(Box::new(connector::Globepay::new())))
|
Ok(ConnectorEnum::Old(Box::new(connector::Globepay::new())))
|
||||||
}
|
}
|
||||||
enums::Connector::Gocardless => {
|
enums::Connector::Gocardless => {
|
||||||
Ok(ConnectorEnum::Old(Box::new(&connector::Gocardless)))
|
Ok(ConnectorEnum::Old(Box::new(connector::Gocardless::new())))
|
||||||
}
|
}
|
||||||
enums::Connector::Hipay => {
|
enums::Connector::Hipay => {
|
||||||
Ok(ConnectorEnum::Old(Box::new(connector::Hipay::new())))
|
Ok(ConnectorEnum::Old(Box::new(connector::Hipay::new())))
|
||||||
|
|||||||
@ -15,7 +15,7 @@ impl utils::Connector for CoinbaseTest {
|
|||||||
fn get_data(&self) -> api::ConnectorData {
|
fn get_data(&self) -> api::ConnectorData {
|
||||||
use router::connector::Coinbase;
|
use router::connector::Coinbase;
|
||||||
utils::construct_connector_data_old(
|
utils::construct_connector_data_old(
|
||||||
Box::new(&Coinbase),
|
Box::new(Coinbase::new()),
|
||||||
types::Connector::Coinbase,
|
types::Connector::Coinbase,
|
||||||
api::GetToken::Connector,
|
api::GetToken::Connector,
|
||||||
None,
|
None,
|
||||||
|
|||||||
@ -14,7 +14,7 @@ impl utils::Connector for DummyConnectorTest {
|
|||||||
fn get_data(&self) -> types::api::ConnectorData {
|
fn get_data(&self) -> types::api::ConnectorData {
|
||||||
use router::connector::DummyConnector;
|
use router::connector::DummyConnector;
|
||||||
utils::construct_connector_data_old(
|
utils::construct_connector_data_old(
|
||||||
Box::new(&DummyConnector::<1>),
|
Box::new(DummyConnector::<1>::new()),
|
||||||
types::Connector::DummyConnector1,
|
types::Connector::DummyConnector1,
|
||||||
types::api::GetToken::Connector,
|
types::api::GetToken::Connector,
|
||||||
None,
|
None,
|
||||||
|
|||||||
@ -11,7 +11,7 @@ impl utils::Connector for GocardlessTest {
|
|||||||
fn get_data(&self) -> types::api::ConnectorData {
|
fn get_data(&self) -> types::api::ConnectorData {
|
||||||
use router::connector::Gocardless;
|
use router::connector::Gocardless;
|
||||||
utils::construct_connector_data_old(
|
utils::construct_connector_data_old(
|
||||||
Box::new(&Gocardless),
|
Box::new(Gocardless::new()),
|
||||||
types::Connector::Gocardless,
|
types::Connector::Gocardless,
|
||||||
types::api::GetToken::Connector,
|
types::api::GetToken::Connector,
|
||||||
None,
|
None,
|
||||||
|
|||||||
Reference in New Issue
Block a user