Skip to content

Commit

Permalink
Merge branch 'hotfix-2024.09.13.0' into stripe-customer-acceptance
Browse files Browse the repository at this point in the history
  • Loading branch information
AkshayaFoiger authored Sep 17, 2024
2 parents 232aea5 + 5e47f63 commit fdae79f
Show file tree
Hide file tree
Showing 9 changed files with 161 additions and 93 deletions.
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,22 @@ All notable changes to HyperSwitch will be documented here.

- - -

## 2024.09.13.0-hotfix2

### Refactors

- **core:** Update response for PaymentsDynamicTaxCalculationResponse ([#5910](https://github.com/juspay/hyperswitch/pull/5910)) ([`f462c73`](https://github.com/juspay/hyperswitch/commit/f462c7329982e6f8c1c266a6e19f33560fba6615))

- - -

## 2024.09.13.0-hotfix1

### Revert

- Feat(router): mask keys in connector_account_details for merchant_connector_response in mca retrieve flow ([#5890](https://github.com/juspay/hyperswitch/pull/5890)) ([`3e463bc`](https://github.com/juspay/hyperswitch/commit/3e463bcccfd5974efc82dde119c46016b2685691))

- - -

## 2024.09.13.0

### Features
Expand Down
28 changes: 27 additions & 1 deletion api-reference-v2/openapi_spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -6212,6 +6212,28 @@
"BRW"
]
},
"DisplayAmountOnSdk": {
"type": "object",
"required": [
"net_amount",
"order_tax_amount",
"shipping_cost"
],
"properties": {
"net_amount": {
"type": "string",
"description": "net amount = amount + order_tax_amount + shipping_cost"
},
"order_tax_amount": {
"type": "string",
"description": "order tax amount calculated by tax connectors"
},
"shipping_cost": {
"type": "string",
"description": "shipping cost for the order"
}
}
},
"DisputeResponse": {
"type": "object",
"required": [
Expand Down Expand Up @@ -13537,7 +13559,8 @@
"type": "object",
"required": [
"payment_id",
"net_amount"
"net_amount",
"display_amount"
],
"properties": {
"payment_id": {
Expand All @@ -13562,6 +13585,9 @@
}
],
"nullable": true
},
"display_amount": {
"$ref": "#/components/schemas/DisplayAmountOnSdk"
}
}
},
Expand Down
28 changes: 27 additions & 1 deletion api-reference/openapi_spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -9831,6 +9831,28 @@
"BRW"
]
},
"DisplayAmountOnSdk": {
"type": "object",
"required": [
"net_amount",
"order_tax_amount",
"shipping_cost"
],
"properties": {
"net_amount": {
"type": "string",
"description": "net amount = amount + order_tax_amount + shipping_cost"
},
"order_tax_amount": {
"type": "string",
"description": "order tax amount calculated by tax connectors"
},
"shipping_cost": {
"type": "string",
"description": "shipping cost for the order"
}
}
},
"DisputeResponse": {
"type": "object",
"required": [
Expand Down Expand Up @@ -17535,7 +17557,8 @@
"type": "object",
"required": [
"payment_id",
"net_amount"
"net_amount",
"display_amount"
],
"properties": {
"payment_id": {
Expand All @@ -17560,6 +17583,9 @@
}
],
"nullable": true
},
"display_amount": {
"$ref": "#/components/schemas/DisplayAmountOnSdk"
}
}
},
Expand Down
15 changes: 15 additions & 0 deletions crates/api_models/src/payments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4619,6 +4619,21 @@ pub struct PaymentsDynamicTaxCalculationResponse {
pub order_tax_amount: Option<MinorUnit>,
/// shipping cost for the order
pub shipping_cost: Option<MinorUnit>,
/// amount in Base Unit display format
pub display_amount: DisplayAmountOnSdk,
}

#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, ToSchema)]
pub struct DisplayAmountOnSdk {
/// net amount = amount + order_tax_amount + shipping_cost
#[schema(value_type = String)]
pub net_amount: StringMajorUnit,
/// order tax amount calculated by tax connectors
#[schema(value_type = String)]
pub order_tax_amount: Option<StringMajorUnit>,
/// shipping cost for the order
#[schema(value_type = String)]
pub shipping_cost: Option<StringMajorUnit>,
}

#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
Expand Down
70 changes: 1 addition & 69 deletions crates/hyperswitch_domain_models/src/router_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use common_utils::{
types::MinorUnit,
};
use error_stack::ResultExt;
use masking::{ExposeInterface, Secret};
use masking::Secret;

