Skip to content

Commit

Permalink
refactor(connector): [Paypal] Add support for both BodyKey and Signat…
Browse files Browse the repository at this point in the history
…ureKey (#2633)

Co-authored-by: Mani Chandra Dulam <mani.dchandra@juspay.in>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Mani Chandra <84711804+ThisIsMani@users.noreply.github.com>
  • Loading branch information
4 people authored Nov 21, 2023
1 parent 938b63a commit d8fcd3c
Show file tree
Hide file tree
Showing 2 changed files with 325 additions and 56 deletions.
90 changes: 59 additions & 31 deletions crates/router/src/connector/paypal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ use base64::Engine;
use common_utils::ext_traits::ByteSliceExt;
use diesel_models::enums;
use error_stack::{IntoReport, ResultExt};
use masking::PeekInterface;
use masking::{ExposeInterface, PeekInterface, Secret};
use transformers as paypal;

use self::transformers::{PaypalAuthResponse, PaypalMeta, PaypalWebhookEventType};
use self::transformers::{auth_headers, PaypalAuthResponse, PaypalMeta, PaypalWebhookEventType};
use super::utils::PaymentsCompleteAuthorizeRequestData;
use crate::{
configs::settings,
Expand All @@ -31,7 +31,7 @@ use crate::{
self,
api::{self, CompleteAuthorize, ConnectorCommon, ConnectorCommonExt, VerifyWebhookSource},
transformers::ForeignFrom,
ErrorResponse, Response,
ConnectorAuthType, ErrorResponse, Response,
},
utils::{self, BytesExt},
};
Expand Down Expand Up @@ -110,8 +110,8 @@ where
.clone()
.ok_or(errors::ConnectorError::FailedToObtainAuthType)?;
let key = &req.attempt_id;

Ok(vec![
let auth = paypal::PaypalAuthType::try_from(&req.connector_auth_type)?;
let mut headers = vec![
(
headers::CONTENT_TYPE.to_string(),
self.get_content_type().to_string().into(),
Expand All @@ -121,17 +121,57 @@ where
format!("Bearer {}", access_token.token.peek()).into_masked(),
),
(
"Prefer".to_string(),
auth_headers::PREFER.to_string(),
"return=representation".to_string().into(),
),
(
"PayPal-Request-Id".to_string(),
auth_headers::PAYPAL_REQUEST_ID.to_string(),
key.to_string().into_masked(),
),
])
];
if let Ok(paypal::PaypalConnectorCredentials::PartnerIntegration(credentials)) =
auth.get_credentials()
{
let auth_assertion_header =
construct_auth_assertion_header(&credentials.payer_id, &credentials.client_id);
headers.extend(vec![
(
auth_headers::PAYPAL_AUTH_ASSERTION.to_string(),
auth_assertion_header.to_string().into_masked(),
),
(
auth_headers::PAYPAL_PARTNER_ATTRIBUTION_ID.to_string(),
"HyperSwitchPPCP_SP".to_string().into(),
),
])
} else {
headers.extend(vec![(
auth_headers::PAYPAL_PARTNER_ATTRIBUTION_ID.to_string(),
"HyperSwitchlegacy_Ecom".to_string().into(),
)])
}
Ok(headers)
}
}

fn construct_auth_assertion_header(
payer_id: &Secret<String>,
client_id: &Secret<String>,
) -> String {
let algorithm = consts::BASE64_ENGINE
.encode("{\"alg\":\"none\"}")
.to_string();
let merchant_credentials = format!(
"{{\"iss\":\"{}\",\"payer_id\":\"{}\"}}",
client_id.clone().expose(),
payer_id.clone().expose()
);
let encoded_credentials = consts::BASE64_ENGINE
.encode(merchant_credentials)
.to_string();
format!("{algorithm}.{encoded_credentials}.")
}

impl ConnectorCommon for Paypal {
fn id(&self) -> &'static str {
"paypal"
Expand All @@ -151,14 +191,14 @@ impl ConnectorCommon for Paypal {

fn get_auth_header(
&self,
auth_type: &types::ConnectorAuthType,
auth_type: &ConnectorAuthType,
) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
let auth: paypal::PaypalAuthType = auth_type
.try_into()
.change_context(errors::ConnectorError::FailedToObtainAuthType)?;
let auth = paypal::PaypalAuthType::try_from(auth_type)?;
let credentials = auth.get_credentials()?;

Ok(vec![(
headers::AUTHORIZATION.to_string(),
auth.api_key.into_masked(),
credentials.get_client_secret().into_masked(),
)])
}

Expand Down Expand Up @@ -260,15 +300,9 @@ impl ConnectorIntegration<api::AccessTokenAuth, types::AccessTokenRequestData, t
req: &types::RefreshTokenRouterData,
_connectors: &settings::Connectors,
) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
let auth: paypal::PaypalAuthType = (&req.connector_auth_type)
.try_into()
.change_context(errors::ConnectorError::FailedToObtainAuthType)?;

let auth_id = auth
.key1
.zip(auth.api_key)
.map(|(key1, api_key)| format!("{}:{}", key1, api_key));
let auth_val = format!("Basic {}", consts::BASE64_ENGINE.encode(auth_id.peek()));
let auth = paypal::PaypalAuthType::try_from(&req.connector_auth_type)?;
let credentials = auth.get_credentials()?;
let auth_val = credentials.generate_authorization_value();

Ok(vec![
(
Expand Down Expand Up @@ -998,15 +1032,9 @@ impl
>,
_connectors: &settings::Connectors,
) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
let auth: paypal::PaypalAuthType = (&req.connector_auth_type)
.try_into()
.change_context(errors::ConnectorError::FailedToObtainAuthType)?;

let auth_id = auth
.key1
.zip(auth.api_key)
.map(|(key1, api_key)| format!("{}:{}", key1, api_key));
let auth_val = format!("Basic {}", consts::BASE64_ENGINE.encode(auth_id.peek()));
let auth = paypal::PaypalAuthType::try_from(&req.connector_auth_type)?;
let credentials = auth.get_credentials()?;
let auth_val = credentials.generate_authorization_value();

Ok(vec![
(
Expand Down
Loading

0 comments on commit d8fcd3c

Please sign in to comment.