Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(router): skip apple pay session call if the browser is not Safari #5136

Merged
merged 7 commits into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 17 additions & 6 deletions api-reference/openapi_spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -5201,6 +5201,13 @@
}
}
},
"ApplepayInitiative": {
"type": "string",
"enum": [
"web",
"ios"
]
},
"ApplepayPaymentMethod": {
"type": "object",
"required": [
Expand All @@ -5226,14 +5233,18 @@
"ApplepaySessionTokenResponse": {
"type": "object",
"required": [
"session_token_data",
"connector",
"delayed_session_token",
"sdk_next_action"
],
"properties": {
"session_token_data": {
"$ref": "#/components/schemas/ApplePaySessionResponse"
"allOf": [
{
"$ref": "#/components/schemas/ApplePaySessionResponse"
}
],
"nullable": true
},
"payment_request_data": {
"allOf": [
Expand Down Expand Up @@ -19434,8 +19445,7 @@
"certificate_keys",
"merchant_identifier",
"display_name",
"initiative",
"initiative_context"
"initiative"
],
"properties": {
"certificate": {
Expand All @@ -19451,10 +19461,11 @@
"type": "string"
},
"initiative": {
"type": "string"
"$ref": "#/components/schemas/ApplepayInitiative"
},
"initiative_context": {
"type": "string"
"type": "string",
"nullable": true
},
"merchant_business_country": {
"allOf": [
Expand Down
18 changes: 15 additions & 3 deletions crates/api_models/src/payments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use serde::{
ser::Serializer,
Deserialize, Deserializer, Serialize,
};
use strum::Display;
use time::{Date, PrimitiveDateTime};
use url::Url;
use utoipa::ToSchema;
Expand Down Expand Up @@ -592,6 +593,8 @@ pub struct HeaderPayload {
pub client_source: Option<String>,
pub client_version: Option<String>,
pub x_hs_latency: Option<bool>,
pub browser_name: Option<api_enums::BrowserName>,
pub x_client_platform: Option<api_enums::ClientPlatform>,
}

impl HeaderPayload {
Expand Down Expand Up @@ -4299,14 +4302,21 @@ pub struct SessionTokenInfo {
pub certificate_keys: Secret<String>,
pub merchant_identifier: String,
pub display_name: String,
pub initiative: String,
pub initiative_context: String,
pub initiative: ApplepayInitiative,
pub initiative_context: Option<String>,
#[schema(value_type = Option<CountryAlpha2>)]
pub merchant_business_country: Option<api_enums::CountryAlpha2>,
#[serde(flatten)]
pub payment_processing_details_at: Option<PaymentProcessingDetailsAt>,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Display, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum ApplepayInitiative {
Web,
Ios,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
#[serde(tag = "payment_processing_details_at")]
pub enum PaymentProcessingDetailsAt {
Expand Down Expand Up @@ -4421,7 +4431,9 @@ pub struct PaypalSessionTokenResponse {
#[serde(rename_all = "lowercase")]
pub struct ApplepaySessionTokenResponse {
/// Session object for Apple Pay
pub session_token_data: ApplePaySessionResponse,
/// The session_token_data will be null for iOS devices because the Apple Pay session call is skipped, as there is no web domain involved
#[serde(skip_serializing_if = "Option::is_none")]
pub session_token_data: Option<ApplePaySessionResponse>,
/// Payment request object for Apple Pay
pub payment_request_data: Option<ApplePayPaymentRequest>,
/// The session token is w.r.t this connector
Expand Down
18 changes: 18 additions & 0 deletions crates/common_enums/src/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2258,6 +2258,24 @@ pub enum PaymentSource {
ExternalAuthenticator,
}

#[derive(Default, Debug, Clone, serde::Deserialize, serde::Serialize, strum::EnumString)]
ShankarSinghC marked this conversation as resolved.
Show resolved Hide resolved
pub enum BrowserName {
#[default]
Safari,
#[serde(other)]
Unknown,
}

#[derive(Default, Debug, Clone, serde::Deserialize, serde::Serialize, strum::EnumString)]
#[strum(serialize_all = "snake_case")]
pub enum ClientPlatform {
#[default]
Web,
Ios,
#[serde(other)]
Unknown,
}

impl PaymentSource {
pub fn is_for_internal_use_only(&self) -> bool {
match self {
Expand Down
1 change: 1 addition & 0 deletions crates/openapi/src/openapi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@ Never share your secret api keys. Keep them guarded and secure.
api_models::payments::ApplepayConnectorMetadataRequest,
api_models::payments::SessionTokenInfo,
api_models::payments::PaymentProcessingDetailsAt,
api_models::payments::ApplepayInitiative,
api_models::payments::PaymentProcessingDetails,
api_models::payments::PaymentMethodDataResponseWithBilling,
api_models::payments::PaymentMethodDataResponse,
Expand Down
12 changes: 9 additions & 3 deletions crates/router/src/connector/bluesnap/transformers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -461,10 +461,16 @@ impl TryFrom<&types::PaymentsSessionRouterData> for BluesnapCreateWalletToken {
})
}
}?;
let domain_name = session_token_data.initiative_context.ok_or(
errors::ConnectorError::MissingRequiredField {
field_name: "apple pay initiative_context",
},
)?;

Ok(Self {
wallet_type: "APPLE_PAY".to_string(),
validation_url: consts::APPLEPAY_VALIDATION_URL.to_string().into(),
domain_name: session_token_data.initiative_context,
domain_name,
display_name: Some(session_token_data.display_name),
})
}
Expand Down Expand Up @@ -529,8 +535,8 @@ impl
response: Ok(types::PaymentsResponseData::SessionResponse {
session_token: api::SessionToken::ApplePay(Box::new(
payments::ApplepaySessionTokenResponse {
session_token_data: payments::ApplePaySessionResponse::NoThirdPartySdk(
session_response,
session_token_data: Some(
payments::ApplePaySessionResponse::NoThirdPartySdk(session_response),
),
payment_request_data: Some(payments::ApplePayPaymentRequest {
country_code: item.data.get_billing_country()?,
Expand Down
3 changes: 2 additions & 1 deletion crates/router/src/connector/payme/transformers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -553,8 +553,9 @@ impl<F>
_,
))) => Some(api_models::payments::SessionToken::ApplePay(Box::new(
api_models::payments::ApplepaySessionTokenResponse {
session_token_data:
session_token_data: Some(
api_models::payments::ApplePaySessionResponse::NoSessionResponse,
),
payment_request_data: Some(
api_models::payments::ApplePayPaymentRequest {
country_code: item.data.get_billing_country()?,
Expand Down
3 changes: 2 additions & 1 deletion crates/router/src/connector/trustpay/transformers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1209,12 +1209,13 @@ pub fn get_apple_pay_session<F, T>(
pre_processing_id: types::PreprocessingResponseId::ConnectorTransactionId(instance_id),
session_token: Some(types::api::SessionToken::ApplePay(Box::new(
api_models::payments::ApplepaySessionTokenResponse {
session_token_data:
session_token_data: Some(
api_models::payments::ApplePaySessionResponse::ThirdPartySdk(
api_models::payments::ThirdPartySdkSessionResponse {
secrets: secrets.to_owned().into(),
},
),
),
payment_request_data: Some(api_models::payments::ApplePayPaymentRequest {
country_code: apple_pay_init_result.country_code,
currency_code: apple_pay_init_result.currency_code,
Expand Down
4 changes: 4 additions & 0 deletions crates/router/src/core/payments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,7 @@ where
&customer,
session_surcharge_details,
&business_profile,
header_payload.clone(),
))
.await?
}
Expand Down Expand Up @@ -1610,6 +1611,7 @@ where
call_connector_action,
connector_request,
business_profile,
header_payload.clone(),
)
.await
} else {
Expand Down Expand Up @@ -1673,6 +1675,7 @@ pub async fn call_multiple_connectors_service<F, Op, Req>(
customer: &Option<domain::Customer>,
session_surcharge_details: Option<api::SessionSurchargeDetails>,
business_profile: &storage::business_profile::BusinessProfile,
header_payload: HeaderPayload,
) -> RouterResult<PaymentData<F>>
where
Op: Debug,
Expand Down Expand Up @@ -1736,6 +1739,7 @@ where
CallConnectorAction::Trigger,
None,
business_profile,
header_payload.clone(),
);

join_handlers.push(res);
Expand Down
1 change: 1 addition & 0 deletions crates/router/src/core/payments/flows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ pub trait Feature<F, T> {
call_connector_action: payments::CallConnectorAction,
connector_request: Option<services::Request>,
business_profile: &storage::business_profile::BusinessProfile,
header_payload: api_models::payments::HeaderPayload,
) -> RouterResult<Self>
where
Self: Sized,
Expand Down
1 change: 1 addition & 0 deletions crates/router/src/core/payments/flows/approve_flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ impl Feature<api::Approve, types::PaymentsApproveData>
_call_connector_action: payments::CallConnectorAction,
_connector_request: Option<services::Request>,
_business_profile: &storage::business_profile::BusinessProfile,
_header_payload: api_models::payments::HeaderPayload,
) -> RouterResult<Self> {
Err(ApiErrorResponse::NotImplemented {
message: NotImplementedMessage::Reason("Flow not supported".to_string()),
Expand Down
1 change: 1 addition & 0 deletions crates/router/src/core/payments/flows/authorize_flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ impl Feature<api::Authorize, types::PaymentsAuthorizeData> for types::PaymentsAu
call_connector_action: payments::CallConnectorAction,
connector_request: Option<services::Request>,
_business_profile: &storage::business_profile::BusinessProfile,
_header_payload: api_models::payments::HeaderPayload,
) -> RouterResult<Self> {
let connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
api::Authorize,
Expand Down
1 change: 1 addition & 0 deletions crates/router/src/core/payments/flows/cancel_flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ impl Feature<api::Void, types::PaymentsCancelData>
call_connector_action: payments::CallConnectorAction,
connector_request: Option<services::Request>,
_business_profile: &storage::business_profile::BusinessProfile,
_header_payload: api_models::payments::HeaderPayload,
) -> RouterResult<Self> {
metrics::PAYMENT_CANCEL_COUNT.add(
&metrics::CONTEXT,
Expand Down
1 change: 1 addition & 0 deletions crates/router/src/core/payments/flows/capture_flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ impl Feature<api::Capture, types::PaymentsCaptureData>
call_connector_action: payments::CallConnectorAction,
connector_request: Option<services::Request>,
_business_profile: &storage::business_profile::BusinessProfile,
_header_payload: api_models::payments::HeaderPayload,
) -> RouterResult<Self> {
let connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
api::Capture,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ impl Feature<api::CompleteAuthorize, types::CompleteAuthorizeData>
call_connector_action: payments::CallConnectorAction,
connector_request: Option<services::Request>,
_business_profile: &storage::business_profile::BusinessProfile,
_header_payload: api_models::payments::HeaderPayload,
) -> RouterResult<Self> {
let connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
api::CompleteAuthorize,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ impl Feature<api::IncrementalAuthorization, types::PaymentsIncrementalAuthorizat
call_connector_action: payments::CallConnectorAction,
connector_request: Option<services::Request>,
_business_profile: &storage::business_profile::BusinessProfile,
_header_payload: api_models::payments::HeaderPayload,
) -> RouterResult<Self> {
let connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
api::IncrementalAuthorization,
Expand Down
1 change: 1 addition & 0 deletions crates/router/src/core/payments/flows/psync_flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ impl Feature<api::PSync, types::PaymentsSyncData>
call_connector_action: payments::CallConnectorAction,
connector_request: Option<services::Request>,
_business_profile: &storage::business_profile::BusinessProfile,
_header_payload: api_models::payments::HeaderPayload,
) -> RouterResult<Self> {
let connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
api::PSync,
Expand Down
1 change: 1 addition & 0 deletions crates/router/src/core/payments/flows/reject_flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ impl Feature<api::Reject, types::PaymentsRejectData>
_call_connector_action: payments::CallConnectorAction,
_connector_request: Option<services::Request>,
_business_profile: &storage::business_profile::BusinessProfile,
_header_payload: api_models::payments::HeaderPayload,
) -> RouterResult<Self> {
Err(ApiErrorResponse::NotImplemented {
message: NotImplementedMessage::Reason("Flow not supported".to_string()),
Expand Down
Loading
Loading