mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-28 04:04:55 +08:00
refactor(connector): [CRYPTOPAY] amount conversion framework added (#4928)
Co-authored-by: Sahkal Poddar <sahkal.poddar@juspay.in> Co-authored-by: Deepanshu Bansal <deepanshu.bansal@Deepanshu-Bansal-K3PYF02LFW.local>
This commit is contained in:
@ -1,13 +1,12 @@
|
||||
pub mod transformers;
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
use base64::Engine;
|
||||
use common_utils::{
|
||||
crypto::{self, GenerateDigest, SignMessage},
|
||||
date_time,
|
||||
ext_traits::ByteSliceExt,
|
||||
request::RequestContent,
|
||||
types::{AmountConvertor, StringMajorUnit, StringMajorUnitForConnector},
|
||||
};
|
||||
use error_stack::ResultExt;
|
||||
use hex::encode;
|
||||
@ -36,8 +35,18 @@ use crate::{
|
||||
utils::BytesExt,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Cryptopay;
|
||||
#[derive(Clone)]
|
||||
pub struct Cryptopay {
|
||||
amount_converter: &'static (dyn AmountConvertor<Output = StringMajorUnit> + Sync),
|
||||
}
|
||||
|
||||
impl Cryptopay {
|
||||
pub fn new() -> &'static Self {
|
||||
&Self {
|
||||
amount_converter: &StringMajorUnitForConnector,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl api::Payment for Cryptopay {}
|
||||
impl api::PaymentSession for Cryptopay {}
|
||||
@ -123,7 +132,7 @@ where
|
||||
(headers::DATE.to_string(), date.into()),
|
||||
(
|
||||
headers::CONTENT_TYPE.to_string(),
|
||||
Self.get_content_type().to_string().into(),
|
||||
self.get_content_type().to_string().into(),
|
||||
),
|
||||
];
|
||||
Ok(headers)
|
||||
@ -244,12 +253,12 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
|
||||
req: &types::PaymentsAuthorizeRouterData,
|
||||
_connectors: &settings::Connectors,
|
||||
) -> CustomResult<RequestContent, errors::ConnectorError> {
|
||||
let connector_router_data = cryptopay::CryptopayRouterData::try_from((
|
||||
&self.get_currency_unit(),
|
||||
let amount = utils::convert_amount(
|
||||
self.amount_converter,
|
||||
req.request.minor_amount,
|
||||
req.request.currency,
|
||||
req.request.amount,
|
||||
req,
|
||||
))?;
|
||||
)?;
|
||||
let connector_router_data = cryptopay::CryptopayRouterData::from((amount, req));
|
||||
let connector_req = cryptopay::CryptopayPaymentsRequest::try_from(&connector_router_data)?;
|
||||
Ok(RequestContent::Json(Box::new(connector_req)))
|
||||
}
|
||||
@ -288,13 +297,21 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
|
||||
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
|
||||
event_builder.map(|i| i.set_response_body(&response));
|
||||
router_env::logger::info!(connector_response=?response);
|
||||
let capture_amount_in_minor_units = match response.data.price_amount {
|
||||
Some(ref amount) => Some(utils::convert_back(
|
||||
self.amount_converter,
|
||||
amount.clone(),
|
||||
data.request.currency,
|
||||
)?),
|
||||
None => None,
|
||||
};
|
||||
types::RouterData::foreign_try_from((
|
||||
types::ResponseRouterData {
|
||||
response,
|
||||
data: data.clone(),
|
||||
http_code: res.status_code,
|
||||
},
|
||||
data.request.currency,
|
||||
capture_amount_in_minor_units,
|
||||
))
|
||||
}
|
||||
|
||||
@ -375,13 +392,21 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe
|
||||
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
|
||||
event_builder.map(|i| i.set_response_body(&response));
|
||||
router_env::logger::info!(connector_response=?response);
|
||||
let capture_amount_in_minor_units = match response.data.price_amount {
|
||||
Some(ref amount) => Some(utils::convert_back(
|
||||
self.amount_converter,
|
||||
amount.clone(),
|
||||
data.request.currency,
|
||||
)?),
|
||||
None => None,
|
||||
};
|
||||
types::RouterData::foreign_try_from((
|
||||
types::ResponseRouterData {
|
||||
response,
|
||||
data: data.clone(),
|
||||
http_code: res.status_code,
|
||||
},
|
||||
data.request.currency,
|
||||
capture_amount_in_minor_units,
|
||||
))
|
||||
}
|
||||
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
use common_utils::pii;
|
||||
use error_stack::ResultExt;
|
||||
use common_utils::{
|
||||
pii,
|
||||
types::{MinorUnit, StringMajorUnit},
|
||||
};
|
||||
use masking::Secret;
|
||||
use reqwest::Url;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::utils as connector_utils;
|
||||
use crate::{
|
||||
connector::utils::{self, is_payment_failure, CryptoData, PaymentsAuthorizeRequestData},
|
||||
consts,
|
||||
@ -15,31 +16,22 @@ use crate::{
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct CryptopayRouterData<T> {
|
||||
pub amount: String,
|
||||
pub amount: StringMajorUnit,
|
||||
pub router_data: T,
|
||||
}
|
||||
|
||||
impl<T> TryFrom<(&types::api::CurrencyUnit, enums::Currency, i64, T)> for CryptopayRouterData<T> {
|
||||
type Error = error_stack::Report<errors::ConnectorError>;
|
||||
fn try_from(
|
||||
(currency_unit, currency, amount, item): (
|
||||
&types::api::CurrencyUnit,
|
||||
enums::Currency,
|
||||
i64,
|
||||
T,
|
||||
),
|
||||
) -> Result<Self, Self::Error> {
|
||||
let amount = utils::get_amount_as_string(currency_unit, amount, currency)?;
|
||||
Ok(Self {
|
||||
impl<T> From<(StringMajorUnit, T)> for CryptopayRouterData<T> {
|
||||
fn from((amount, item): (StringMajorUnit, T)) -> Self {
|
||||
Self {
|
||||
amount,
|
||||
router_data: item,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Serialize)]
|
||||
pub struct CryptopayPaymentsRequest {
|
||||
price_amount: String,
|
||||
price_amount: StringMajorUnit,
|
||||
price_currency: enums::Currency,
|
||||
pay_currency: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
@ -62,7 +54,7 @@ impl TryFrom<&CryptopayRouterData<&types::PaymentsAuthorizeRouterData>>
|
||||
domain::PaymentMethodData::Crypto(ref cryptodata) => {
|
||||
let pay_currency = cryptodata.get_pay_currency()?;
|
||||
Ok(Self {
|
||||
price_amount: item.amount.to_owned(),
|
||||
price_amount: item.amount.clone(),
|
||||
price_currency: item.router_data.request.currency,
|
||||
pay_currency,
|
||||
network: cryptodata.network.to_owned(),
|
||||
@ -140,20 +132,20 @@ impl From<CryptopayPaymentStatus> for enums::AttemptStatus {
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct CryptopayPaymentsResponse {
|
||||
data: CryptopayPaymentResponseData,
|
||||
pub data: CryptopayPaymentResponseData,
|
||||
}
|
||||
|
||||
impl<F, T>
|
||||
ForeignTryFrom<(
|
||||
types::ResponseRouterData<F, CryptopayPaymentsResponse, T, types::PaymentsResponseData>,
|
||||
diesel_models::enums::Currency,
|
||||
Option<MinorUnit>,
|
||||
)> for types::RouterData<F, T, types::PaymentsResponseData>
|
||||
{
|
||||
type Error = error_stack::Report<errors::ConnectorError>;
|
||||
fn foreign_try_from(
|
||||
(item, currency): (
|
||||
(item, amount_captured_in_minor_units): (
|
||||
types::ResponseRouterData<F, CryptopayPaymentsResponse, T, types::PaymentsResponseData>,
|
||||
diesel_models::enums::Currency,
|
||||
Option<MinorUnit>,
|
||||
),
|
||||
) -> Result<Self, Self::Error> {
|
||||
let status = enums::AttemptStatus::from(item.response.data.status.clone());
|
||||
@ -196,15 +188,9 @@ impl<F, T>
|
||||
charge_id: None,
|
||||
})
|
||||
};
|
||||
|
||||
match item.response.data.price_amount {
|
||||
Some(price_amount) => {
|
||||
let amount_captured = Some(
|
||||
connector_utils::to_currency_lower_unit(price_amount, currency)?
|
||||
.parse::<i64>()
|
||||
.change_context(errors::ConnectorError::ParsingFailed)?,
|
||||
);
|
||||
|
||||
match amount_captured_in_minor_units {
|
||||
Some(minor_amount) => {
|
||||
let amount_captured = Some(minor_amount.get_amount_as_i64());
|
||||
Ok(Self {
|
||||
status,
|
||||
response,
|
||||
@ -243,9 +229,9 @@ pub struct CryptopayPaymentResponseData {
|
||||
pub address: Option<Secret<String>>,
|
||||
pub network: Option<String>,
|
||||
pub uri: Option<String>,
|
||||
pub price_amount: Option<String>,
|
||||
pub price_amount: Option<StringMajorUnit>,
|
||||
pub price_currency: Option<String>,
|
||||
pub pay_amount: Option<String>,
|
||||
pub pay_amount: Option<StringMajorUnit>,
|
||||
pub pay_currency: Option<String>,
|
||||
pub fee: Option<String>,
|
||||
pub fee_currency: Option<String>,
|
||||
|
||||
@ -329,7 +329,7 @@ impl ConnectorData {
|
||||
enums::Connector::Cashtocode => Ok(Box::new(&connector::Cashtocode)),
|
||||
enums::Connector::Checkout => Ok(Box::new(&connector::Checkout)),
|
||||
enums::Connector::Coinbase => Ok(Box::new(&connector::Coinbase)),
|
||||
enums::Connector::Cryptopay => Ok(Box::new(&connector::Cryptopay)),
|
||||
enums::Connector::Cryptopay => Ok(Box::new(connector::Cryptopay::new())),
|
||||
enums::Connector::Cybersource => Ok(Box::new(&connector::Cybersource)),
|
||||
enums::Connector::Dlocal => Ok(Box::new(&connector::Dlocal)),
|
||||
#[cfg(feature = "dummy_connector")]
|
||||
|
||||
@ -13,7 +13,7 @@ impl utils::Connector for CryptopayTest {
|
||||
fn get_data(&self) -> api::ConnectorData {
|
||||
use router::connector::Cryptopay;
|
||||
api::ConnectorData {
|
||||
connector: Box::new(&Cryptopay),
|
||||
connector: Box::new(Cryptopay::new()),
|
||||
connector_name: types::Connector::Cryptopay,
|
||||
get_token: api::GetToken::Connector,
|
||||
merchant_connector_id: None,
|
||||
|
||||
Reference in New Issue
Block a user