mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-30 01:27:31 +08:00
fix: certificate decode failed when creating the session token for applepay (#1385)
This commit is contained in:
@ -1711,6 +1711,12 @@ pub struct ApplepaySessionRequest {
|
|||||||
pub initiative_context: String,
|
pub initiative_context: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub struct ConnectorMetadata {
|
||||||
|
pub apple_pay: Option<ApplePayMetadata>,
|
||||||
|
pub google_pay: Option<GpayMetaData>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
pub struct ApplepaySessionTokenData {
|
pub struct ApplepaySessionTokenData {
|
||||||
#[serde(rename = "apple_pay")]
|
#[serde(rename = "apple_pay")]
|
||||||
|
|||||||
@ -380,6 +380,36 @@ fn get_business_details_wrapper(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn validate_certificate_in_mca_metadata(
|
||||||
|
connector_metadata: Secret<serde_json::Value>,
|
||||||
|
) -> RouterResult<()> {
|
||||||
|
let parsed_connector_metadata = connector_metadata
|
||||||
|
.parse_value::<api_models::payments::ConnectorMetadata>("ApplepaySessionTokenData")
|
||||||
|
.change_context(errors::ParsingError::StructParseFailure("Metadata"))
|
||||||
|
.change_context(errors::ApiErrorResponse::InvalidDataFormat {
|
||||||
|
field_name: "metadata".to_string(),
|
||||||
|
expected_format: "connector metadata".to_string(),
|
||||||
|
})?;
|
||||||
|
|
||||||
|
parsed_connector_metadata
|
||||||
|
.apple_pay
|
||||||
|
.map(|applepay_metadata| {
|
||||||
|
let api_models::payments::SessionTokenInfo {
|
||||||
|
certificate,
|
||||||
|
certificate_keys,
|
||||||
|
..
|
||||||
|
} = applepay_metadata.session_token_data;
|
||||||
|
helpers::create_identity_from_certificate_and_key(certificate, certificate_keys)
|
||||||
|
.change_context(errors::ApiErrorResponse::InvalidDataValue {
|
||||||
|
field_name: "certificate/certificate key",
|
||||||
|
})
|
||||||
|
.map(|_identity_result| ())
|
||||||
|
})
|
||||||
|
.transpose()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn create_payment_connector(
|
pub async fn create_payment_connector(
|
||||||
store: &dyn StorageInterface,
|
store: &dyn StorageInterface,
|
||||||
req: api::MerchantConnectorCreate,
|
req: api::MerchantConnectorCreate,
|
||||||
@ -390,6 +420,11 @@ pub async fn create_payment_connector(
|
|||||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||||
.attach_printable("Unable to get key from merchant key store")?;
|
.attach_printable("Unable to get key from merchant key store")?;
|
||||||
|
|
||||||
|
req.metadata
|
||||||
|
.clone()
|
||||||
|
.map(validate_certificate_in_mca_metadata)
|
||||||
|
.transpose()?;
|
||||||
|
|
||||||
let merchant_account = store
|
let merchant_account = store
|
||||||
.find_merchant_account_by_merchant_id(merchant_id)
|
.find_merchant_account_by_merchant_id(merchant_id)
|
||||||
.await
|
.await
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
use base64::Engine;
|
||||||
use common_utils::{
|
use common_utils::{
|
||||||
ext_traits::{AsyncExt, ByteSliceExt, ValueExt},
|
ext_traits::{AsyncExt, ByteSliceExt, ValueExt},
|
||||||
fp_utils, generate_id, pii,
|
fp_utils, generate_id, pii,
|
||||||
@ -46,6 +47,33 @@ use crate::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub fn create_identity_from_certificate_and_key(
|
||||||
|
encoded_certificate: String,
|
||||||
|
encoded_certificate_key: String,
|
||||||
|
) -> Result<reqwest::Identity, error_stack::Report<errors::ApiClientError>> {
|
||||||
|
let decoded_certificate = consts::BASE64_ENGINE
|
||||||
|
.decode(encoded_certificate)
|
||||||
|
.into_report()
|
||||||
|
.change_context(errors::ApiClientError::CertificateDecodeFailed)?;
|
||||||
|
|
||||||
|
let decoded_certificate_key = consts::BASE64_ENGINE
|
||||||
|
.decode(encoded_certificate_key)
|
||||||
|
.into_report()
|
||||||
|
.change_context(errors::ApiClientError::CertificateDecodeFailed)?;
|
||||||
|
|
||||||
|
let certificate = String::from_utf8(decoded_certificate)
|
||||||
|
.into_report()
|
||||||
|
.change_context(errors::ApiClientError::CertificateDecodeFailed)?;
|
||||||
|
|
||||||
|
let certificate_key = String::from_utf8(decoded_certificate_key)
|
||||||
|
.into_report()
|
||||||
|
.change_context(errors::ApiClientError::CertificateDecodeFailed)?;
|
||||||
|
|
||||||
|
reqwest::Identity::from_pkcs8_pem(certificate.as_bytes(), certificate_key.as_bytes())
|
||||||
|
.into_report()
|
||||||
|
.change_context(errors::ApiClientError::CertificateDecodeFailed)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn filter_mca_based_on_business_details(
|
pub fn filter_mca_based_on_business_details(
|
||||||
merchant_connector_accounts: Vec<domain::MerchantConnectorAccount>,
|
merchant_connector_accounts: Vec<domain::MerchantConnectorAccount>,
|
||||||
payment_intent: Option<&storage_models::payment_intent::PaymentIntent>,
|
payment_intent: Option<&storage_models::payment_intent::PaymentIntent>,
|
||||||
|
|||||||
@ -1,11 +1,12 @@
|
|||||||
use base64::Engine;
|
|
||||||
use error_stack::{IntoReport, ResultExt};
|
use error_stack::{IntoReport, ResultExt};
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
configs::settings::{Locker, Proxy},
|
configs::settings::{Locker, Proxy},
|
||||||
consts,
|
core::{
|
||||||
core::errors::{self, CustomResult},
|
errors::{self, CustomResult},
|
||||||
|
payments,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static NON_PROXIED_CLIENT: OnceCell<reqwest::Client> = OnceCell::new();
|
static NON_PROXIED_CLIENT: OnceCell<reqwest::Client> = OnceCell::new();
|
||||||
@ -74,30 +75,13 @@ pub(super) fn create_client(
|
|||||||
client_certificate_key: Option<String>,
|
client_certificate_key: Option<String>,
|
||||||
) -> CustomResult<reqwest::Client, errors::ApiClientError> {
|
) -> CustomResult<reqwest::Client, errors::ApiClientError> {
|
||||||
match (client_certificate, client_certificate_key) {
|
match (client_certificate, client_certificate_key) {
|
||||||
(Some(encoded_cert), Some(encoded_cert_key)) => {
|
(Some(encoded_certificate), Some(encoded_certificate_key)) => {
|
||||||
let client_builder = get_client_builder(proxy_config, should_bypass_proxy)?;
|
let client_builder = get_client_builder(proxy_config, should_bypass_proxy)?;
|
||||||
|
|
||||||
let decoded_cert = consts::BASE64_ENGINE
|
let identity = payments::helpers::create_identity_from_certificate_and_key(
|
||||||
.decode(encoded_cert)
|
encoded_certificate,
|
||||||
.into_report()
|
encoded_certificate_key,
|
||||||
.change_context(errors::ApiClientError::CertificateDecodeFailed)?;
|
)?;
|
||||||
let decoded_cert_key = consts::BASE64_ENGINE
|
|
||||||
.decode(encoded_cert_key)
|
|
||||||
.into_report()
|
|
||||||
.change_context(errors::ApiClientError::CertificateDecodeFailed)?;
|
|
||||||
|
|
||||||
let certificate = String::from_utf8(decoded_cert)
|
|
||||||
.into_report()
|
|
||||||
.change_context(errors::ApiClientError::CertificateDecodeFailed)?;
|
|
||||||
let certificate_key = String::from_utf8(decoded_cert_key)
|
|
||||||
.into_report()
|
|
||||||
.change_context(errors::ApiClientError::CertificateDecodeFailed)?;
|
|
||||||
let identity = reqwest::Identity::from_pkcs8_pem(
|
|
||||||
certificate.as_bytes(),
|
|
||||||
certificate_key.as_bytes(),
|
|
||||||
)
|
|
||||||
.into_report()
|
|
||||||
.change_context(errors::ApiClientError::CertificateDecodeFailed)?;
|
|
||||||
|
|
||||||
client_builder
|
client_builder
|
||||||
.identity(identity)
|
.identity(identity)
|
||||||
|
|||||||
Reference in New Issue
Block a user