use crate::{payment_address::PaymentAddress, payment_method_data};

Expand Down Expand Up @@ -136,74 +136,6 @@ impl ConnectorAuthType {
"ConnectorAuthType",
))
}

// show only first and last two digits of the key and mask others with *
// mask the entire key if it's length is less than or equal to 4
fn mask_key(&self, key: String) -> Secret<String> {
let key_len = key.len();
let masked_key = if key_len <= 4 {
"*".repeat(key_len)
} else {
// Show the first two and last two characters, mask the rest with '*'
let mut masked_key = String::new();
let key_len = key.len();
// Iterate through characters by their index
for (index, character) in key.chars().enumerate() {
if index < 2 || index >= key_len - 2 {
masked_key.push(character); // Keep the first two and last two characters
} else {
masked_key.push('*'); // Mask the middle characters
}
}
masked_key
};
Secret::new(masked_key)
}

// Mask the keys in the auth_type
pub fn get_masked_keys(&self) -> Self {
match self {
Self::TemporaryAuth => Self::TemporaryAuth,
Self::NoKey => Self::NoKey,
Self::HeaderKey { api_key } => Self::HeaderKey {
api_key: self.mask_key(api_key.clone().expose()),
},
Self::BodyKey { api_key, key1 } => Self::BodyKey {
api_key: self.mask_key(api_key.clone().expose()),
key1: self.mask_key(key1.clone().expose()),
},
Self::SignatureKey {
api_key,
key1,
api_secret,
} => Self::SignatureKey {
api_key: self.mask_key(api_key.clone().expose()),
key1: self.mask_key(key1.clone().expose()),
api_secret: self.mask_key(api_secret.clone().expose()),
},
Self::MultiAuthKey {
api_key,
key1,
api_secret,
key2,
} => Self::MultiAuthKey {
api_key: self.mask_key(api_key.clone().expose()),
key1: self.mask_key(key1.clone().expose()),
api_secret: self.mask_key(api_secret.clone().expose()),
key2: self.mask_key(key2.clone().expose()),
},
Self::CurrencyAuthKey { auth_key_map } => Self::CurrencyAuthKey {
auth_key_map: auth_key_map.clone(),
},
Self::CertificateAuth {
certificate,
private_key,
} => Self::CertificateAuth {
certificate: self.mask_key(certificate.clone().expose()),
private_key: self.mask_key(private_key.clone().expose()),
},
}
}
}

#[derive(serde::Deserialize, serde::Serialize, Debug, Clone)]
Expand Down
1 change: 1 addition & 0 deletions crates/openapi/src/openapi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,7 @@ Never share your secret api keys. Keep them guarded and secure.
api_models::payments::additional_info::UpiCollectAdditionalData,
api_models::payments::PaymentsDynamicTaxCalculationRequest,
api_models::payments::PaymentsDynamicTaxCalculationResponse,
api_models::payments::DisplayAmountOnSdk,
)),
modifiers(&SecurityAddon)
)]
Expand Down
1 change: 1 addition & 0 deletions crates/openapi/src/openapi_v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,7 @@ Never share your secret api keys. Keep them guarded and secure.
api_models::payments::additional_info::UpiCollectAdditionalData,
api_models::payments::PaymentsDynamicTaxCalculationRequest,
api_models::payments::PaymentsDynamicTaxCalculationResponse,
api_models::payments::DisplayAmountOnSdk,
)),
modifiers(&SecurityAddon)
)]
Expand Down
71 changes: 69 additions & 2 deletions crates/router/src/core/payments/transformers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@ use api_models::payments::{
Address, CustomerDetails, CustomerDetailsResponse, FrmMessage, PaymentChargeRequest,
PaymentChargeResponse, RequestSurchargeDetails,
};
use common_enums::RequestIncrementalAuthorization;
use common_utils::{consts::X_HS_LATENCY, fp_utils, pii::Email, types::MinorUnit};
use common_enums::{Currency, RequestIncrementalAuthorization};
use common_utils::{
consts::X_HS_LATENCY,
fp_utils,
pii::Email,
types::{AmountConvertor, MinorUnit, StringMajorUnitForConnector},
};
use diesel_models::ephemeral_key;
use error_stack::{report, ResultExt};
use hyperswitch_domain_models::{payments::payment_intent::CustomerData, router_request_types};
Expand Down Expand Up @@ -503,18 +508,80 @@ where
amount = amount + tax_amount;
}

let currency = payment_data
.get_payment_attempt()
.currency
.get_required_value("currency")?;

