mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-31 01:57:45 +08:00
feat: applepay through trustpay (#1422)
Co-authored-by: dracarys18 <karthikey.hegde@juspay.in>
This commit is contained in:
committed by
GitHub
parent
641995371d
commit
8032e0290b
@ -112,6 +112,9 @@ basilisk_host = "" # Basilisk host
|
|||||||
locker_setup = "legacy_locker" # With locker to use while in the deployed environment (eg. legacy_locker, basilisk_locker)
|
locker_setup = "legacy_locker" # With locker to use while in the deployed environment (eg. legacy_locker, basilisk_locker)
|
||||||
locker_signing_key_id = "1" # Key_id to sign basilisk hs locker
|
locker_signing_key_id = "1" # Key_id to sign basilisk hs locker
|
||||||
|
|
||||||
|
[delayed_session_response]
|
||||||
|
connectors_with_delayed_session_response = "trustpay" # List of connectors which has delayed session response
|
||||||
|
|
||||||
[jwekey] # 4 priv/pub key pair
|
[jwekey] # 4 priv/pub key pair
|
||||||
locker_key_identifier1 = "" # key identifier for key rotation , should be same as basilisk
|
locker_key_identifier1 = "" # key identifier for key rotation , should be same as basilisk
|
||||||
locker_key_identifier2 = "" # key identifier for key rotation , should be same as basilisk
|
locker_key_identifier2 = "" # key identifier for key rotation , should be same as basilisk
|
||||||
|
|||||||
@ -262,3 +262,6 @@ refund_duration = 1000
|
|||||||
refund_tolerance = 100
|
refund_tolerance = 100
|
||||||
refund_retrieve_duration = 500
|
refund_retrieve_duration = 500
|
||||||
refund_retrieve_tolerance = 100
|
refund_retrieve_tolerance = 100
|
||||||
|
|
||||||
|
[delayed_session_response]
|
||||||
|
connectors_with_delayed_session_response = "trustpay"
|
||||||
|
|||||||
@ -148,6 +148,9 @@ cards = [
|
|||||||
"zen",
|
"zen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[delayed_session_response]
|
||||||
|
connectors_with_delayed_session_response = "trustpay"
|
||||||
|
|
||||||
|
|
||||||
[scheduler]
|
[scheduler]
|
||||||
stream = "SCHEDULER_STREAM"
|
stream = "SCHEDULER_STREAM"
|
||||||
|
|||||||
@ -829,6 +829,8 @@ pub enum WalletData {
|
|||||||
ApplePay(ApplePayWalletData),
|
ApplePay(ApplePayWalletData),
|
||||||
/// Wallet data for apple pay redirect flow
|
/// Wallet data for apple pay redirect flow
|
||||||
ApplePayRedirect(Box<ApplePayRedirectData>),
|
ApplePayRedirect(Box<ApplePayRedirectData>),
|
||||||
|
/// Wallet data for apple pay third party sdk flow
|
||||||
|
ApplePayThirdPartySdk(Box<ApplePayThirdPartySdkData>),
|
||||||
/// The wallet data for Google pay
|
/// The wallet data for Google pay
|
||||||
GooglePay(GooglePayWalletData),
|
GooglePay(GooglePayWalletData),
|
||||||
/// Wallet data for google pay redirect flow
|
/// Wallet data for google pay redirect flow
|
||||||
@ -864,6 +866,9 @@ pub struct ApplePayRedirectData {}
|
|||||||
#[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)]
|
#[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)]
|
||||||
pub struct GooglePayRedirectData {}
|
pub struct GooglePayRedirectData {}
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)]
|
||||||
|
pub struct ApplePayThirdPartySdkData {}
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)]
|
#[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)]
|
||||||
pub struct WeChatPayRedirection {}
|
pub struct WeChatPayRedirection {}
|
||||||
|
|
||||||
@ -1125,6 +1130,8 @@ pub enum NextActionData {
|
|||||||
DisplayBankTransferInformation {
|
DisplayBankTransferInformation {
|
||||||
bank_transfer_steps_and_charges_details: BankTransferNextStepsData,
|
bank_transfer_steps_and_charges_details: BankTransferNextStepsData,
|
||||||
},
|
},
|
||||||
|
/// contains third party sdk session token response
|
||||||
|
ThirdPartySdkSessionToken { session_token: Option<SessionToken> },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
|
||||||
@ -1679,7 +1686,7 @@ pub struct PaymentsSessionRequest {
|
|||||||
pub merchant_connector_details: Option<admin::MerchantConnectorDetailsWrap>,
|
pub merchant_connector_details: Option<admin::MerchantConnectorDetailsWrap>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
|
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
|
||||||
pub struct GpayAllowedMethodsParameters {
|
pub struct GpayAllowedMethodsParameters {
|
||||||
/// The list of allowed auth methods (ex: 3DS, No3DS, PAN_ONLY etc)
|
/// The list of allowed auth methods (ex: 3DS, No3DS, PAN_ONLY etc)
|
||||||
pub allowed_auth_methods: Vec<String>,
|
pub allowed_auth_methods: Vec<String>,
|
||||||
@ -1687,7 +1694,7 @@ pub struct GpayAllowedMethodsParameters {
|
|||||||
pub allowed_card_networks: Vec<String>,
|
pub allowed_card_networks: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
|
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
|
||||||
pub struct GpayTokenParameters {
|
pub struct GpayTokenParameters {
|
||||||
/// The name of the connector
|
/// The name of the connector
|
||||||
pub gateway: String,
|
pub gateway: String,
|
||||||
@ -1703,7 +1710,7 @@ pub struct GpayTokenParameters {
|
|||||||
pub stripe_publishable_key: Option<String>,
|
pub stripe_publishable_key: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
|
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
|
||||||
pub struct GpayTokenizationSpecification {
|
pub struct GpayTokenizationSpecification {
|
||||||
/// The token specification type(ex: PAYMENT_GATEWAY)
|
/// The token specification type(ex: PAYMENT_GATEWAY)
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
@ -1712,7 +1719,7 @@ pub struct GpayTokenizationSpecification {
|
|||||||
pub parameters: GpayTokenParameters,
|
pub parameters: GpayTokenParameters,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
|
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
|
||||||
pub struct GpayAllowedPaymentMethods {
|
pub struct GpayAllowedPaymentMethods {
|
||||||
/// The type of payment method
|
/// The type of payment method
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
@ -1723,7 +1730,7 @@ pub struct GpayAllowedPaymentMethods {
|
|||||||
pub tokenization_specification: GpayTokenizationSpecification,
|
pub tokenization_specification: GpayTokenizationSpecification,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
|
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
|
||||||
pub struct GpayTransactionInfo {
|
pub struct GpayTransactionInfo {
|
||||||
/// The country code
|
/// The country code
|
||||||
#[schema(value_type = CountryAlpha2, example = "US")]
|
#[schema(value_type = CountryAlpha2, example = "US")]
|
||||||
@ -1736,7 +1743,7 @@ pub struct GpayTransactionInfo {
|
|||||||
pub total_price: String,
|
pub total_price: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
|
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
|
||||||
pub struct GpayMerchantInfo {
|
pub struct GpayMerchantInfo {
|
||||||
/// The name of the merchant
|
/// The name of the merchant
|
||||||
pub merchant_name: String,
|
pub merchant_name: String,
|
||||||
@ -1802,7 +1809,7 @@ pub struct SessionTokenInfo {
|
|||||||
pub initiative_context: String,
|
pub initiative_context: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, ToSchema)]
|
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, ToSchema)]
|
||||||
#[serde(tag = "wallet_name")]
|
#[serde(tag = "wallet_name")]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
pub enum SessionToken {
|
pub enum SessionToken {
|
||||||
@ -1814,9 +1821,11 @@ pub enum SessionToken {
|
|||||||
Paypal(Box<PaypalSessionTokenResponse>),
|
Paypal(Box<PaypalSessionTokenResponse>),
|
||||||
/// The session response structure for Apple Pay
|
/// The session response structure for Apple Pay
|
||||||
ApplePay(Box<ApplepaySessionTokenResponse>),
|
ApplePay(Box<ApplepaySessionTokenResponse>),
|
||||||
|
/// Whenever there is no session token response or an error in session response
|
||||||
|
NoSessionTokenReceived,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, ToSchema)]
|
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, ToSchema)]
|
||||||
#[serde(rename_all = "lowercase")]
|
#[serde(rename_all = "lowercase")]
|
||||||
pub struct GpaySessionTokenResponse {
|
pub struct GpaySessionTokenResponse {
|
||||||
/// The merchant info
|
/// The merchant info
|
||||||
@ -1828,7 +1837,7 @@ pub struct GpaySessionTokenResponse {
|
|||||||
pub connector: String,
|
pub connector: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, ToSchema)]
|
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, ToSchema)]
|
||||||
#[serde(rename_all = "lowercase")]
|
#[serde(rename_all = "lowercase")]
|
||||||
pub struct KlarnaSessionTokenResponse {
|
pub struct KlarnaSessionTokenResponse {
|
||||||
/// The session token for Klarna
|
/// The session token for Klarna
|
||||||
@ -1837,26 +1846,58 @@ pub struct KlarnaSessionTokenResponse {
|
|||||||
pub session_id: String,
|
pub session_id: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, ToSchema)]
|
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, ToSchema)]
|
||||||
#[serde(rename_all = "lowercase")]
|
#[serde(rename_all = "lowercase")]
|
||||||
pub struct PaypalSessionTokenResponse {
|
pub struct PaypalSessionTokenResponse {
|
||||||
/// The session token for PayPal
|
/// The session token for PayPal
|
||||||
pub session_token: String,
|
pub session_token: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, ToSchema)]
|
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, ToSchema)]
|
||||||
#[serde(rename_all = "lowercase")]
|
#[serde(rename_all = "lowercase")]
|
||||||
pub struct ApplepaySessionTokenResponse {
|
pub struct ApplepaySessionTokenResponse {
|
||||||
/// Session object for Apple Pay
|
/// Session object for Apple Pay
|
||||||
pub session_token_data: ApplePaySessionResponse,
|
pub session_token_data: ApplePaySessionResponse,
|
||||||
/// Payment request object for Apple Pay
|
/// Payment request object for Apple Pay
|
||||||
pub payment_request_data: ApplePayPaymentRequest,
|
pub payment_request_data: Option<ApplePayPaymentRequest>,
|
||||||
|
/// The session token is w.r.t this connector
|
||||||
pub connector: String,
|
pub connector: String,
|
||||||
|
/// Identifier for the delayed session response
|
||||||
|
pub delayed_session_token: bool,
|
||||||
|
/// The next action for the sdk (ex: calling confirm or sync call)
|
||||||
|
pub sdk_next_action: SdkNextAction,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, ToSchema, serde::Deserialize)]
|
#[derive(Debug, Eq, PartialEq, serde::Serialize, Clone, ToSchema)]
|
||||||
|
pub struct SdkNextAction {
|
||||||
|
/// The type of next action
|
||||||
|
pub next_action: NextActionCall,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Eq, PartialEq, serde::Serialize, Clone, ToSchema)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub enum NextActionCall {
|
||||||
|
/// The next action call is confirm
|
||||||
|
Confirm,
|
||||||
|
/// The next action call is sync
|
||||||
|
Sync,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, ToSchema)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum ApplePaySessionResponse {
|
||||||
|
/// We get this session response, when third party sdk is involved
|
||||||
|
ThirdPartySdk(ThirdPartySdkSessionResponse),
|
||||||
|
/// We get this session response, when there is no involvement of third party sdk
|
||||||
|
/// This is the common response most of the times
|
||||||
|
NoThirdPartySdk(NoThirdPartySdkSessionResponse),
|
||||||
|
/// This is for the empty session response
|
||||||
|
NoSessionResponse,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, ToSchema, serde::Deserialize)]
|
||||||
#[serde(rename_all(deserialize = "camelCase"))]
|
#[serde(rename_all(deserialize = "camelCase"))]
|
||||||
pub struct ApplePaySessionResponse {
|
pub struct NoThirdPartySdkSessionResponse {
|
||||||
/// Timestamp at which session is requested
|
/// Timestamp at which session is requested
|
||||||
pub epoch_timestamp: u64,
|
pub epoch_timestamp: u64,
|
||||||
/// Timestamp at which session expires
|
/// Timestamp at which session expires
|
||||||
@ -1881,7 +1922,22 @@ pub struct ApplePaySessionResponse {
|
|||||||
pub psp_id: String,
|
pub psp_id: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, ToSchema, serde::Deserialize)]
|
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, ToSchema)]
|
||||||
|
pub struct ThirdPartySdkSessionResponse {
|
||||||
|
pub secrets: SecretInfoToInitiateSdk,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, ToSchema, serde::Deserialize)]
|
||||||
|
pub struct SecretInfoToInitiateSdk {
|
||||||
|
// Authorization secrets used by client to initiate sdk
|
||||||
|
#[schema(value_type = String)]
|
||||||
|
pub display: Secret<String>,
|
||||||
|
// Authorization secrets used by client for payment
|
||||||
|
#[schema(value_type = String)]
|
||||||
|
pub payment: Secret<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, ToSchema, serde::Deserialize)]
|
||||||
pub struct ApplePayPaymentRequest {
|
pub struct ApplePayPaymentRequest {
|
||||||
/// The code for country
|
/// The code for country
|
||||||
#[schema(value_type = CountryAlpha2, example = "US")]
|
#[schema(value_type = CountryAlpha2, example = "US")]
|
||||||
@ -1894,16 +1950,16 @@ pub struct ApplePayPaymentRequest {
|
|||||||
pub merchant_capabilities: Vec<String>,
|
pub merchant_capabilities: Vec<String>,
|
||||||
/// The list of supported networks
|
/// The list of supported networks
|
||||||
pub supported_networks: Vec<String>,
|
pub supported_networks: Vec<String>,
|
||||||
pub merchant_identifier: String,
|
pub merchant_identifier: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, ToSchema, serde::Deserialize)]
|
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, ToSchema, serde::Deserialize)]
|
||||||
pub struct AmountInfo {
|
pub struct AmountInfo {
|
||||||
/// The label must be the name of the merchant.
|
/// The label must be the name of the merchant.
|
||||||
pub label: String,
|
pub label: String,
|
||||||
/// A value that indicates whether the line item(Ex: total, tax, discount, or grand total) is final or pending.
|
/// A value that indicates whether the line item(Ex: total, tax, discount, or grand total) is final or pending.
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
pub total_type: String,
|
pub total_type: Option<String>,
|
||||||
/// The total amount for the payment
|
/// The total amount for the payment
|
||||||
pub amount: String,
|
pub amount: String,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -657,6 +657,9 @@ pub enum StripeNextAction {
|
|||||||
DisplayBankTransferInformation {
|
DisplayBankTransferInformation {
|
||||||
bank_transfer_steps_and_charges_details: payments::BankTransferNextStepsData,
|
bank_transfer_steps_and_charges_details: payments::BankTransferNextStepsData,
|
||||||
},
|
},
|
||||||
|
ThirdPartySdkSessionToken {
|
||||||
|
session_token: Option<payments::SessionToken>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn into_stripe_next_action(
|
pub(crate) fn into_stripe_next_action(
|
||||||
@ -677,5 +680,8 @@ pub(crate) fn into_stripe_next_action(
|
|||||||
} => StripeNextAction::DisplayBankTransferInformation {
|
} => StripeNextAction::DisplayBankTransferInformation {
|
||||||
bank_transfer_steps_and_charges_details,
|
bank_transfer_steps_and_charges_details,
|
||||||
},
|
},
|
||||||
|
payments::NextActionData::ThirdPartySdkSessionToken { session_token } => {
|
||||||
|
StripeNextAction::ThirdPartySdkSessionToken { session_token }
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -317,6 +317,9 @@ pub enum StripeNextAction {
|
|||||||
DisplayBankTransferInformation {
|
DisplayBankTransferInformation {
|
||||||
bank_transfer_steps_and_charges_details: payments::BankTransferNextStepsData,
|
bank_transfer_steps_and_charges_details: payments::BankTransferNextStepsData,
|
||||||
},
|
},
|
||||||
|
ThirdPartySdkSessionToken {
|
||||||
|
session_token: Option<payments::SessionToken>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn into_stripe_next_action(
|
pub(crate) fn into_stripe_next_action(
|
||||||
@ -337,6 +340,9 @@ pub(crate) fn into_stripe_next_action(
|
|||||||
} => StripeNextAction::DisplayBankTransferInformation {
|
} => StripeNextAction::DisplayBankTransferInformation {
|
||||||
bank_transfer_steps_and_charges_details,
|
bank_transfer_steps_and_charges_details,
|
||||||
},
|
},
|
||||||
|
payments::NextActionData::ThirdPartySdkSessionToken { session_token } => {
|
||||||
|
StripeNextAction::ThirdPartySdkSessionToken { session_token }
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -83,6 +83,7 @@ pub struct Settings {
|
|||||||
pub dummy_connector: DummyConnector,
|
pub dummy_connector: DummyConnector,
|
||||||
#[cfg(feature = "email")]
|
#[cfg(feature = "email")]
|
||||||
pub email: EmailSettings,
|
pub email: EmailSettings,
|
||||||
|
pub delayed_session_response: DelayedSessionConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone, Default)]
|
#[derive(Debug, Deserialize, Clone, Default)]
|
||||||
@ -507,6 +508,27 @@ pub struct FileUploadConfig {
|
|||||||
pub bucket_name: String,
|
pub bucket_name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Clone, Default)]
|
||||||
|
pub struct DelayedSessionConfig {
|
||||||
|
#[serde(deserialize_with = "delayed_session_deser")]
|
||||||
|
pub connectors_with_delayed_session_response: HashSet<api_models::enums::Connector>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn delayed_session_deser<'a, D>(
|
||||||
|
deserializer: D,
|
||||||
|
) -> Result<HashSet<api_models::enums::Connector>, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'a>,
|
||||||
|
{
|
||||||
|
let value = <String>::deserialize(deserializer)?;
|
||||||
|
value
|
||||||
|
.trim()
|
||||||
|
.split(',')
|
||||||
|
.map(api_models::enums::Connector::from_str)
|
||||||
|
.collect::<Result<_, _>>()
|
||||||
|
.map_err(D::Error::custom)
|
||||||
|
}
|
||||||
|
|
||||||
impl Settings {
|
impl Settings {
|
||||||
pub fn new() -> ApplicationResult<Self> {
|
pub fn new() -> ApplicationResult<Self> {
|
||||||
Self::with_config_path(None)
|
Self::with_config_path(None)
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use api_models::enums as api_enums;
|
use api_models::{enums as api_enums, payments};
|
||||||
use base64::Engine;
|
use base64::Engine;
|
||||||
use common_utils::{
|
use common_utils::{
|
||||||
errors::CustomResult,
|
errors::CustomResult,
|
||||||
@ -321,11 +321,12 @@ impl TryFrom<types::PaymentsSessionResponseRouterData<BluesnapWalletTokenRespons
|
|||||||
let wallet_token = consts::BASE64_ENGINE
|
let wallet_token = consts::BASE64_ENGINE
|
||||||
.decode(response.wallet_token.clone().expose())
|
.decode(response.wallet_token.clone().expose())
|
||||||
.into_report()
|
.into_report()
|
||||||
.change_context(errors::ConnectorError::ParsingFailed)?;
|
.change_context(errors::ConnectorError::ResponseHandlingFailed)?;
|
||||||
|
|
||||||
let session_response: api_models::payments::ApplePaySessionResponse = wallet_token[..]
|
let session_response: api_models::payments::NoThirdPartySdkSessionResponse =
|
||||||
.parse_struct("ApplePayResponse")
|
wallet_token[..]
|
||||||
.change_context(errors::ConnectorError::ParsingFailed)?;
|
.parse_struct("NoThirdPartySdkSessionResponse")
|
||||||
|
.change_context(errors::ConnectorError::ParsingFailed)?;
|
||||||
|
|
||||||
let metadata = item.data.get_connector_meta()?.expose();
|
let metadata = item.data.get_connector_meta()?.expose();
|
||||||
let applepay_metadata = metadata
|
let applepay_metadata = metadata
|
||||||
@ -338,13 +339,16 @@ impl TryFrom<types::PaymentsSessionResponseRouterData<BluesnapWalletTokenRespons
|
|||||||
response: Ok(types::PaymentsResponseData::SessionResponse {
|
response: Ok(types::PaymentsResponseData::SessionResponse {
|
||||||
session_token: types::api::SessionToken::ApplePay(Box::new(
|
session_token: types::api::SessionToken::ApplePay(Box::new(
|
||||||
api_models::payments::ApplepaySessionTokenResponse {
|
api_models::payments::ApplepaySessionTokenResponse {
|
||||||
session_token_data: session_response,
|
session_token_data:
|
||||||
payment_request_data: api_models::payments::ApplePayPaymentRequest {
|
api_models::payments::ApplePaySessionResponse::NoThirdPartySdk(
|
||||||
|
session_response,
|
||||||
|
),
|
||||||
|
payment_request_data: Some(api_models::payments::ApplePayPaymentRequest {
|
||||||
country_code: item.data.get_billing_country()?,
|
country_code: item.data.get_billing_country()?,
|
||||||
currency_code: item.data.request.currency.to_string(),
|
currency_code: item.data.request.currency.to_string(),
|
||||||
total: api_models::payments::AmountInfo {
|
total: api_models::payments::AmountInfo {
|
||||||
label: applepay_metadata.data.payment_request_data.label,
|
label: applepay_metadata.data.payment_request_data.label,
|
||||||
total_type: "final".to_string(),
|
total_type: Some("final".to_string()),
|
||||||
amount: item.data.request.amount.to_string(),
|
amount: item.data.request.amount.to_string(),
|
||||||
},
|
},
|
||||||
merchant_capabilities: applepay_metadata
|
merchant_capabilities: applepay_metadata
|
||||||
@ -355,12 +359,20 @@ impl TryFrom<types::PaymentsSessionResponseRouterData<BluesnapWalletTokenRespons
|
|||||||
.data
|
.data
|
||||||
.payment_request_data
|
.payment_request_data
|
||||||
.supported_networks,
|
.supported_networks,
|
||||||
merchant_identifier: applepay_metadata
|
merchant_identifier: Some(
|
||||||
.data
|
applepay_metadata
|
||||||
.session_token_data
|
.data
|
||||||
.merchant_identifier,
|
.session_token_data
|
||||||
},
|
.merchant_identifier,
|
||||||
|
),
|
||||||
|
}),
|
||||||
connector: "bluesnap".to_string(),
|
connector: "bluesnap".to_string(),
|
||||||
|
delayed_session_token: false,
|
||||||
|
sdk_next_action: {
|
||||||
|
payments::SdkNextAction {
|
||||||
|
next_action: payments::NextActionCall::Confirm,
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
}),
|
}),
|
||||||
|
|||||||
@ -2167,8 +2167,11 @@ impl<F, T>
|
|||||||
};
|
};
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
response: Ok(types::PaymentsResponseData::PreProcessingResponse {
|
response: Ok(types::PaymentsResponseData::PreProcessingResponse {
|
||||||
pre_processing_id: item.response.id,
|
pre_processing_id: types::PreprocessingResponseId::PreProcessingId(
|
||||||
|
item.response.id,
|
||||||
|
),
|
||||||
connector_metadata: Some(connector_metadata),
|
connector_metadata: Some(connector_metadata),
|
||||||
|
session_token: None,
|
||||||
}),
|
}),
|
||||||
status,
|
status,
|
||||||
..item.data
|
..item.data
|
||||||
|
|||||||
@ -343,6 +343,102 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl api::PaymentsPreProcessing for Trustpay {}
|
||||||
|
|
||||||
|
impl
|
||||||
|
ConnectorIntegration<
|
||||||
|
api::PreProcessing,
|
||||||
|
types::PaymentsPreProcessingData,
|
||||||
|
types::PaymentsResponseData,
|
||||||
|
> for Trustpay
|
||||||
|
{
|
||||||
|
fn get_headers(
|
||||||
|
&self,
|
||||||
|
req: &types::PaymentsPreProcessingRouterData,
|
||||||
|
_connectors: &settings::Connectors,
|
||||||
|
) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
|
||||||
|
let mut header = vec![(
|
||||||
|
headers::CONTENT_TYPE.to_string(),
|
||||||
|
types::PaymentsPreProcessingType::get_content_type(self)
|
||||||
|
.to_string()
|
||||||
|
.into(),
|
||||||
|
)];
|
||||||
|
let mut api_key = self.get_auth_header(&req.connector_auth_type)?;
|
||||||
|
header.append(&mut api_key);
|
||||||
|
Ok(header)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_content_type(&self) -> &'static str {
|
||||||
|
self.common_get_content_type()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_url(
|
||||||
|
&self,
|
||||||
|
_req: &types::PaymentsPreProcessingRouterData,
|
||||||
|
connectors: &settings::Connectors,
|
||||||
|
) -> CustomResult<String, errors::ConnectorError> {
|
||||||
|
Ok(format!("{}{}", self.base_url(connectors), "api/v1/intent"))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_request_body(
|
||||||
|
&self,
|
||||||
|
req: &types::PaymentsPreProcessingRouterData,
|
||||||
|
) -> CustomResult<Option<String>, errors::ConnectorError> {
|
||||||
|
let create_intent_req = trustpay::TrustpayCreateIntentRequest::try_from(req)?;
|
||||||
|
let trustpay_req =
|
||||||
|
utils::Encode::<trustpay::TrustpayCreateIntentRequest>::url_encode(&create_intent_req)
|
||||||
|
.change_context(errors::ConnectorError::RequestEncodingFailed)?;
|
||||||
|
Ok(Some(trustpay_req))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_request(
|
||||||
|
&self,
|
||||||
|
req: &types::PaymentsPreProcessingRouterData,
|
||||||
|
connectors: &settings::Connectors,
|
||||||
|
) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
|
||||||
|
let req = Some(
|
||||||
|
services::RequestBuilder::new()
|
||||||
|
.method(services::Method::Post)
|
||||||
|
.attach_default_headers()
|
||||||
|
.headers(types::PaymentsPreProcessingType::get_headers(
|
||||||
|
self, req, connectors,
|
||||||
|
)?)
|
||||||
|
.url(&types::PaymentsPreProcessingType::get_url(
|
||||||
|
self, req, connectors,
|
||||||
|
)?)
|
||||||
|
.body(types::PaymentsPreProcessingType::get_request_body(
|
||||||
|
self, req,
|
||||||
|
)?)
|
||||||
|
.build(),
|
||||||
|
);
|
||||||
|
Ok(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_response(
|
||||||
|
&self,
|
||||||
|
data: &types::PaymentsPreProcessingRouterData,
|
||||||
|
res: Response,
|
||||||
|
) -> CustomResult<types::PaymentsPreProcessingRouterData, errors::ConnectorError> {
|
||||||
|
let response: trustpay::TrustpayCreateIntentResponse = res
|
||||||
|
.response
|
||||||
|
.parse_struct("TrustpayCreateIntentResponse")
|
||||||
|
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
|
||||||
|
types::RouterData::try_from(types::ResponseRouterData {
|
||||||
|
response,
|
||||||
|
data: data.clone(),
|
||||||
|
http_code: res.status_code,
|
||||||
|
})
|
||||||
|
.change_context(errors::ConnectorError::ResponseHandlingFailed)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_error_response(
|
||||||
|
&self,
|
||||||
|
res: Response,
|
||||||
|
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
|
||||||
|
self.build_error_response(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl api::PaymentSession for Trustpay {}
|
impl api::PaymentSession for Trustpay {}
|
||||||
|
|
||||||
impl ConnectorIntegration<api::Session, types::PaymentsSessionData, types::PaymentsResponseData>
|
impl ConnectorIntegration<api::Session, types::PaymentsSessionData, types::PaymentsResponseData>
|
||||||
|
|||||||
@ -16,6 +16,7 @@ use crate::{
|
|||||||
core::errors,
|
core::errors,
|
||||||
services,
|
services,
|
||||||
types::{self, api, storage::enums, BrowserInformation},
|
types::{self, api, storage::enums, BrowserInformation},
|
||||||
|
utils::OptionExt,
|
||||||
};
|
};
|
||||||
|
|
||||||
type Error = error_stack::Report<errors::ConnectorError>;
|
type Error = error_stack::Report<errors::ConnectorError>;
|
||||||
@ -474,7 +475,7 @@ pub struct PaymentsResponseCards {
|
|||||||
pub status: i64,
|
pub status: i64,
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
pub instance_id: String,
|
pub instance_id: String,
|
||||||
pub payment_status: String,
|
pub payment_status: Option<String>,
|
||||||
pub payment_description: Option<String>,
|
pub payment_description: Option<String>,
|
||||||
pub redirect_url: Option<Url>,
|
pub redirect_url: Option<Url>,
|
||||||
pub redirect_params: Option<HashMap<String, String>>,
|
pub redirect_params: Option<HashMap<String, String>>,
|
||||||
@ -553,8 +554,13 @@ fn handle_cards_response(
|
|||||||
),
|
),
|
||||||
errors::ConnectorError,
|
errors::ConnectorError,
|
||||||
> {
|
> {
|
||||||
|
// By default, payment status is pending(000.200.000 status code)
|
||||||
let (status, msg) = get_transaction_status(
|
let (status, msg) = get_transaction_status(
|
||||||
response.payment_status.as_str(),
|
response
|
||||||
|
.payment_status
|
||||||
|
.to_owned()
|
||||||
|
.unwrap_or("000.200.000".to_string())
|
||||||
|
.as_str(),
|
||||||
response.redirect_url.clone(),
|
response.redirect_url.clone(),
|
||||||
)?;
|
)?;
|
||||||
let form_fields = response.redirect_params.unwrap_or_default();
|
let form_fields = response.redirect_params.unwrap_or_default();
|
||||||
@ -567,7 +573,9 @@ fn handle_cards_response(
|
|||||||
});
|
});
|
||||||
let error = if msg.is_some() {
|
let error = if msg.is_some() {
|
||||||
Some(types::ErrorResponse {
|
Some(types::ErrorResponse {
|
||||||
code: response.payment_status,
|
code: response
|
||||||
|
.payment_status
|
||||||
|
.unwrap_or_else(|| consts::NO_ERROR_CODE.to_string()),
|
||||||
message: msg.unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()),
|
message: msg.unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()),
|
||||||
reason: None,
|
reason: None,
|
||||||
status_code,
|
status_code,
|
||||||
@ -802,6 +810,164 @@ impl<F, T> TryFrom<types::ResponseRouterData<F, TrustpayAuthUpdateResponse, T, t
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Debug, Serialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct TrustpayCreateIntentRequest {
|
||||||
|
pub amount: String,
|
||||||
|
pub currency: String,
|
||||||
|
// If true, Apple Pay will be initialized
|
||||||
|
pub init_apple_pay: Option<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<&types::PaymentsSessionRouterData> for TrustpayCreateIntentRequest {
|
||||||
|
type Error = Error;
|
||||||
|
fn try_from(item: &types::PaymentsSessionRouterData) -> Result<Self, Self::Error> {
|
||||||
|
Ok(Self {
|
||||||
|
amount: item.request.amount.to_string(),
|
||||||
|
currency: item.request.currency.to_string(),
|
||||||
|
init_apple_pay: Some(true),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<&types::PaymentsPreProcessingRouterData> for TrustpayCreateIntentRequest {
|
||||||
|
type Error = Error;
|
||||||
|
fn try_from(item: &types::PaymentsPreProcessingRouterData) -> Result<Self, Self::Error> {
|
||||||
|
Ok(Self {
|
||||||
|
amount: item
|
||||||
|
.request
|
||||||
|
.amount
|
||||||
|
.get_required_value("amount")
|
||||||
|
.change_context(errors::ConnectorError::MissingRequiredField {
|
||||||
|
field_name: "amount",
|
||||||
|
})?
|
||||||
|
.to_string(),
|
||||||
|
currency: item
|
||||||
|
.request
|
||||||
|
.currency
|
||||||
|
.get_required_value("currency")
|
||||||
|
.change_context(errors::ConnectorError::MissingRequiredField {
|
||||||
|
field_name: "currency",
|
||||||
|
})?
|
||||||
|
.to_string(),
|
||||||
|
init_apple_pay: Some(true),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct TrustpayCreateIntentResponse {
|
||||||
|
// TrustPay's authorization secrets used by client
|
||||||
|
pub secrets: SdkSecretInfo,
|
||||||
|
// Data object to be used for Apple Pay
|
||||||
|
pub apple_init_result_data: TrustpayApplePayResponse,
|
||||||
|
// Unique operation/transaction identifier
|
||||||
|
pub instance_id: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct SdkSecretInfo {
|
||||||
|
pub display: Secret<String>,
|
||||||
|
pub payment: Secret<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct TrustpayApplePayResponse {
|
||||||
|
pub country_code: api_models::enums::CountryAlpha2,
|
||||||
|
pub currency_code: String,
|
||||||
|
pub supported_networks: Vec<String>,
|
||||||
|
pub merchant_capabilities: Vec<String>,
|
||||||
|
pub total: ApplePayTotalInfo,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct ApplePayTotalInfo {
|
||||||
|
pub label: String,
|
||||||
|
pub amount: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F, T>
|
||||||
|
TryFrom<
|
||||||
|
types::ResponseRouterData<F, TrustpayCreateIntentResponse, T, types::PaymentsResponseData>,
|
||||||
|
> for types::RouterData<F, T, types::PaymentsResponseData>
|
||||||
|
{
|
||||||
|
type Error = Error;
|
||||||
|
fn try_from(
|
||||||
|
item: types::ResponseRouterData<
|
||||||
|
F,
|
||||||
|
TrustpayCreateIntentResponse,
|
||||||
|
T,
|
||||||
|
types::PaymentsResponseData,
|
||||||
|
>,
|
||||||
|
) -> Result<Self, Self::Error> {
|
||||||
|
let response = item.response;
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
response: Ok(types::PaymentsResponseData::PreProcessingResponse {
|
||||||
|
connector_metadata: None,
|
||||||
|
pre_processing_id: types::PreprocessingResponseId::ConnectorTransactionId(
|
||||||
|
response.instance_id,
|
||||||
|
),
|
||||||
|
session_token: Some(types::api::SessionToken::ApplePay(Box::new(
|
||||||
|
api_models::payments::ApplepaySessionTokenResponse {
|
||||||
|
session_token_data:
|
||||||
|
api_models::payments::ApplePaySessionResponse::ThirdPartySdk(
|
||||||
|
api_models::payments::ThirdPartySdkSessionResponse {
|
||||||
|
secrets: response.secrets.into(),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
payment_request_data: Some(api_models::payments::ApplePayPaymentRequest {
|
||||||
|
country_code: response.apple_init_result_data.country_code,
|
||||||
|
currency_code: response.apple_init_result_data.currency_code.clone(),
|
||||||
|
supported_networks: response
|
||||||
|
.apple_init_result_data
|
||||||
|
.supported_networks
|
||||||
|
.clone(),
|
||||||
|
merchant_capabilities: response
|
||||||
|
.apple_init_result_data
|
||||||
|
.merchant_capabilities
|
||||||
|
.clone(),
|
||||||
|
total: response.apple_init_result_data.total.into(),
|
||||||
|
merchant_identifier: None,
|
||||||
|
}),
|
||||||
|
connector: "trustpay".to_string(),
|
||||||
|
delayed_session_token: true,
|
||||||
|
sdk_next_action: {
|
||||||
|
api_models::payments::SdkNextAction {
|
||||||
|
next_action: api_models::payments::NextActionCall::Sync,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
))),
|
||||||
|
}),
|
||||||
|
..item.data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<SdkSecretInfo> for api_models::payments::SecretInfoToInitiateSdk {
|
||||||
|
fn from(value: SdkSecretInfo) -> Self {
|
||||||
|
Self {
|
||||||
|
display: value.display,
|
||||||
|
payment: value.payment,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ApplePayTotalInfo> for api_models::payments::AmountInfo {
|
||||||
|
fn from(value: ApplePayTotalInfo) -> Self {
|
||||||
|
Self {
|
||||||
|
label: value.label,
|
||||||
|
amount: value.amount,
|
||||||
|
total_type: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug, Serialize)]
|
#[derive(Default, Debug, Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct TrustpayRefundRequestCards {
|
pub struct TrustpayRefundRequestCards {
|
||||||
|
|||||||
@ -156,7 +156,7 @@ where
|
|||||||
&merchant_account,
|
&merchant_account,
|
||||||
connector,
|
connector,
|
||||||
&operation,
|
&operation,
|
||||||
&payment_data,
|
&mut payment_data,
|
||||||
&customer,
|
&customer,
|
||||||
call_connector_action,
|
call_connector_action,
|
||||||
tokenization_action,
|
tokenization_action,
|
||||||
@ -399,6 +399,7 @@ impl PaymentRedirectFlow for PaymentRedirectCompleteAuthorize {
|
|||||||
.and_then(|next_action_data| match next_action_data {
|
.and_then(|next_action_data| match next_action_data {
|
||||||
api_models::payments::NextActionData::RedirectToUrl { redirect_to_url } => Some(redirect_to_url),
|
api_models::payments::NextActionData::RedirectToUrl { redirect_to_url } => Some(redirect_to_url),
|
||||||
api_models::payments::NextActionData::DisplayBankTransferInformation { .. } => None,
|
api_models::payments::NextActionData::DisplayBankTransferInformation { .. } => None,
|
||||||
|
api_models::payments::NextActionData::ThirdPartySdkSessionToken { .. } => None
|
||||||
})
|
})
|
||||||
.ok_or(errors::ApiErrorResponse::InternalServerError)
|
.ok_or(errors::ApiErrorResponse::InternalServerError)
|
||||||
.into_report()
|
.into_report()
|
||||||
@ -489,7 +490,7 @@ pub async fn call_connector_service<F, Op, Req>(
|
|||||||
merchant_account: &domain::MerchantAccount,
|
merchant_account: &domain::MerchantAccount,
|
||||||
connector: api::ConnectorData,
|
connector: api::ConnectorData,
|
||||||
_operation: &Op,
|
_operation: &Op,
|
||||||
payment_data: &PaymentData<F>,
|
payment_data: &mut PaymentData<F>,
|
||||||
customer: &Option<domain::Customer>,
|
customer: &Option<domain::Customer>,
|
||||||
call_connector_action: CallConnectorAction,
|
call_connector_action: CallConnectorAction,
|
||||||
tokenization_action: TokenizationAction,
|
tokenization_action: TokenizationAction,
|
||||||
@ -542,6 +543,14 @@ where
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
if let Ok(types::PaymentsResponseData::PreProcessingResponse {
|
||||||
|
session_token: Some(session_token),
|
||||||
|
..
|
||||||
|
}) = router_data.response.to_owned()
|
||||||
|
{
|
||||||
|
payment_data.sessions_token.push(session_token);
|
||||||
|
};
|
||||||
|
|
||||||
let router_data_res = if should_continue_payment {
|
let router_data_res = if should_continue_payment {
|
||||||
router_data
|
router_data
|
||||||
.decide_flows(
|
.decide_flows(
|
||||||
@ -590,7 +599,6 @@ where
|
|||||||
|
|
||||||
for session_connector_data in connectors.iter() {
|
for session_connector_data in connectors.iter() {
|
||||||
let connector_id = session_connector_data.connector.connector.id();
|
let connector_id = session_connector_data.connector.connector.id();
|
||||||
|
|
||||||
let router_data = payment_data
|
let router_data = payment_data
|
||||||
.construct_router_data(state, connector_id, merchant_account, customer)
|
.construct_router_data(state, connector_id, merchant_account, customer)
|
||||||
.await?;
|
.await?;
|
||||||
@ -612,10 +620,17 @@ where
|
|||||||
let connector_name = session_connector.connector.connector_name.to_string();
|
let connector_name = session_connector.connector.connector_name.to_string();
|
||||||
match connector_res {
|
match connector_res {
|
||||||
Ok(connector_response) => {
|
Ok(connector_response) => {
|
||||||
if let Ok(types::PaymentsResponseData::SessionResponse { session_token }) =
|
if let Ok(types::PaymentsResponseData::SessionResponse { session_token, .. }) =
|
||||||
connector_response.response
|
connector_response.response
|
||||||
{
|
{
|
||||||
payment_data.sessions_token.push(session_token);
|
// If session token is NoSessionTokenReceived, it is not pushed into the sessions_token as there is no response or there can be some error
|
||||||
|
// In case of error, that error is already logged
|
||||||
|
if !matches!(
|
||||||
|
session_token,
|
||||||
|
api_models::payments::SessionToken::NoSessionTokenReceived,
|
||||||
|
) {
|
||||||
|
payment_data.sessions_token.push(session_token);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(connector_error) => {
|
Err(connector_error) => {
|
||||||
@ -716,17 +731,17 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn complete_preprocessing_steps_if_required<F, Req, Res>(
|
async fn complete_preprocessing_steps_if_required<F, Req>(
|
||||||
state: &AppState,
|
state: &AppState,
|
||||||
connector: &api::ConnectorData,
|
connector: &api::ConnectorData,
|
||||||
payment_data: &PaymentData<F>,
|
payment_data: &PaymentData<F>,
|
||||||
router_data: types::RouterData<F, Req, Res>,
|
router_data: types::RouterData<F, Req, types::PaymentsResponseData>,
|
||||||
should_continue_payment: bool,
|
should_continue_payment: bool,
|
||||||
) -> RouterResult<(types::RouterData<F, Req, Res>, bool)>
|
) -> RouterResult<(types::RouterData<F, Req, types::PaymentsResponseData>, bool)>
|
||||||
where
|
where
|
||||||
F: Send + Clone + Sync,
|
F: Send + Clone + Sync,
|
||||||
Req: Send + Sync,
|
Req: Send + Sync,
|
||||||
types::RouterData<F, Req, Res>: Feature<F, Req> + Send,
|
types::RouterData<F, Req, types::PaymentsResponseData>: Feature<F, Req> + Send,
|
||||||
dyn api::Connector: services::api::ConnectorIntegration<F, Req, types::PaymentsResponseData>,
|
dyn api::Connector: services::api::ConnectorIntegration<F, Req, types::PaymentsResponseData>,
|
||||||
{
|
{
|
||||||
//TODO: For ACH transfers, if preprocessing_step is not required for connectors encountered in future, add the check
|
//TODO: For ACH transfers, if preprocessing_step is not required for connectors encountered in future, add the check
|
||||||
@ -744,6 +759,16 @@ where
|
|||||||
}
|
}
|
||||||
_ => (router_data, should_continue_payment),
|
_ => (router_data, should_continue_payment),
|
||||||
},
|
},
|
||||||
|
Some(api_models::payments::PaymentMethodData::Wallet(_)) => {
|
||||||
|
if connector.connector_name.to_string() == *"trustpay" {
|
||||||
|
(
|
||||||
|
router_data.preprocessing_steps(state, connector).await?,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(router_data, should_continue_payment)
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => (router_data, should_continue_payment),
|
_ => (router_data, should_continue_payment),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -869,7 +894,6 @@ where
|
|||||||
.payment_method
|
.payment_method
|
||||||
.get_required_value("payment_method")?;
|
.get_required_value("payment_method")?;
|
||||||
let payment_method_type = &payment_data.payment_attempt.payment_method_type;
|
let payment_method_type = &payment_data.payment_attempt.payment_method_type;
|
||||||
|
|
||||||
let is_connector_tokenization_enabled =
|
let is_connector_tokenization_enabled =
|
||||||
is_payment_method_tokenization_enabled_for_connector(
|
is_payment_method_tokenization_enabled_for_connector(
|
||||||
state,
|
state,
|
||||||
|
|||||||
@ -647,7 +647,6 @@ default_imp_for_pre_processing_steps!(
|
|||||||
connector::Payu,
|
connector::Payu,
|
||||||
connector::Rapyd,
|
connector::Rapyd,
|
||||||
connector::Shift4,
|
connector::Shift4,
|
||||||
connector::Trustpay,
|
|
||||||
connector::Worldline,
|
connector::Worldline,
|
||||||
connector::Worldpay,
|
connector::Worldpay,
|
||||||
connector::Zen
|
connector::Zen
|
||||||
|
|||||||
@ -337,6 +337,7 @@ impl TryFrom<types::PaymentsAuthorizeData> for types::PaymentsPreProcessingData
|
|||||||
Ok(Self {
|
Ok(Self {
|
||||||
email: data.email,
|
email: data.email,
|
||||||
currency: Some(data.currency),
|
currency: Some(data.currency),
|
||||||
|
amount: Some(data.amount),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use api_models::payments as payment_types;
|
use api_models::payments as payment_types;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use common_utils::ext_traits::ByteSliceExt;
|
use common_utils::ext_traits::ByteSliceExt;
|
||||||
use error_stack::{report, ResultExt};
|
use error_stack::{Report, ResultExt};
|
||||||
|
|
||||||
use super::{ConstructFlowSpecificData, Feature};
|
use super::{ConstructFlowSpecificData, Feature};
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -10,7 +10,7 @@ use crate::{
|
|||||||
errors::{self, ConnectorErrorExt, RouterResult},
|
errors::{self, ConnectorErrorExt, RouterResult},
|
||||||
payments::{self, access_token, transformers, PaymentData},
|
payments::{self, access_token, transformers, PaymentData},
|
||||||
},
|
},
|
||||||
headers,
|
headers, logger,
|
||||||
routes::{self, metrics},
|
routes::{self, metrics},
|
||||||
services,
|
services,
|
||||||
types::{self, api, domain},
|
types::{self, api, domain},
|
||||||
@ -78,18 +78,22 @@ impl Feature<api::Session, types::PaymentsSessionData> for types::PaymentsSessio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mk_applepay_session_request(
|
fn get_applepay_metadata(
|
||||||
state: &routes::AppState,
|
connector_metadata: Option<common_utils::pii::SecretSerdeValue>,
|
||||||
router_data: &types::PaymentsSessionRouterData,
|
) -> RouterResult<payment_types::ApplepaySessionTokenData> {
|
||||||
) -> RouterResult<(services::Request, payment_types::ApplepaySessionTokenData)> {
|
connector_metadata
|
||||||
let connector_metadata = router_data.connector_meta_data.clone();
|
|
||||||
|
|
||||||
let applepay_metadata = connector_metadata
|
|
||||||
.parse_value::<payment_types::ApplepaySessionTokenData>("ApplepaySessionTokenData")
|
.parse_value::<payment_types::ApplepaySessionTokenData>("ApplepaySessionTokenData")
|
||||||
.change_context(errors::ApiErrorResponse::InvalidDataFormat {
|
.change_context(errors::ApiErrorResponse::InvalidDataFormat {
|
||||||
field_name: "connector_metadata".to_string(),
|
field_name: "connector_metadata".to_string(),
|
||||||
expected_format: "applepay_metadata_format".to_string(),
|
expected_format: "applepay_metadata_format".to_string(),
|
||||||
})?;
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mk_applepay_session_request(
|
||||||
|
state: &routes::AppState,
|
||||||
|
router_data: &types::PaymentsSessionRouterData,
|
||||||
|
) -> RouterResult<services::Request> {
|
||||||
|
let applepay_metadata = get_applepay_metadata(router_data.connector_meta_data.clone())?;
|
||||||
let request = payment_types::ApplepaySessionRequest {
|
let request = payment_types::ApplepaySessionRequest {
|
||||||
merchant_identifier: applepay_metadata
|
merchant_identifier: applepay_metadata
|
||||||
.data
|
.data
|
||||||
@ -134,14 +138,10 @@ fn mk_applepay_session_request(
|
|||||||
.clone(),
|
.clone(),
|
||||||
))
|
))
|
||||||
.add_certificate_key(Some(
|
.add_certificate_key(Some(
|
||||||
applepay_metadata
|
applepay_metadata.data.session_token_data.certificate_keys,
|
||||||
.data
|
|
||||||
.session_token_data
|
|
||||||
.certificate_keys
|
|
||||||
.clone(),
|
|
||||||
))
|
))
|
||||||
.build();
|
.build();
|
||||||
Ok((session_request, applepay_metadata))
|
Ok(session_request)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_applepay_session_token(
|
async fn create_applepay_session_token(
|
||||||
@ -149,83 +149,138 @@ async fn create_applepay_session_token(
|
|||||||
router_data: &types::PaymentsSessionRouterData,
|
router_data: &types::PaymentsSessionRouterData,
|
||||||
connector: &api::ConnectorData,
|
connector: &api::ConnectorData,
|
||||||
) -> RouterResult<types::PaymentsSessionRouterData> {
|
) -> RouterResult<types::PaymentsSessionRouterData> {
|
||||||
let (applepay_session_request, applepay_metadata) =
|
let connectors_with_delayed_response = &state
|
||||||
mk_applepay_session_request(state, router_data)?;
|
.conf
|
||||||
let response = services::call_connector_api(state, applepay_session_request)
|
.delayed_session_response
|
||||||
.await
|
.connectors_with_delayed_session_response;
|
||||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
|
||||||
.attach_printable("Failure in calling connector api")?;
|
|
||||||
let session_response: payment_types::ApplePaySessionResponse = match response {
|
|
||||||
Ok(resp) => resp
|
|
||||||
.response
|
|
||||||
.parse_struct("ApplePaySessionResponse")
|
|
||||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
|
||||||
.attach_printable("Failed to parse ApplePaySessionResponse struct"),
|
|
||||||
Err(err) => {
|
|
||||||
let error_response: payment_types::ApplepayErrorResponse = err
|
|
||||||
.response
|
|
||||||
.parse_struct("ApplepayErrorResponse")
|
|
||||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
|
||||||
.attach_printable("Failed to parse ApplepayErrorResponse struct")?;
|
|
||||||
Err(
|
|
||||||
report!(errors::ApiErrorResponse::InternalServerError).attach_printable(format!(
|
|
||||||
"Failed with {} status code and the error response is {:?}",
|
|
||||||
err.status_code, error_response
|
|
||||||
)),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}?;
|
|
||||||
|
|
||||||
let amount_info = payment_types::AmountInfo {
|
let connector_name = connector.connector_name;
|
||||||
label: applepay_metadata.data.payment_request_data.label,
|
let delayed_response = connectors_with_delayed_response.contains(&connector_name);
|
||||||
total_type: "final".to_string(),
|
|
||||||
amount: connector::utils::to_currency_base_unit(
|
if delayed_response {
|
||||||
router_data.request.amount,
|
let delayed_response_apple_pay_session =
|
||||||
router_data.request.currency,
|
Some(payment_types::ApplePaySessionResponse::NoSessionResponse);
|
||||||
|
create_apple_pay_session_response(
|
||||||
|
router_data,
|
||||||
|
delayed_response_apple_pay_session,
|
||||||
|
None, // Apple pay payment request will be none for delayed session response
|
||||||
|
connector_name.to_string(),
|
||||||
|
delayed_response,
|
||||||
|
payment_types::NextActionCall::Confirm,
|
||||||
)
|
)
|
||||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
} else {
|
||||||
.attach_printable("Failed to convert currency to base unit")?,
|
let applepay_metadata = get_applepay_metadata(router_data.connector_meta_data.clone())?;
|
||||||
};
|
|
||||||
|
|
||||||
let applepay_payment_request = payment_types::ApplePayPaymentRequest {
|
let amount_info = payment_types::AmountInfo {
|
||||||
country_code: router_data
|
label: applepay_metadata.data.payment_request_data.label,
|
||||||
.request
|
total_type: Some("final".to_string()),
|
||||||
.country
|
amount: connector::utils::to_currency_base_unit(
|
||||||
.to_owned()
|
router_data.request.amount,
|
||||||
.get_required_value("country_code")
|
router_data.request.currency,
|
||||||
.change_context(errors::ApiErrorResponse::MissingRequiredField {
|
)
|
||||||
field_name: "country_code",
|
.change_context(errors::ApiErrorResponse::PreconditionFailed {
|
||||||
|
message: "Failed to convert currency to base unit".to_string(),
|
||||||
})?,
|
})?,
|
||||||
currency_code: router_data.request.currency.to_string(),
|
};
|
||||||
total: amount_info,
|
|
||||||
merchant_capabilities: applepay_metadata
|
|
||||||
.data
|
|
||||||
.payment_request_data
|
|
||||||
.merchant_capabilities,
|
|
||||||
supported_networks: applepay_metadata
|
|
||||||
.data
|
|
||||||
.payment_request_data
|
|
||||||
.supported_networks,
|
|
||||||
merchant_identifier: applepay_metadata
|
|
||||||
.data
|
|
||||||
.session_token_data
|
|
||||||
.merchant_identifier,
|
|
||||||
};
|
|
||||||
|
|
||||||
let response_router_data = types::PaymentsSessionRouterData {
|
let applepay_payment_request = payment_types::ApplePayPaymentRequest {
|
||||||
response: Ok(types::PaymentsResponseData::SessionResponse {
|
country_code: router_data
|
||||||
session_token: payment_types::SessionToken::ApplePay(Box::new(
|
.request
|
||||||
payment_types::ApplepaySessionTokenResponse {
|
.country
|
||||||
session_token_data: session_response,
|
.to_owned()
|
||||||
payment_request_data: applepay_payment_request,
|
.get_required_value("country_code")
|
||||||
connector: connector.connector_name.to_string(),
|
.change_context(errors::ApiErrorResponse::MissingRequiredField {
|
||||||
},
|
field_name: "country_code",
|
||||||
)),
|
})?,
|
||||||
|
currency_code: router_data.request.currency.to_string(),
|
||||||
|
total: amount_info,
|
||||||
|
merchant_capabilities: applepay_metadata
|
||||||
|
.data
|
||||||
|
.payment_request_data
|
||||||
|
.merchant_capabilities,
|
||||||
|
supported_networks: applepay_metadata
|
||||||
|
.data
|
||||||
|
.payment_request_data
|
||||||
|
.supported_networks,
|
||||||
|
merchant_identifier: Some(
|
||||||
|
applepay_metadata
|
||||||
|
.data
|
||||||
|
.session_token_data
|
||||||
|
.merchant_identifier,
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
let applepay_session_request = mk_applepay_session_request(state, router_data)?;
|
||||||
|
let response = services::call_connector_api(state, applepay_session_request).await;
|
||||||
|
|
||||||
|
// logging the error if present in session call response
|
||||||
|
log_session_response_if_error(&response);
|
||||||
|
|
||||||
|
let apple_pay_session_response = response
|
||||||
|
.ok()
|
||||||
|
.and_then(|apple_pay_res| {
|
||||||
|
apple_pay_res
|
||||||
|
.map(|res| {
|
||||||
|
let response: Result<
|
||||||
|
payment_types::NoThirdPartySdkSessionResponse,
|
||||||
|
Report<common_utils::errors::ParsingError>,
|
||||||
|
> = res.response.parse_struct("NoThirdPartySdkSessionResponse");
|
||||||
|
|
||||||
|
// logging the parsing failed error
|
||||||
|
if let Err(error) = response.as_ref() {
|
||||||
|
logger::error!(?error);
|
||||||
|
};
|
||||||
|
|
||||||
|
response.ok()
|
||||||
|
})
|
||||||
|
.ok()
|
||||||
|
})
|
||||||
|
.flatten();
|
||||||
|
|
||||||
|
let session_response =
|
||||||
|
apple_pay_session_response.map(payment_types::ApplePaySessionResponse::NoThirdPartySdk);
|
||||||
|
|
||||||
|
create_apple_pay_session_response(
|
||||||
|
router_data,
|
||||||
|
session_response,
|
||||||
|
Some(applepay_payment_request),
|
||||||
|
connector_name.to_string(),
|
||||||
|
delayed_response,
|
||||||
|
payment_types::NextActionCall::Confirm,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_apple_pay_session_response(
|
||||||
|
router_data: &types::PaymentsSessionRouterData,
|
||||||
|
session_response: Option<payment_types::ApplePaySessionResponse>,
|
||||||
|
apple_pay_payment_request: Option<payment_types::ApplePayPaymentRequest>,
|
||||||
|
connector_name: String,
|
||||||
|
delayed_response: bool,
|
||||||
|
next_action: payment_types::NextActionCall,
|
||||||
|
) -> RouterResult<types::PaymentsSessionRouterData> {
|
||||||
|
match session_response {
|
||||||
|
Some(response) => Ok(types::PaymentsSessionRouterData {
|
||||||
|
response: Ok(types::PaymentsResponseData::SessionResponse {
|
||||||
|
session_token: payment_types::SessionToken::ApplePay(Box::new(
|
||||||
|
payment_types::ApplepaySessionTokenResponse {
|
||||||
|
session_token_data: response,
|
||||||
|
payment_request_data: apple_pay_payment_request,
|
||||||
|
connector: connector_name,
|
||||||
|
delayed_session_token: delayed_response,
|
||||||
|
sdk_next_action: { payment_types::SdkNextAction { next_action } },
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
}),
|
||||||
|
..router_data.clone()
|
||||||
}),
|
}),
|
||||||
..router_data.clone()
|
None => Ok(types::PaymentsSessionRouterData {
|
||||||
};
|
response: Ok(types::PaymentsResponseData::SessionResponse {
|
||||||
|
session_token: payment_types::SessionToken::NoSessionTokenReceived,
|
||||||
Ok(response_router_data)
|
}),
|
||||||
|
..router_data.clone()
|
||||||
|
}),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_gpay_session_token(
|
fn create_gpay_session_token(
|
||||||
@ -278,6 +333,18 @@ fn create_gpay_session_token(
|
|||||||
Ok(response_router_data)
|
Ok(response_router_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn log_session_response_if_error(
|
||||||
|
response: &Result<Result<types::Response, types::Response>, Report<errors::ApiClientError>>,
|
||||||
|
) {
|
||||||
|
if let Err(error) = response.as_ref() {
|
||||||
|
logger::error!(?error);
|
||||||
|
};
|
||||||
|
response
|
||||||
|
.as_ref()
|
||||||
|
.ok()
|
||||||
|
.map(|res| res.as_ref().map_err(|error| logger::error!(?error)));
|
||||||
|
}
|
||||||
|
|
||||||
impl types::PaymentsSessionRouterData {
|
impl types::PaymentsSessionRouterData {
|
||||||
pub async fn decide_flow<'a, 'b>(
|
pub async fn decide_flow<'a, 'b>(
|
||||||
&'b self,
|
&'b self,
|
||||||
|
|||||||
@ -315,13 +315,28 @@ async fn payment_response_update_tracker<F: Clone, T: types::Capturable>(
|
|||||||
types::PaymentsResponseData::PreProcessingResponse {
|
types::PaymentsResponseData::PreProcessingResponse {
|
||||||
pre_processing_id,
|
pre_processing_id,
|
||||||
connector_metadata,
|
connector_metadata,
|
||||||
|
..
|
||||||
} => {
|
} => {
|
||||||
|
let connector_transaction_id = match pre_processing_id.to_owned() {
|
||||||
|
types::PreprocessingResponseId::PreProcessingId(_) => None,
|
||||||
|
types::PreprocessingResponseId::ConnectorTransactionId(connector_txn_id) => {
|
||||||
|
Some(connector_txn_id)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let preprocessing_step_id = match pre_processing_id {
|
||||||
|
types::PreprocessingResponseId::PreProcessingId(pre_processing_id) => {
|
||||||
|
Some(pre_processing_id)
|
||||||
|
}
|
||||||
|
types::PreprocessingResponseId::ConnectorTransactionId(_) => None,
|
||||||
|
};
|
||||||
let payment_attempt_update = storage::PaymentAttemptUpdate::PreprocessingUpdate {
|
let payment_attempt_update = storage::PaymentAttemptUpdate::PreprocessingUpdate {
|
||||||
status: router_data.status,
|
status: router_data.status,
|
||||||
payment_method_id: Some(router_data.payment_method_id),
|
payment_method_id: Some(router_data.payment_method_id),
|
||||||
connector_metadata,
|
connector_metadata,
|
||||||
preprocessing_step_id: Some(pre_processing_id),
|
preprocessing_step_id,
|
||||||
|
connector_transaction_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
(Some(payment_attempt_update), None)
|
(Some(payment_attempt_update), None)
|
||||||
}
|
}
|
||||||
types::PaymentsResponseData::TransactionResponse {
|
types::PaymentsResponseData::TransactionResponse {
|
||||||
|
|||||||
@ -377,15 +377,15 @@ where
|
|||||||
for (connector, payment_method_type, business_sub_label) in
|
for (connector, payment_method_type, business_sub_label) in
|
||||||
connector_and_supporting_payment_method_type
|
connector_and_supporting_payment_method_type
|
||||||
{
|
{
|
||||||
if let Ok(connector_data) = api::ConnectorData::get_connector_by_name(
|
let connector_type =
|
||||||
connectors,
|
get_connector_type_for_session_token(payment_method_type, request, &connector);
|
||||||
&connector,
|
if let Ok(connector_data) =
|
||||||
api::GetToken::from(payment_method_type),
|
api::ConnectorData::get_connector_by_name(connectors, &connector, connector_type)
|
||||||
)
|
.map_err(|err| {
|
||||||
.map_err(|err| {
|
logger::error!(session_token_error=?err);
|
||||||
logger::error!(session_token_error=?err);
|
err
|
||||||
err
|
})
|
||||||
}) {
|
{
|
||||||
session_connector_data.push(api::SessionConnectorData {
|
session_connector_data.push(api::SessionConnectorData {
|
||||||
payment_method_type,
|
payment_method_type,
|
||||||
connector: connector_data,
|
connector: connector_data,
|
||||||
@ -412,11 +412,11 @@ impl From<api_models::enums::PaymentMethodType> for api::GetToken {
|
|||||||
|
|
||||||
pub fn get_connector_type_for_session_token(
|
pub fn get_connector_type_for_session_token(
|
||||||
payment_method_type: api_models::enums::PaymentMethodType,
|
payment_method_type: api_models::enums::PaymentMethodType,
|
||||||
_request: &api::PaymentsSessionRequest,
|
request: &api::PaymentsSessionRequest,
|
||||||
connector: String,
|
connector: &str,
|
||||||
) -> api::GetToken {
|
) -> api::GetToken {
|
||||||
if payment_method_type == api_models::enums::PaymentMethodType::ApplePay {
|
if payment_method_type == api_models::enums::PaymentMethodType::ApplePay {
|
||||||
if connector == *"bluesnap" {
|
if is_apple_pay_get_token_connector(connector, request) {
|
||||||
api::GetToken::Connector
|
api::GetToken::Connector
|
||||||
} else {
|
} else {
|
||||||
api::GetToken::ApplePayMetadata
|
api::GetToken::ApplePayMetadata
|
||||||
@ -425,3 +425,11 @@ pub fn get_connector_type_for_session_token(
|
|||||||
api::GetToken::from(payment_method_type)
|
api::GetToken::from(payment_method_type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_apple_pay_get_token_connector(
|
||||||
|
connector: &str,
|
||||||
|
_request: &api::PaymentsSessionRequest,
|
||||||
|
) -> bool {
|
||||||
|
// Add connectors here, which all are required to hit connector for session call
|
||||||
|
matches!(connector, "bluesnap")
|
||||||
|
}
|
||||||
|
|||||||
@ -169,6 +169,7 @@ where
|
|||||||
payment_data.connector_response.authentication_data,
|
payment_data.connector_response.authentication_data,
|
||||||
&operation,
|
&operation,
|
||||||
payment_data.ephemeral_key,
|
payment_data.ephemeral_key,
|
||||||
|
payment_data.sessions_token,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -260,6 +261,7 @@ pub fn payments_to_payments_response<R, Op>(
|
|||||||
redirection_data: Option<serde_json::Value>,
|
redirection_data: Option<serde_json::Value>,
|
||||||
operation: &Op,
|
operation: &Op,
|
||||||
ephemeral_key_option: Option<ephemeral_key::EphemeralKey>,
|
ephemeral_key_option: Option<ephemeral_key::EphemeralKey>,
|
||||||
|
session_tokens: Vec<api::SessionToken>,
|
||||||
) -> RouterResponse<api::PaymentsResponse>
|
) -> RouterResponse<api::PaymentsResponse>
|
||||||
where
|
where
|
||||||
Op: Debug,
|
Op: Debug,
|
||||||
@ -337,6 +339,15 @@ where
|
|||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// next action check for third party sdk session (for ex: Apple pay through trustpay has third party sdk session response)
|
||||||
|
if third_party_sdk_session_next_action(&payment_attempt, operation) {
|
||||||
|
next_action_response = Some(
|
||||||
|
api_models::payments::NextActionData::ThirdPartySdkSessionToken {
|
||||||
|
session_token: session_tokens.get(0).cloned(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
let mut response: api::PaymentsResponse = Default::default();
|
let mut response: api::PaymentsResponse = Default::default();
|
||||||
let routed_through = payment_attempt.connector.clone();
|
let routed_through = payment_attempt.connector.clone();
|
||||||
|
|
||||||
@ -514,6 +525,34 @@ where
|
|||||||
output
|
output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn third_party_sdk_session_next_action<Op>(
|
||||||
|
payment_attempt: &storage::PaymentAttempt,
|
||||||
|
operation: &Op,
|
||||||
|
) -> bool
|
||||||
|
where
|
||||||
|
Op: Debug,
|
||||||
|
{
|
||||||
|
// If the operation is confirm, we will send session token response in next action
|
||||||
|
if format!("{operation:?}").eq("PaymentConfirm") {
|
||||||
|
payment_attempt
|
||||||
|
.connector
|
||||||
|
.as_ref()
|
||||||
|
.map(|connector| matches!(connector.as_str(), "trustpay"))
|
||||||
|
.and_then(|is_connector_supports_third_party_sdk| {
|
||||||
|
if is_connector_supports_third_party_sdk {
|
||||||
|
payment_attempt
|
||||||
|
.payment_method
|
||||||
|
.map(|pm| matches!(pm, storage_models::enums::PaymentMethod::Wallet))
|
||||||
|
} else {
|
||||||
|
Some(false)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.unwrap_or(false)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ForeignFrom<(storage::PaymentIntent, storage::PaymentAttempt)> for api::PaymentsResponse {
|
impl ForeignFrom<(storage::PaymentIntent, storage::PaymentAttempt)> for api::PaymentsResponse {
|
||||||
fn foreign_from(item: (storage::PaymentIntent, storage::PaymentAttempt)) -> Self {
|
fn foreign_from(item: (storage::PaymentIntent, storage::PaymentAttempt)) -> Self {
|
||||||
let pi = item.0;
|
let pi = item.0;
|
||||||
@ -900,6 +939,7 @@ impl<F: Clone> TryFrom<PaymentAdditionalData<'_, F>> for types::PaymentsPreProce
|
|||||||
Ok(Self {
|
Ok(Self {
|
||||||
email: payment_data.email,
|
email: payment_data.email,
|
||||||
currency: Some(payment_data.currency),
|
currency: Some(payment_data.currency),
|
||||||
|
amount: Some(payment_data.amount.into()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -201,6 +201,9 @@ Never share your secret api keys. Keep them guarded and secure.
|
|||||||
api_models::payments::PaymentsSessionResponse,
|
api_models::payments::PaymentsSessionResponse,
|
||||||
api_models::payments::SessionToken,
|
api_models::payments::SessionToken,
|
||||||
api_models::payments::ApplePaySessionResponse,
|
api_models::payments::ApplePaySessionResponse,
|
||||||
|
api_models::payments::ThirdPartySdkSessionResponse,
|
||||||
|
api_models::payments::NoThirdPartySdkSessionResponse,
|
||||||
|
api_models::payments::SecretInfoToInitiateSdk,
|
||||||
api_models::payments::ApplePayPaymentRequest,
|
api_models::payments::ApplePayPaymentRequest,
|
||||||
api_models::payments::AmountInfo,
|
api_models::payments::AmountInfo,
|
||||||
api_models::payments::GooglePayWalletData,
|
api_models::payments::GooglePayWalletData,
|
||||||
@ -216,6 +219,8 @@ Never share your secret api keys. Keep them guarded and secure.
|
|||||||
api_models::payments::KlarnaSessionTokenResponse,
|
api_models::payments::KlarnaSessionTokenResponse,
|
||||||
api_models::payments::PaypalSessionTokenResponse,
|
api_models::payments::PaypalSessionTokenResponse,
|
||||||
api_models::payments::ApplepaySessionTokenResponse,
|
api_models::payments::ApplepaySessionTokenResponse,
|
||||||
|
api_models::payments::SdkNextAction,
|
||||||
|
api_models::payments::NextActionCall,
|
||||||
api_models::payments::GpayTokenizationData,
|
api_models::payments::GpayTokenizationData,
|
||||||
api_models::payments::GooglePayPaymentMethodInfo,
|
api_models::payments::GooglePayPaymentMethodInfo,
|
||||||
api_models::payments::ApplePayWalletData,
|
api_models::payments::ApplePayWalletData,
|
||||||
@ -231,6 +236,7 @@ Never share your secret api keys. Keep them guarded and secure.
|
|||||||
api_models::payments::ReceiverDetails,
|
api_models::payments::ReceiverDetails,
|
||||||
api_models::payments::AchTransfer,
|
api_models::payments::AchTransfer,
|
||||||
api_models::payments::ApplePayRedirectData,
|
api_models::payments::ApplePayRedirectData,
|
||||||
|
api_models::payments::ApplePayThirdPartySdkData,
|
||||||
api_models::payments::GooglePayRedirectData,
|
api_models::payments::GooglePayRedirectData,
|
||||||
api_models::payments::SepaBankTransferInstructions,
|
api_models::payments::SepaBankTransferInstructions,
|
||||||
api_models::payments::BacsBankTransferInstructions,
|
api_models::payments::BacsBankTransferInstructions,
|
||||||
|
|||||||
@ -270,6 +270,7 @@ pub struct PaymentMethodTokenizationData {
|
|||||||
pub struct PaymentsPreProcessingData {
|
pub struct PaymentsPreProcessingData {
|
||||||
pub email: Option<Email>,
|
pub email: Option<Email>,
|
||||||
pub currency: Option<storage_enums::Currency>,
|
pub currency: Option<storage_enums::Currency>,
|
||||||
|
pub amount: Option<i64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -425,11 +426,18 @@ pub enum PaymentsResponseData {
|
|||||||
related_transaction_id: Option<String>,
|
related_transaction_id: Option<String>,
|
||||||
},
|
},
|
||||||
PreProcessingResponse {
|
PreProcessingResponse {
|
||||||
pre_processing_id: String,
|
pre_processing_id: PreprocessingResponseId,
|
||||||
connector_metadata: Option<serde_json::Value>,
|
connector_metadata: Option<serde_json::Value>,
|
||||||
|
session_token: Option<api::SessionToken>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum PreprocessingResponseId {
|
||||||
|
PreProcessingId(String),
|
||||||
|
ConnectorTransactionId(String),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub enum ResponseId {
|
pub enum ResponseId {
|
||||||
ConnectorTransactionId(String),
|
ConnectorTransactionId(String),
|
||||||
|
|||||||
@ -178,6 +178,7 @@ pub enum PaymentAttemptUpdate {
|
|||||||
payment_method_id: Option<Option<String>>,
|
payment_method_id: Option<Option<String>>,
|
||||||
connector_metadata: Option<serde_json::Value>,
|
connector_metadata: Option<serde_json::Value>,
|
||||||
preprocessing_step_id: Option<String>,
|
preprocessing_step_id: Option<String>,
|
||||||
|
connector_transaction_id: Option<String>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,12 +395,14 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
|
|||||||
payment_method_id,
|
payment_method_id,
|
||||||
connector_metadata,
|
connector_metadata,
|
||||||
preprocessing_step_id,
|
preprocessing_step_id,
|
||||||
|
connector_transaction_id,
|
||||||
} => Self {
|
} => Self {
|
||||||
status: Some(status),
|
status: Some(status),
|
||||||
payment_method_id,
|
payment_method_id,
|
||||||
modified_at: Some(common_utils::date_time::now()),
|
modified_at: Some(common_utils::date_time::now()),
|
||||||
connector_metadata,
|
connector_metadata,
|
||||||
preprocessing_step_id,
|
preprocessing_step_id,
|
||||||
|
connector_transaction_id,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user