mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-29 00:49:42 +08:00
refactor(connector): [Paypal] Add support for both BodyKey and SignatureKey (#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>
This commit is contained in:
@ -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,
|
||||
@ -31,7 +31,7 @@ use crate::{
|
||||
self,
|
||||
api::{self, CompleteAuthorize, ConnectorCommon, ConnectorCommonExt, VerifyWebhookSource},
|
||||
transformers::ForeignFrom,
|
||||
ErrorResponse, Response,
|
||||
ConnectorAuthType, ErrorResponse, Response,
|
||||
},
|
||||
utils::{self, BytesExt},
|
||||
};
|
||||
@ -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(),
|
||||
@ -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"
|
||||
@ -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(),
|
||||
)])
|
||||
}
|
||||
|
||||
@ -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![
|
||||
(
|
||||
@ -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![
|
||||
(
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
use api_models::{enums, payments::BankRedirectData};
|
||||
use base64::Engine;
|
||||
use common_utils::errors::CustomResult;
|
||||
use error_stack::{IntoReport, ResultExt};
|
||||
use masking::Secret;
|
||||
use masking::{ExposeInterface, Secret};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use time::PrimitiveDateTime;
|
||||
use url::Url;
|
||||
@ -11,10 +12,11 @@ use crate::{
|
||||
self, to_connector_meta, AccessTokenRequestInfo, AddressDetailsData,
|
||||
BankRedirectBillingData, CardData, PaymentsAuthorizeRequestData,
|
||||
},
|
||||
consts,
|
||||
core::errors,
|
||||
services,
|
||||
types::{
|
||||
self, api, storage::enums as storage_enums, transformers::ForeignFrom,
|
||||
self, api, storage::enums as storage_enums, transformers::ForeignFrom, ConnectorAuthType,
|
||||
VerifyWebhookSourceResponseData,
|
||||
},
|
||||
};
|
||||
@ -57,6 +59,12 @@ mod webhook_headers {
|
||||
pub const PAYPAL_CERT_URL: &str = "paypal-cert-url";
|
||||
pub const PAYPAL_AUTH_ALGO: &str = "paypal-auth-algo";
|
||||
}
|
||||
pub mod auth_headers {
|
||||
pub const PAYPAL_PARTNER_ATTRIBUTION_ID: &str = "PayPal-Partner-Attribution-Id";
|
||||
pub const PREFER: &str = "Prefer";
|
||||
pub const PAYPAL_REQUEST_ID: &str = "PayPal-Request-Id";
|
||||
pub const PAYPAL_AUTH_ASSERTION: &str = "PayPal-Auth-Assertion";
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
|
||||
#[serde(rename_all = "UPPERCASE")]
|
||||
@ -72,19 +80,111 @@ pub struct OrderAmount {
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Serialize, Deserialize, Eq, PartialEq)]
|
||||
pub struct OrderRequestAmount {
|
||||
pub currency_code: storage_enums::Currency,
|
||||
pub value: String,
|
||||
pub breakdown: AmountBreakdown,
|
||||
}
|
||||
|
||||
impl From<&PaypalRouterData<&types::PaymentsAuthorizeRouterData>> for OrderRequestAmount {
|
||||
fn from(item: &PaypalRouterData<&types::PaymentsAuthorizeRouterData>) -> Self {
|
||||
Self {
|
||||
currency_code: item.router_data.request.currency,
|
||||
value: item.amount.to_owned(),
|
||||
breakdown: AmountBreakdown {
|
||||
item_total: OrderAmount {
|
||||
currency_code: item.router_data.request.currency,
|
||||
value: item.amount.to_owned(),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Serialize, Deserialize, Eq, PartialEq)]
|
||||
pub struct AmountBreakdown {
|
||||
item_total: OrderAmount,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Serialize, Eq, PartialEq)]
|
||||
pub struct PurchaseUnitRequest {
|
||||
reference_id: Option<String>, //reference for an item in purchase_units
|
||||
invoice_id: Option<String>, //The API caller-provided external invoice number for this order. Appears in both the payer's transaction history and the emails that the payer receives.
|
||||
custom_id: Option<String>, //Used to reconcile client transactions with PayPal transactions.
|
||||
amount: OrderAmount,
|
||||
amount: OrderRequestAmount,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
payee: Option<Payee>,
|
||||
shipping: Option<ShippingAddress>,
|
||||
items: Vec<ItemDetails>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
#[derive(Default, Debug, Serialize, Eq, PartialEq)]
|
||||
pub struct Payee {
|
||||
merchant_id: Secret<String>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Serialize, Eq, PartialEq)]
|
||||
pub struct ItemDetails {
|
||||
name: String,
|
||||
quantity: u16,
|
||||
unit_amount: OrderAmount,
|
||||
}
|
||||
|
||||
impl From<&PaypalRouterData<&types::PaymentsAuthorizeRouterData>> for ItemDetails {
|
||||
fn from(item: &PaypalRouterData<&types::PaymentsAuthorizeRouterData>) -> Self {
|
||||
Self {
|
||||
name: format!(
|
||||
"Payment for invoice {}",
|
||||
item.router_data.connector_request_reference_id
|
||||
),
|
||||
quantity: 1,
|
||||
unit_amount: OrderAmount {
|
||||
currency_code: item.router_data.request.currency,
|
||||
value: item.amount.to_string(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Serialize, Eq, PartialEq)]
|
||||
pub struct Address {
|
||||
address_line_1: Option<Secret<String>>,
|
||||
postal_code: Option<Secret<String>>,
|
||||
country_code: api_models::enums::CountryAlpha2,
|
||||
admin_area_2: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Serialize, Eq, PartialEq)]
|
||||
pub struct ShippingAddress {
|
||||
address: Option<Address>,
|
||||
name: Option<ShippingName>,
|
||||
}
|
||||
|
||||
impl TryFrom<&PaypalRouterData<&types::PaymentsAuthorizeRouterData>> for ShippingAddress {
|
||||
type Error = error_stack::Report<errors::ConnectorError>;
|
||||
|
||||
fn try_from(
|
||||
item: &PaypalRouterData<&types::PaymentsAuthorizeRouterData>,
|
||||
) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
address: get_address_info(item.router_data.address.shipping.as_ref())?,
|
||||
name: Some(ShippingName {
|
||||
full_name: item
|
||||
.router_data
|
||||
.address
|
||||
.shipping
|
||||
.as_ref()
|
||||
.and_then(|inner_data| inner_data.address.as_ref())
|
||||
.and_then(|inner_data| inner_data.first_name.clone()),
|
||||
}),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Serialize, Eq, PartialEq)]
|
||||
pub struct ShippingName {
|
||||
full_name: Option<Secret<String>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
@ -124,6 +224,22 @@ pub struct RedirectRequest {
|
||||
pub struct ContextStruct {
|
||||
return_url: Option<String>,
|
||||
cancel_url: Option<String>,
|
||||
user_action: Option<UserAction>,
|
||||
shipping_preference: ShippingPreference,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum UserAction {
|
||||
#[serde(rename = "PAY_NOW")]
|
||||
PayNow,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum ShippingPreference {
|
||||
#[serde(rename = "SET_PROVIDED_ADDRESS")]
|
||||
SetProvidedAddress,
|
||||
#[serde(rename = "GET_FROM_FILE")]
|
||||
GetFromFile,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
@ -158,6 +274,7 @@ fn get_address_info(
|
||||
country_code: address.get_country()?.to_owned(),
|
||||
address_line_1: address.line1.clone(),
|
||||
postal_code: address.zip.clone(),
|
||||
admin_area_2: address.city.clone(),
|
||||
}),
|
||||
None => None,
|
||||
};
|
||||
@ -180,6 +297,12 @@ fn get_payment_source(
|
||||
experience_context: ContextStruct {
|
||||
return_url: item.request.complete_authorize_url.clone(),
|
||||
cancel_url: item.request.complete_authorize_url.clone(),
|
||||
shipping_preference: if item.address.shipping.is_some() {
|
||||
ShippingPreference::SetProvidedAddress
|
||||
} else {
|
||||
ShippingPreference::GetFromFile
|
||||
},
|
||||
user_action: Some(UserAction::PayNow),
|
||||
},
|
||||
})),
|
||||
BankRedirectData::Giropay {
|
||||
@ -194,6 +317,12 @@ fn get_payment_source(
|
||||
experience_context: ContextStruct {
|
||||
return_url: item.request.complete_authorize_url.clone(),
|
||||
cancel_url: item.request.complete_authorize_url.clone(),
|
||||
shipping_preference: if item.address.shipping.is_some() {
|
||||
ShippingPreference::SetProvidedAddress
|
||||
} else {
|
||||
ShippingPreference::GetFromFile
|
||||
},
|
||||
user_action: Some(UserAction::PayNow),
|
||||
},
|
||||
})),
|
||||
BankRedirectData::Ideal {
|
||||
@ -208,6 +337,12 @@ fn get_payment_source(
|
||||
experience_context: ContextStruct {
|
||||
return_url: item.request.complete_authorize_url.clone(),
|
||||
cancel_url: item.request.complete_authorize_url.clone(),
|
||||
shipping_preference: if item.address.shipping.is_some() {
|
||||
ShippingPreference::SetProvidedAddress
|
||||
} else {
|
||||
ShippingPreference::GetFromFile
|
||||
},
|
||||
user_action: Some(UserAction::PayNow),
|
||||
},
|
||||
})),
|
||||
BankRedirectData::Sofort {
|
||||
@ -220,6 +355,12 @@ fn get_payment_source(
|
||||
experience_context: ContextStruct {
|
||||
return_url: item.request.complete_authorize_url.clone(),
|
||||
cancel_url: item.request.complete_authorize_url.clone(),
|
||||
shipping_preference: if item.address.shipping.is_some() {
|
||||
ShippingPreference::SetProvidedAddress
|
||||
} else {
|
||||
ShippingPreference::GetFromFile
|
||||
},
|
||||
user_action: Some(UserAction::PayNow),
|
||||
},
|
||||
})),
|
||||
BankRedirectData::BancontactCard { .. }
|
||||
@ -247,11 +388,24 @@ fn get_payment_source(
|
||||
}
|
||||
}
|
||||
|
||||
fn get_payee(auth_type: &PaypalAuthType) -> Option<Payee> {
|
||||
auth_type
|
||||
.get_credentials()
|
||||
.ok()
|
||||
.and_then(|credentials| credentials.get_payer_id())
|
||||
.map(|payer_id| Payee {
|
||||
merchant_id: payer_id,
|
||||
})
|
||||
}
|
||||
|
||||
impl TryFrom<&PaypalRouterData<&types::PaymentsAuthorizeRouterData>> for PaypalPaymentsRequest {
|
||||
type Error = error_stack::Report<errors::ConnectorError>;
|
||||
fn try_from(
|
||||
item: &PaypalRouterData<&types::PaymentsAuthorizeRouterData>,
|
||||
) -> Result<Self, Self::Error> {
|
||||
let paypal_auth: PaypalAuthType =
|
||||
PaypalAuthType::try_from(&item.router_data.connector_auth_type)?;
|
||||
let payee = get_payee(&paypal_auth);
|
||||
match item.router_data.request.payment_method_data {
|
||||
api_models::payments::PaymentMethodData::Card(ref ccard) => {
|
||||
let intent = if item.router_data.request.is_auto_capture()? {
|
||||
@ -259,18 +413,20 @@ impl TryFrom<&PaypalRouterData<&types::PaymentsAuthorizeRouterData>> for PaypalP
|
||||
} else {
|
||||
PaypalPaymentIntent::Authorize
|
||||
};
|
||||
let amount = OrderAmount {
|
||||
currency_code: item.router_data.request.currency,
|
||||
value: item.amount.to_owned(),
|
||||
};
|
||||
let amount = OrderRequestAmount::from(item);
|
||||
let connector_request_reference_id =
|
||||
item.router_data.connector_request_reference_id.clone();
|
||||
let shipping_address = ShippingAddress::try_from(item)?;
|
||||
let item_details = vec![ItemDetails::from(item)];
|
||||
|
||||
let purchase_units = vec![PurchaseUnitRequest {
|
||||
reference_id: Some(connector_request_reference_id.clone()),
|
||||
custom_id: Some(connector_request_reference_id.clone()),
|
||||
invoice_id: Some(connector_request_reference_id),
|
||||
amount,
|
||||
payee,
|
||||
shipping: Some(shipping_address),
|
||||
items: item_details,
|
||||
}];
|
||||
let card = item.router_data.request.get_card()?;
|
||||
let expiry = Some(card.get_expiry_date_as_yyyymm("-"));
|
||||
@ -306,25 +462,29 @@ impl TryFrom<&PaypalRouterData<&types::PaymentsAuthorizeRouterData>> for PaypalP
|
||||
} else {
|
||||
PaypalPaymentIntent::Authorize
|
||||
};
|
||||
let amount = OrderAmount {
|
||||
currency_code: item.router_data.request.currency,
|
||||
value: item.amount.to_owned(),
|
||||
};
|
||||
let amount = OrderRequestAmount::from(item);
|
||||
|
||||
let connector_req_reference_id =
|
||||
item.router_data.connector_request_reference_id.clone();
|
||||
let shipping_address = ShippingAddress::try_from(item)?;
|
||||
let item_details = vec![ItemDetails::from(item)];
|
||||
|
||||
let purchase_units = vec![PurchaseUnitRequest {
|
||||
reference_id: Some(connector_req_reference_id.clone()),
|
||||
custom_id: Some(connector_req_reference_id.clone()),
|
||||
invoice_id: Some(connector_req_reference_id),
|
||||
amount,
|
||||
payee,
|
||||
shipping: Some(shipping_address),
|
||||
items: item_details,
|
||||
}];
|
||||
let payment_source =
|
||||
Some(PaymentSourceItem::Paypal(PaypalRedirectionRequest {
|
||||
experience_context: ContextStruct {
|
||||
return_url: item.router_data.request.complete_authorize_url.clone(),
|
||||
cancel_url: item.router_data.request.complete_authorize_url.clone(),
|
||||
shipping_preference: ShippingPreference::SetProvidedAddress,
|
||||
user_action: Some(UserAction::PayNow),
|
||||
},
|
||||
}));
|
||||
|
||||
@ -374,18 +534,20 @@ impl TryFrom<&PaypalRouterData<&types::PaymentsAuthorizeRouterData>> for PaypalP
|
||||
connector: "Paypal".to_string(),
|
||||
})?
|
||||
};
|
||||
let amount = OrderAmount {
|
||||
currency_code: item.router_data.request.currency,
|
||||
value: item.amount.to_owned(),
|
||||
};
|
||||
let amount = OrderRequestAmount::from(item);
|
||||
let connector_req_reference_id =
|
||||
item.router_data.connector_request_reference_id.clone();
|
||||
let shipping_address = ShippingAddress::try_from(item)?;
|
||||
let item_details = vec![ItemDetails::from(item)];
|
||||
|
||||
let purchase_units = vec![PurchaseUnitRequest {
|
||||
reference_id: Some(connector_req_reference_id.clone()),
|
||||
custom_id: Some(connector_req_reference_id.clone()),
|
||||
invoice_id: Some(connector_req_reference_id),
|
||||
amount,
|
||||
payee,
|
||||
shipping: Some(shipping_address),
|
||||
items: item_details,
|
||||
}];
|
||||
let payment_source =
|
||||
Some(get_payment_source(item.router_data, bank_redirection_data)?);
|
||||
@ -604,19 +766,98 @@ impl<F, T> TryFrom<types::ResponseRouterData<F, PaypalAuthUpdateResponse, T, typ
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PaypalAuthType {
|
||||
pub(super) api_key: Secret<String>,
|
||||
pub(super) key1: Secret<String>,
|
||||
pub enum PaypalAuthType {
|
||||
TemporaryAuth,
|
||||
AuthWithDetails(PaypalConnectorCredentials),
|
||||
}
|
||||
|
||||
impl TryFrom<&types::ConnectorAuthType> for PaypalAuthType {
|
||||
#[derive(Debug)]
|
||||
pub enum PaypalConnectorCredentials {
|
||||
StandardIntegration(StandardFlowCredentials),
|
||||
PartnerIntegration(PartnerFlowCredentials),
|
||||
}
|
||||
|
||||
impl PaypalConnectorCredentials {
|
||||
pub fn get_client_id(&self) -> Secret<String> {
|
||||
match self {
|
||||
Self::StandardIntegration(item) => item.client_id.clone(),
|
||||
Self::PartnerIntegration(item) => item.client_id.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_client_secret(&self) -> Secret<String> {
|
||||
match self {
|
||||
Self::StandardIntegration(item) => item.client_secret.clone(),
|
||||
Self::PartnerIntegration(item) => item.client_secret.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_payer_id(&self) -> Option<Secret<String>> {
|
||||
match self {
|
||||
Self::StandardIntegration(_) => None,
|
||||
Self::PartnerIntegration(item) => Some(item.payer_id.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_authorization_value(&self) -> String {
|
||||
let auth_id = format!(
|
||||
"{}:{}",
|
||||
self.get_client_id().expose(),
|
||||
self.get_client_secret().expose(),
|
||||
);
|
||||
format!("Basic {}", consts::BASE64_ENGINE.encode(auth_id))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct StandardFlowCredentials {
|
||||
pub(super) client_id: Secret<String>,
|
||||
pub(super) client_secret: Secret<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PartnerFlowCredentials {
|
||||
pub(super) client_id: Secret<String>,
|
||||
pub(super) client_secret: Secret<String>,
|
||||
pub(super) payer_id: Secret<String>,
|
||||
}
|
||||
|
||||
impl PaypalAuthType {
|
||||
pub fn get_credentials(
|
||||
&self,
|
||||
) -> CustomResult<&PaypalConnectorCredentials, errors::ConnectorError> {
|
||||
match self {
|
||||
Self::TemporaryAuth => Err(errors::ConnectorError::InvalidConnectorConfig {
|
||||
config: "TemporaryAuth found in connector_account_details",
|
||||
}
|
||||
.into()),
|
||||
Self::AuthWithDetails(credentials) => Ok(credentials),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&ConnectorAuthType> for PaypalAuthType {
|
||||
type Error = error_stack::Report<errors::ConnectorError>;
|
||||
fn try_from(auth_type: &types::ConnectorAuthType) -> Result<Self, Self::Error> {
|
||||
fn try_from(auth_type: &ConnectorAuthType) -> Result<Self, Self::Error> {
|
||||
match auth_type {
|
||||
types::ConnectorAuthType::BodyKey { api_key, key1 } => Ok(Self {
|
||||
api_key: api_key.to_owned(),
|
||||
key1: key1.to_owned(),
|
||||
}),
|
||||
types::ConnectorAuthType::BodyKey { api_key, key1 } => Ok(Self::AuthWithDetails(
|
||||
PaypalConnectorCredentials::StandardIntegration(StandardFlowCredentials {
|
||||
client_id: key1.to_owned(),
|
||||
client_secret: api_key.to_owned(),
|
||||
}),
|
||||
)),
|
||||
types::ConnectorAuthType::SignatureKey {
|
||||
api_key,
|
||||
key1,
|
||||
api_secret,
|
||||
} => Ok(Self::AuthWithDetails(
|
||||
PaypalConnectorCredentials::PartnerIntegration(PartnerFlowCredentials {
|
||||
client_id: key1.to_owned(),
|
||||
client_secret: api_key.to_owned(),
|
||||
payer_id: api_secret.to_owned(),
|
||||
}),
|
||||
)),
|
||||
types::ConnectorAuthType::TemporaryAuth => Ok(Self::TemporaryAuth),
|
||||
_ => Err(errors::ConnectorError::FailedToObtainAuthType)?,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user