Ok(services::ApplicationResponse::JsonWithHeaders((
Self {
net_amount: amount,
payment_id: payment_data.get_payment_attempt().payment_id.clone(),
order_tax_amount,
shipping_cost,
display_amount: api_models::payments::DisplayAmountOnSdk::foreign_try_from((
amount,
shipping_cost,
order_tax_amount,
currency,
))?,
},
vec![],
)))
}
}

impl ForeignTryFrom<(MinorUnit, Option<MinorUnit>, Option<MinorUnit>, Currency)>
for api_models::payments::DisplayAmountOnSdk
{
type Error = error_stack::Report<errors::ApiErrorResponse>;

fn foreign_try_from(
(net_amount, shipping_cost, order_tax_amount, currency): (
MinorUnit,
Option<MinorUnit>,
Option<MinorUnit>,
Currency,
),
) -> Result<Self, Self::Error> {
let major_unit_convertor = StringMajorUnitForConnector;

let sdk_net_amount = major_unit_convertor
.convert(net_amount, currency)
.change_context(errors::ApiErrorResponse::PreconditionFailed {
message: "Failed to convert net_amount to base unit".to_string(),
})
.attach_printable("Failed to convert net_amount to string major unit")?;

let sdk_shipping_cost = shipping_cost
.map(|cost| {
major_unit_convertor
.convert(cost, currency)
.change_context(errors::ApiErrorResponse::PreconditionFailed {
message: "Failed to convert shipping_cost to base unit".to_string(),
})
.attach_printable("Failed to convert shipping_cost to string major unit")
})
.transpose()?;

let sdk_order_tax_amount = order_tax_amount
.map(|cost| {
major_unit_convertor
.convert(cost, currency)
.change_context(errors::ApiErrorResponse::PreconditionFailed {
message: "Failed to convert order_tax_amount to base unit".to_string(),
})
.attach_printable("Failed to convert order_tax_amount to string major unit")
})
.transpose()?;
Ok(Self {
net_amount: sdk_net_amount,
shipping_cost: sdk_shipping_cost,
order_tax_amount: sdk_order_tax_amount,
})
}
}

impl<F, Op, D> ToResponse<F, D, Op> for api::VerifyResponse
where
F: Clone,
Expand Down
24 changes: 4 additions & 20 deletions crates/router/src/types/transformers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ use api_models::{
use common_utils::{
consts::X_HS_LATENCY,
crypto::Encryptable,
ext_traits::{Encode, StringExt, ValueExt},
ext_traits::{StringExt, ValueExt},
fp_utils::when,
pii,
types::MinorUnit,
};
use diesel_models::enums as storage_enums;
use error_stack::{report, ResultExt};
use hyperswitch_domain_models::payments::payment_intent::CustomerData;
use masking::{ExposeInterface, PeekInterface, Secret};
use masking::{ExposeInterface, PeekInterface};

use super::domain;
use crate::{
Expand Down Expand Up @@ -1149,29 +1149,13 @@ impl ForeignTryFrom<domain::MerchantConnectorAccount>
}
None => None,
};
// parse the connector_account_details into ConnectorAuthType
let connector_account_details: hyperswitch_domain_models::router_data::ConnectorAuthType =
item.connector_account_details
.clone()
.into_inner()
.parse_value("ConnectorAuthType")
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed while parsing value for ConnectorAuthType")?;
// get the masked keys from the ConnectorAuthType and encode it to secret value
let masked_connector_account_details = Secret::new(
connector_account_details
.get_masked_keys()
.encode_to_value()
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed to encode ConnectorAuthType")?,
);
#[cfg(feature = "v2")]
let response = Self {
id: item.get_id(),
connector_type: item.connector_type,
connector_name: item.connector_name,
connector_label: item.connector_label,
connector_account_details: masked_connector_account_details,
connector_account_details: item.connector_account_details.into_inner(),
disabled: item.disabled,
payment_methods_enabled,
metadata: item.metadata,
Expand Down Expand Up @@ -1211,7 +1195,7 @@ impl ForeignTryFrom<domain::MerchantConnectorAccount>
connector_name: item.connector_name,
connector_label: item.connector_label,
merchant_connector_id: item.merchant_connector_id,
connector_account_details: masked_connector_account_details,
connector_account_details: item.connector_account_details.into_inner(),
test_mode: item.test_mode,
disabled: item.disabled,
payment_methods_enabled,
Expand Down

0 comments on commit fdae79f

Please sign in to comment.