refactor(connector): [paysafe] introduce PaymentMethodToken flow#10541
refactor(connector): [paysafe] introduce PaymentMethodToken flow#10541likhinbopanna merged 12 commits intomainfrom
PaymentMethodToken flow#10541Conversation
Changed Files
|
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #10541 +/- ##
=======================================
Coverage ? 6.42%
=======================================
Files ? 1262
Lines ? 315994
Branches ? 0
=======================================
Hits ? 20292
Misses ? 295702
Partials ? 0 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
PreProcessing flow for PaymentMethodToken flow
PreProcessing flow for PaymentMethodToken flowPaymentMethodToken flow
f4b29e3 to
6a09ca3
Compare
There was a problem hiding this comment.
Pull request overview
This PR refactors the Paysafe connector integration to introduce the PaymentMethodToken flow as a replacement for the deprecated preProcessing flow. However, the implementation is intentionally incomplete to avoid breaking existing 3DS transactions until the upstream unified connector service (UCS) supports granular flow control.
Key changes include:
- Added
router_return_urlandcapture_methodfields toPaymentMethodTokenizationDatastruct - Implemented new
PaymentMethodTokenflow alongside existingPreProcessingflow for Paysafe - Updated UCS dependency version from
f43fbfdbtoe2cb5b7004
Reviewed changes
Copilot reviewed 13 out of 14 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| crates/router/Cargo.toml | Updated UCS client and cards dependency versions |
| crates/hyperswitch_interfaces/Cargo.toml | Updated UCS client dependency version |
| crates/external_services/Cargo.toml | Updated UCS client dependency version |
| Cargo.lock | Updated dependency lock hashes for UCS packages |
| crates/hyperswitch_domain_models/src/router_request_types.rs | Added router_return_url and capture_method fields to PaymentMethodTokenizationData struct and updated TryFrom implementations |
| crates/router/tests/connectors/utils.rs | Initialized new fields in test data structures |
| crates/router/tests/connectors/stax.rs | Initialized new fields in multiple test cases |
| crates/router/tests/connectors/square.rs | Initialized new fields in multiple test cases |
| crates/router/src/core/unified_connector_service/transformers.rs | Added new fields to various request structures and refactored metadata conversion to use helper function |
| crates/router/src/core/payments/flows/setup_mandate_flow.rs | Added Box::pin wrapper to payment_setup_mandate call |
| crates/router/src/core/payment_methods.rs | Initialized new fields in tokenization flow creation |
| crates/hyperswitch_connectors/src/utils.rs | Added get_router_return_url and is_customer_initiated_mandate_payment trait methods |
| crates/hyperswitch_connectors/src/connectors/paysafe.rs | Implemented PaymentMethodToken flow ConnectorIntegration and moved PreProcessing flow to maintain both implementations |
| crates/hyperswitch_connectors/src/connectors/paysafe/transformers.rs | Added TryFrom implementations for TokenizationRouterData, refactored Apple Pay data handling, and updated mandate data retrieval logic |
Comments suppressed due to low confidence (1)
crates/hyperswitch_connectors/src/connectors/paysafe/transformers.rs:1381
- There is significant code duplication in the TryFrom implementations for PaysafeApplepayPayment. The implementations for PaymentsPreProcessingRouterData (lines 1175-1280) and TokenizationRouterData (lines 1282-1381) are nearly identical, with only minor differences in how currency is accessed. This duplication makes the code harder to maintain. Consider extracting the common logic into a helper function or using a macro to reduce duplication.
impl
TryFrom<(
&ApplePayWalletData,
&PaysafeRouterData<&PaymentsPreProcessingRouterData>,
)> for PaysafeApplepayPayment
{
type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(
(wallet_data, item): (
&ApplePayWalletData,
&PaysafeRouterData<&PaymentsPreProcessingRouterData>,
),
) -> Result<Self, Self::Error> {
let apple_pay_payment_token = PaysafeApplePayPaymentToken {
token: PaysafeApplePayToken {
payment_data: if let Ok(PaymentMethodToken::ApplePayDecrypt(ref token)) =
item.router_data.get_payment_method_token()
{
PaysafeApplePayPaymentData::Decrypted(PaysafeApplePayDecryptedDataWrapper {
decrypted_data: get_apple_pay_decrypt_data(
token,
item.router_data
.request
.currency
.ok_or_else(missing_field_err("currency"))?,
item.amount,
)?,
})
} else {
match &wallet_data.payment_data {
ApplePayPaymentData::Decrypted(applepay_predecrypt_data) => {
PaysafeApplePayPaymentData::Decrypted(
PaysafeApplePayDecryptedDataWrapper {
decrypted_data: get_apple_pay_decrypt_data(
applepay_predecrypt_data,
item.router_data
.request
.currency
.ok_or_else(missing_field_err("currency"))?,
item.amount,
)?,
},
)
}
ApplePayPaymentData::Encrypted(applepay_encrypt_data) => {
let decoded_data = base64::prelude::BASE64_STANDARD
.decode(applepay_encrypt_data)
.change_context(errors::ConnectorError::InvalidDataFormat {
field_name: "apple_pay_encrypted_data",
})?;
let apple_pay_token: DecryptedApplePayTokenData =
serde_json::from_slice(&decoded_data).change_context(
errors::ConnectorError::InvalidDataFormat {
field_name: "apple_pay_token_json",
},
)?;
PaysafeApplePayPaymentData::Encrypted(PaysafeApplePayEncryptedData {
data: apple_pay_token.data,
signature: apple_pay_token.signature,
header: PaysafeApplePayHeader {
public_key_hash: apple_pay_token.header.public_key_hash,
ephemeral_public_key: apple_pay_token
.header
.ephemeral_public_key,
transaction_id: apple_pay_token.header.transaction_id,
},
version: apple_pay_token.version,
})
}
}
},
payment_method: PaysafeApplePayPaymentMethod {
display_name: Secret::new(wallet_data.payment_method.display_name.clone()),
network: Secret::new(wallet_data.payment_method.network.clone()),
method_type: Secret::new(wallet_data.payment_method.pm_type.clone()),
},
transaction_identifier: wallet_data.transaction_identifier.clone(),
},
billing_contact: Some(PaysafeApplePayBillingContact {
address_lines: vec![
item.router_data.get_optional_billing_line1(),
item.router_data.get_optional_billing_line2(),
],
postal_code: item.router_data.get_billing_zip()?,
country_code: item.router_data.get_billing_country()?,
country: None,
family_name: None,
given_name: None,
locality: None,
phonetic_family_name: None,
phonetic_given_name: None,
sub_administrative_area: None,
administrative_area: None,
sub_locality: None,
}),
};
Ok(Self {
label: None,
request_billing_address: Some(false),
apple_pay_payment_token,
})
}
}
impl
TryFrom<(
&ApplePayWalletData,
&PaysafeRouterData<&TokenizationRouterData>,
)> for PaysafeApplepayPayment
{
type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(
(wallet_data, item): (
&ApplePayWalletData,
&PaysafeRouterData<&TokenizationRouterData>,
),
) -> Result<Self, Self::Error> {
let apple_pay_payment_token = PaysafeApplePayPaymentToken {
token: PaysafeApplePayToken {
payment_data: if let Ok(PaymentMethodToken::ApplePayDecrypt(ref token)) =
item.router_data.get_payment_method_token()
{
PaysafeApplePayPaymentData::Decrypted(PaysafeApplePayDecryptedDataWrapper {
decrypted_data: get_apple_pay_decrypt_data(
token,
item.router_data.request.currency,
item.amount,
)?,
})
} else {
match &wallet_data.payment_data {
ApplePayPaymentData::Decrypted(applepay_predecrypt_data) => {
PaysafeApplePayPaymentData::Decrypted(
PaysafeApplePayDecryptedDataWrapper {
decrypted_data: get_apple_pay_decrypt_data(
applepay_predecrypt_data,
item.router_data.request.currency,
item.amount,
)?,
},
)
}
ApplePayPaymentData::Encrypted(applepay_encrypt_data) => {
let decoded_data = base64::prelude::BASE64_STANDARD
.decode(applepay_encrypt_data)
.change_context(errors::ConnectorError::InvalidDataFormat {
field_name: "apple_pay_encrypted_data",
})?;
let apple_pay_token: DecryptedApplePayTokenData =
serde_json::from_slice(&decoded_data).change_context(
errors::ConnectorError::InvalidDataFormat {
field_name: "apple_pay_token_json",
},
)?;
PaysafeApplePayPaymentData::Encrypted(PaysafeApplePayEncryptedData {
data: apple_pay_token.data,
signature: apple_pay_token.signature,
header: PaysafeApplePayHeader {
public_key_hash: apple_pay_token.header.public_key_hash,
ephemeral_public_key: apple_pay_token
.header
.ephemeral_public_key,
transaction_id: apple_pay_token.header.transaction_id,
},
version: apple_pay_token.version,
})
}
}
},
payment_method: PaysafeApplePayPaymentMethod {
display_name: Secret::new(wallet_data.payment_method.display_name.clone()),
network: Secret::new(wallet_data.payment_method.network.clone()),
method_type: Secret::new(wallet_data.payment_method.pm_type.clone()),
},
transaction_identifier: wallet_data.transaction_identifier.clone(),
},
billing_contact: Some(PaysafeApplePayBillingContact {
address_lines: vec![
item.router_data.get_optional_billing_line1(),
item.router_data.get_optional_billing_line2(),
],
postal_code: item.router_data.get_billing_zip()?,
country_code: item.router_data.get_billing_country()?,
country: None,
family_name: None,
given_name: None,
locality: None,
phonetic_family_name: None,
phonetic_given_name: None,
sub_administrative_area: None,
administrative_area: None,
sub_locality: None,
}),
};
Ok(Self {
label: None,
request_billing_address: Some(false),
apple_pay_payment_token,
})
}
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| } | ||
| } | ||
|
|
||
| impl TryFrom<&PaysafeRouterData<&TokenizationRouterData>> for PaysafePaymentHandleRequest { |
There was a problem hiding this comment.
Can you try to reuse existing transformers logic that is already available for PreProcessing.
…aysafe-flow-correction * 'main' of github.com:juspay/hyperswitch: (47 commits) fix: implement is_pre_authentication_flow_required function for nmi (#10692) chore(version): 2025.12.17.0 fix: Corrected the mapping of metadata fields in HS<>UCS tunnel (#10626) fix(users): Check if the inviter role info entity type is greater than invitee (#10667) feat(payouts): [WorldpayWPG] Implement fast access feature of worldpaywpg for payouts (#10647) fix(oidc): registration of oidc paths (#10678) feat(connector): [Peach Payments] Add Pre-Auth Flow With Full Reversal (#10590) fix(payouts): add fallback for names for payout via Psp token (#10502) feat(euclid): support for issuer_country based routing (#10638) feat: implement granular authentication flow for UCS gateway interfaces (#10622) feat(euclid): support for transaction_initiator based routing (#10658) feat(gsm): add standardised error fields to GSM models and database schema (#10600) feat(payments): change lookup for find gsm code and message (#10585) feat: Added Paypal Post Auth Flow for HS<>UCS tunnel (#10640) feat: Added PreAuthenticate Flow for Nmi HS<>UCS tunnel (#10632) chore(version): 2025.12.16.0 feat: implement generic Locker api handler (#10242) fix(user-role): add entity type validation in user role lineage queries (#10608) ci: add API and database Schema validation workflow (#9710) feat(oidc): Add OIDC infrastructure and discovery endpoints (#10145) ...
Sakilmostak
left a comment
There was a problem hiding this comment.
looks good at payment-methods
…pm-metadata * 'main' of github.com:juspay/hyperswitch: chore(version): 2025.12.22.0 feat(braintree): add UCS wallet support for PaypalSdk, ApplePayThirdPartySdk, and GooglePayThirdPartySdk (#10513) Fix: WorldpayVantiv Cypress fix (#10656) feat(connector): Add Apple Pay HS-Decryption support for Braintree (#10734) ci(cypress): add bank redirect flow onlinebankingfpx for fiuu (#10642) chore(version): 2025.12.19.0 refactor(connector): [paysafe] introduce `PaymentMethodToken` flow (#10541) fix(connectors): add 3ds validations for connector for card specific only (#10560) fix(router): Prevent panic when masking non-ASCII strings (#10682) feat(authentication): add domain models for authentication and support kafka filters in dashboard (#10446) fix(docker): increase RUST_MIN_STACK size to handle stack overflow (#10730) fix(api): align ApiEvent status_code with HTTP response when proxy_connector_http_status_code enabled (#10680) feat(core): [Network Token] Passing Network Token in payments request (#9975) feat(core): Bumped UCS Client dependency to bring latest changes (#10641) ci(cypress): Update cypress shadow mode rollout configs (#10689)
…rmers * 'main' of github.com:juspay/hyperswitch: (67 commits) refactor: Introduce PreAuth for redsys HS<>UCS tunnel (#10727) chore(version): 2025.12.22.0 feat(braintree): add UCS wallet support for PaypalSdk, ApplePayThirdPartySdk, and GooglePayThirdPartySdk (#10513) Fix: WorldpayVantiv Cypress fix (#10656) feat(connector): Add Apple Pay HS-Decryption support for Braintree (#10734) ci(cypress): add bank redirect flow onlinebankingfpx for fiuu (#10642) chore(version): 2025.12.19.0 refactor(connector): [paysafe] introduce `PaymentMethodToken` flow (#10541) fix(connectors): add 3ds validations for connector for card specific only (#10560) fix(router): Prevent panic when masking non-ASCII strings (#10682) feat(authentication): add domain models for authentication and support kafka filters in dashboard (#10446) fix(docker): increase RUST_MIN_STACK size to handle stack overflow (#10730) fix(api): align ApiEvent status_code with HTTP response when proxy_connector_http_status_code enabled (#10680) feat(core): [Network Token] Passing Network Token in payments request (#9975) feat(core): Bumped UCS Client dependency to bring latest changes (#10641) ci(cypress): Update cypress shadow mode rollout configs (#10689) chore(version): 2025.12.18.0 feat(payment-methods): Add support for guest checkout flow in payment method service (#10487) feat(connector): [NMI] Implement Apple Pay - hyperswitch decryption flow (#10686) fix(connector): [bluesnap] pass `connector_request_ref_id` instead of `payment_id` (#10653) ...
Type of Change
Description
this pr is aimed at refactoring the paysafe connector integration. the mail goal of this pr is to replace
preProcessingflow withpaymentMethodTokenflow. however, introduction ofpaymentMethodTokenflow in paysafe will break 3ds transactions due to below given reasons:paymentMethodTokenflow is not granular (yet). this will get called beforeauthorizeauthorizeorpaymentMethodTokenflow for a specificauthentication_typehence, this pr introduces the
paymentMethodTokenflow to replace thepreProcessingflow but it is intentionally made to not work just so that it does not affect the existing integration.Important
ucs will be bumped once the corresponding fix for paysafe is merged in ucs
Additional Changes
Motivation and Context
preProcessingflow is wrong. we get a token in the response. we should be usingpaymentMethodTokenflow instead for no3ds cards and applepay.for 3ds cards, authorize flow is expected since that flow tokenizes and authenticates the user.
How did you test it?
existing no 3ds and applepay payment methods should not be affected:
Cards -- No3DS
{ "payment_id": "pay_AEYIlTwKhUaMQyyVWdNe", "merchant_id": "postman_merchant_GHAction_1765193570", "status": "succeeded", "amount": 4000, "net_amount": 4000, "shipping_cost": null, "amount_capturable": 0, "amount_received": 4000, "connector": "paysafe", "client_secret": "pay_AEYIlTwKhUaMQyyVWdNe_secret_9F3PF1GaxtFS24131yU9", "created": "2025-12-08T11:32:57.896Z", "modified_at": "2025-12-08T11:32:59.498Z", "currency": "USD", "customer_id": "customer", "customer": { "id": "customer", "name": null, "email": "guesjhvghht@example.com", "phone": "999999999", "phone_country_code": "+1" }, "description": "Its my first payment request", "refunds": null, "disputes": null, "mandate_id": null, "mandate_data": null, "setup_future_usage": null, "off_session": null, "capture_on": null, "capture_method": "automatic", "payment_method": "card", "payment_method_data": { "card": { "last4": "1091", "card_type": "CREDIT", "card_network": "Visa", "card_issuer": "INTL HDQTRS-CENTER OWNED", "card_issuing_country": "UNITEDSTATES", "card_isin": "400000", "card_extended_bin": null, "card_exp_month": "10", "card_exp_year": "30", "card_holder_name": "Joseph", "payment_checks": null, "authentication_data": null }, "billing": null }, "payment_token": null, "shipping": { "address": { "city": "San Fransico", "country": "US", "line1": "1467", "line2": "Harrison Street", "line3": "Harrison Street", "zip": "94122", "state": "California", "first_name": "PiX", "last_name": null, "origin_zip": null }, "phone": null, "email": null }, "billing": { "address": { "city": "San Fransico", "country": "US", "line1": "1467", "line2": "Harrison Street", "line3": "Harrison Street", "zip": "94122", "state": "California", "first_name": "PiX", "last_name": "THE", "origin_zip": null }, "phone": null, "email": null }, "order_details": null, "email": "guesjhvghht@example.com", "name": null, "phone": "999999999", "return_url": "https://duck.com/", "authentication_type": "no_three_ds", "statement_descriptor_name": "joseph", "statement_descriptor_suffix": "JS", "next_action": null, "cancellation_reason": null, "error_code": null, "error_message": null, "unified_code": null, "unified_message": null, "payment_experience": null, "payment_method_type": "credit", "connector_label": null, "business_country": null, "business_label": "default", "business_sub_label": null, "allowed_payment_method_types": null, "ephemeral_key": { "customer_id": "customer", "created_at": 1765193577, "expires": 1765197177, "secret": "epk_03767cafb717462cbcc04e7fdba0f1b8" }, "manual_retry_allowed": null, "connector_transaction_id": "b4f7dcbf-e26d-4551-b15b-61be7c143740", "frm_message": null, "metadata": { "udf1": "value1", "login_date": "2019-09-10T10:11:12Z", "new_customer": "true" }, "connector_metadata": null, "feature_metadata": { "redirect_response": null, "search_tags": null, "apple_pay_recurring_details": null, "gateway_system": "direct" }, "reference_id": null, "payment_link": null, "profile_id": "pro_1bgv1EqLZpII2LhrqZ6v", "surcharge_details": null, "attempt_count": 1, "merchant_decision": null, "merchant_connector_id": "mca_5JI6HUfzajWqeytwQWPc", "incremental_authorization_allowed": false, "authorization_count": null, "incremental_authorizations": null, "external_authentication_details": null, "external_3ds_authentication_attempted": false, "expires_on": "2025-12-08T11:47:57.896Z", "fingerprint": null, "browser_info": { "language": "en-GB", "time_zone": -330, "ip_address": "208.127.127.193", "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0", "color_depth": 24, "java_enabled": true, "screen_width": 1280, "accept_header": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8", "screen_height": 720, "java_script_enabled": true }, "payment_channel": null, "payment_method_id": null, "network_transaction_id": null, "payment_method_status": null, "updated": "2025-12-08T11:32:59.498Z", "split_payments": null, "frm_metadata": null, "extended_authorization_applied": null, "extended_authorization_last_applied_at": null, "request_extended_authorization": null, "capture_before": null, "merchant_order_reference_id": null, "order_tax_amount": null, "connector_mandate_id": null, "card_discovery": "manual", "force_3ds_challenge": false, "force_3ds_challenge_trigger": false, "issuer_error_code": null, "issuer_error_message": null, "is_iframe_redirection_enabled": null, "whole_connector_response": null, "enable_partial_authorization": null, "enable_overcapture": null, "is_overcapture_enabled": null, "network_details": null, "is_stored_credential": null, "mit_category": null, "billing_descriptor": null, "tokenization": null, "partner_merchant_identifier_details": null, "payment_method_tokenization_details": null }ApplePay -- Predecrypt
{ "payment_id": "pay_ndmQWvahx8Qe4z8sQ2tJ", "merchant_id": "postman_merchant_GHAction_1765211283", "status": "succeeded", "amount": 1000, "net_amount": 1000, "shipping_cost": null, "amount_capturable": 0, "amount_received": 1000, "connector": "paysafe", "client_secret": "pay_ndmQWvahx8Qe4z8sQ2tJ_secret_2xWyC4bezvWdFfs78JfF", "created": "2025-12-08T16:28:18.010Z", "modified_at": "2025-12-08T16:28:23.374Z", "currency": "USD", "customer_id": "StripeCustomer", "customer": { "id": "StripeCustomer", "name": "John Doe", "email": "likhin.bopanna@gmail.com", "phone": "999999999", "phone_country_code": "+65" }, "description": "Its my first payment request", "refunds": null, "disputes": null, "mandate_id": null, "mandate_data": null, "setup_future_usage": null, "off_session": null, "capture_on": null, "capture_method": "automatic", "payment_method": "wallet", "payment_method_data": { "wallet": { "apple_pay": { "last4": "4228", "card_network": "Mastercard", "type": "debit", "card_exp_month": "01", "card_exp_year": "30" } }, "billing": null }, "payment_token": null, "shipping": { "address": { "city": "San Fransico", "country": "US", "line1": "1467", "line2": "Harrison Street", "line3": "Harrison Street", "zip": "94122", "state": "California", "first_name": "John", "last_name": "Doe", "origin_zip": null }, "phone": null, "email": null }, "billing": { "address": { "city": "San Fransico", "country": "US", "line1": "1467", "line2": "Harrison Street", "line3": "Harrison Street", "zip": "94122", "state": "California", "first_name": "John", "last_name": "Doe", "origin_zip": null }, "phone": null, "email": null }, "order_details": null, "email": "likhin.bopanna@gmail.com", "name": "John Doe", "phone": "999999999", "return_url": "https://duck.com/", "authentication_type": "three_ds", "statement_descriptor_name": "joseph", "statement_descriptor_suffix": "JS", "next_action": null, "cancellation_reason": null, "error_code": null, "error_message": null, "unified_code": null, "unified_message": null, "payment_experience": null, "payment_method_type": "apple_pay", "connector_label": "paysafe_US_default", "business_country": "US", "business_label": "default", "business_sub_label": null, "allowed_payment_method_types": null, "ephemeral_key": null, "manual_retry_allowed": null, "connector_transaction_id": "a0813723-4573-461d-81a3-9d961246f9d7", "frm_message": null, "metadata": { "udf1": "value1", "login_date": "2019-09-10T10:11:12Z", "new_customer": "true" }, "connector_metadata": null, "feature_metadata": { "redirect_response": null, "search_tags": null, "apple_pay_recurring_details": null, "gateway_system": "direct" }, "reference_id": null, "payment_link": null, "profile_id": "pro_T9unWs1Yhy7L9ySqL9mT", "surcharge_details": null, "attempt_count": 1, "merchant_decision": null, "merchant_connector_id": "mca_czCRiYiJLertOMihXZJM", "incremental_authorization_allowed": false, "authorization_count": null, "incremental_authorizations": null, "external_authentication_details": null, "external_3ds_authentication_attempted": false, "expires_on": "2025-12-08T16:43:18.010Z", "fingerprint": null, "browser_info": { "os_type": null, "referer": null, "language": "nl-NL", "time_zone": 0, "ip_address": "127.0.0.1", "os_version": null, "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36", "color_depth": 24, "device_model": null, "java_enabled": true, "screen_width": 1536, "accept_header": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8", "screen_height": 723, "accept_language": "en", "java_script_enabled": true }, "payment_channel": null, "payment_method_id": null, "network_transaction_id": null, "payment_method_status": null, "updated": "2025-12-08T16:28:23.374Z", "split_payments": null, "frm_metadata": null, "extended_authorization_applied": null, "extended_authorization_last_applied_at": null, "request_extended_authorization": null, "capture_before": null, "merchant_order_reference_id": null, "order_tax_amount": null, "connector_mandate_id": null, "card_discovery": null, "force_3ds_challenge": false, "force_3ds_challenge_trigger": false, "issuer_error_code": null, "issuer_error_message": null, "is_iframe_redirection_enabled": null, "whole_connector_response": null, "enable_partial_authorization": null, "enable_overcapture": null, "is_overcapture_enabled": null, "network_details": null, "is_stored_credential": null, "mit_category": null, "billing_descriptor": null, "tokenization": null, "partner_merchant_identifier_details": null, "payment_method_tokenization_details": null }ApplePay -- Hyperswitch Decryption
{ "payment_id": "pay_MLJwKrnIOAvjENNCvWWN", "merchant_id": "postman_merchant_GHAction_1765211283", "status": "succeeded", "amount": 1000, "net_amount": 1000, "shipping_cost": null, "amount_capturable": 0, "amount_received": 1000, "connector": "paysafe", "client_secret": "pay_MLJwKrnIOAvjENNCvWWN_secret_plfLi20sU6m92EhAGz78", "created": "2025-12-08T16:29:58.814Z", "modified_at": "2025-12-08T16:30:02.799Z", "currency": "USD", "customer_id": "StripeCustomer", "customer": { "id": "StripeCustomer", "name": "John Doe", "email": "likhin.bopanna@gmail.com", "phone": "999999999", "phone_country_code": "+65" }, "description": "Its my first payment request", "refunds": null, "disputes": null, "mandate_id": null, "mandate_data": null, "setup_future_usage": null, "off_session": null, "capture_on": null, "capture_method": "automatic", "payment_method": "wallet", "payment_method_data": { "wallet": { "apple_pay": { "last4": "4228", "card_network": "Visa", "type": "debit", "card_exp_month": "01", "card_exp_year": "2030" } }, "billing": null }, "payment_token": null, "shipping": { "address": { "city": "San Fransico", "country": "US", "line1": "1467", "line2": "Harrison Street", "line3": "Harrison Street", "zip": "94122", "state": "California", "first_name": "John", "last_name": "Doe", "origin_zip": null }, "phone": null, "email": null }, "billing": { "address": { "city": "San Fransico", "country": "US", "line1": "1467", "line2": "Harrison Street", "line3": "Harrison Street", "zip": "94122", "state": "California", "first_name": "John", "last_name": "Doe", "origin_zip": null }, "phone": null, "email": null }, "order_details": null, "email": "likhin.bopanna@gmail.com", "name": "John Doe", "phone": "999999999", "return_url": "https://duck.com/", "authentication_type": "three_ds", "statement_descriptor_name": "joseph", "statement_descriptor_suffix": "JS", "next_action": null, "cancellation_reason": null, "error_code": null, "error_message": null, "unified_code": null, "unified_message": null, "payment_experience": null, "payment_method_type": "apple_pay", "connector_label": "paysafe_US_default", "business_country": "US", "business_label": "default", "business_sub_label": null, "allowed_payment_method_types": null, "ephemeral_key": null, "manual_retry_allowed": null, "connector_transaction_id": "f773089f-722b-49fd-b4db-1396acef0645", "frm_message": null, "metadata": { "udf1": "value1", "login_date": "2019-09-10T10:11:12Z", "new_customer": "true" }, "connector_metadata": null, "feature_metadata": { "redirect_response": null, "search_tags": null, "apple_pay_recurring_details": null, "gateway_system": "direct" }, "reference_id": null, "payment_link": null, "profile_id": "pro_T9unWs1Yhy7L9ySqL9mT", "surcharge_details": null, "attempt_count": 1, "merchant_decision": null, "merchant_connector_id": "mca_czCRiYiJLertOMihXZJM", "incremental_authorization_allowed": false, "authorization_count": null, "incremental_authorizations": null, "external_authentication_details": null, "external_3ds_authentication_attempted": false, "expires_on": "2025-12-08T16:44:58.814Z", "fingerprint": null, "browser_info": { "os_type": null, "referer": null, "language": "nl-NL", "time_zone": 0, "ip_address": "127.0.0.1", "os_version": null, "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36", "color_depth": 24, "device_model": null, "java_enabled": true, "screen_width": 1536, "accept_header": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8", "screen_height": 723, "accept_language": "en", "java_script_enabled": true }, "payment_channel": null, "payment_method_id": null, "network_transaction_id": null, "payment_method_status": null, "updated": "2025-12-08T16:30:02.799Z", "split_payments": null, "frm_metadata": null, "extended_authorization_applied": null, "extended_authorization_last_applied_at": null, "request_extended_authorization": null, "capture_before": null, "merchant_order_reference_id": null, "order_tax_amount": null, "connector_mandate_id": null, "card_discovery": null, "force_3ds_challenge": false, "force_3ds_challenge_trigger": false, "issuer_error_code": null, "issuer_error_message": null, "is_iframe_redirection_enabled": null, "whole_connector_response": null, "enable_partial_authorization": null, "enable_overcapture": null, "is_overcapture_enabled": null, "network_details": null, "is_stored_credential": null, "mit_category": null, "billing_descriptor": null, "tokenization": null, "partner_merchant_identifier_details": null, "payment_method_tokenization_details": null }cypress
three 3ds transactions do not return redirect url. request has been raised to paysafe team. the same is reproducible on sandbox too.
it might be because, the card number that the documentation points to is 10/25 which is expired and it has never been updated since then.
Checklist
cargo +nightly fmt --alljust clippy && just clippy_v2