Overview
If you do not decommission your app versions that include the older SDK versions or force upgrade your app with the updated certificates by the expiration date, 100% of your customer traffic will fail.
App Switch allows buyers with the PayPal app installed to begin their transactions on a merchant's app or website and then seamlessly navigate to the PayPal app to complete their purchase or vault PayPal as a payment method. This feature is enabled through strong multi-factor authentication, allowing buyers to log in Face ID, biometrics or a passkey, rather than entering a password or one-time password (OTP).
In this flow the SDK will attempt to switch to the PayPal App after calling tokenize if the PayPal App is installed and the user meets eligibility requirements. In cases where App Switch isn't available, the user falls back to the existing PayPal web flow, that is, ASWebAuthenticationSession.
This guide is for merchants who are using the Braintree iOS SDK with the following flows:
- Vault flow: Vaulting without purchase
- One-time Checkout: One-time "Pay Now
- App Switch is not yet supported for One-time “Continue” flow or Vaulting with Purchase flow.
- App Switch is currently only supported for US merchants.
Buyer flow
The buyer initiates PayPal checkout within your native mobile application and is seamlessly redirected to the PayPal consumer app to review and approve the Vault or transaction.
- The buyer selects the PayPal button from your app.
- The PayPal app opens, and the buyer is authenticated using low-friction app login mechanisms, such as Face ID, Fingerprint, App Long-Lived Session, or passkey.
- The buyer reviews details and approves the Vault or transaction in the PayPal app.
- The buyer is redirected back to your app.
- Save PayPal as a payment method, or complete the transaction.
It's important to disable the payment button immediately after it's clicked and show a loading indicator while the network call is being made. This prevents duplicate submissions and improves the user experience by signaling that processing is underway.
Eligibility
- Now available in the United States. We will roll out this feature to the EU and other markets.
- App switch is available with One-time payments and Vaulted payments in Pay Now flows only.
Get the SDK
The PayPal App Switch is part of the BraintreePayPal module in the Braintree SDK. This module can be pulled into your app via all of the currently supported package managers.
Cocoapods
In your Podfile, add the dependency for the PayPal Mobile Checkout module:
- Swift
pod 'Braintree/PayPal'Swift Package Manager
Include the BraintreeCore, BraintreePayPal, and PayPalDataCollector frameworks.
Carthage
Include the BraintreeCore, BraintreePayPal and PayPalDataCollector frameworks.
Allowlist PayPal URL Scheme
You must add the following to the queries schemes allowlist in your app's info.plist:
- Swift
<key>LSApplicationQueriesSchemes</key>
<array>
<string>paypal-app-switch-checkout</string>
</array>Set Up Universal Links
In order to use the PayPal App Switch flow your application must be set up for Universal Links. You will need to use a custom path dedicated to Braintree app switch returns. This URL must also be added to your app association file with wildcards allowed to ensure we receive the expected data on return.
An example apple-app-site-association handle may look like the following:
- Swift
{
"applinks": {
"details": [
{
"appID": "com.your-app-id",
"paths": [
"/braintree-payments/*"
]
}
]
}
}Register Universal Link in Control Panel
Before using this feature, you must register your Universal Link domain in the Braintree Control Panel:
- Log into your Control Panel (e.g. Sandbox, or Production).
- Click on the gear icon in the top right corner. A drop-down menu will open.
- Click Account Settings from the drop-down menu.
- Scroll to the Payment Methods section.
- Next to PayPal, click the Options link. This will take you to your linked PayPal Account(s) page.
- Click the View Domain Names button.
- Note: If you have a single PayPal account, it will be at the bottom of the page. If you have multiple PayPal accounts, it will be at the top right of the page.
- Click the + Add link.
- Enter your list of domain names separated by commas.
- Note: The value must match your fully qualified domain name exactly.
- Click Add Domain Names.
- If successful, a confirmation banner will appear.
- If not, the banner will list rejected domains and reasons.
Set Universal Link in SDK
You will need to use the following BTPayPalClient initializer to set your Universal Link:
- Swift
let apiClient = BTAPIClient(authorization: <#CLIENT_AUTHORIZATION#>)
let payPalClient = BTPayPalClient(
apiClient: apiClient, // required
universalLink: URL(string: "https://my-universal-link.com/braintree-payments")! // required
)Handle App Context Switching
Then pass the URL to Braintree for completion of the flow.
If you're using SwiftUI, add the onOpenURL(perform:) modifier to your ContentView, and call BTAppContextSwitcher.handleOpen(_:).
- Swift
.onOpenURL { url in
BTAppContextSwitcher.sharedInstance.handleOpen(url)
}If you're using UISceneDelegate, call handleOpen(_:) inside scene(_:continue:).
- Swift
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
if let returnURL = userActivity.webpageURL, returnURL.path.contains("/my-dedicated-braintree-path") {
BTAppContextSwitcher.sharedInstance.handleOpen(returnURL)
}
}If not using UISceneDelegate, call handleOpen(_:) within application(_:continue:restorationHandler:).
- Swift
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
if let returnURL = userActivity.webpageURL, returnURL.path.contains("/my-dedicated-braintree-path") {
BTAppContextSwitcher.sharedInstance.handleOpen(returnURL)
}
}Invoking the PayPal App Switch Flow
Opt in to the App Switch flow
Construct a BTPayPalVaultRequest or a BTPayPalCheckoutRequest with enablePayPalAppSwitch set to true and a userAuthenticationEmail included. Use this with your BTPayPalClient to call BTPayPalClient.tokenize(_:completion:).
An example integration might look like this:
- Swift
import UIKit
import BraintreePayPal
class MyViewController: UIViewController {
var apiClient: BTAPIClient!
var payPalClient: BTPayPalClient!
let payPalButton = UIButton(type: .system)
override func viewDidLoad() {
super.viewDidLoad()
apiClient = BTAPIClient(authorization: <#CLIENT_AUTHORIZATION#>)
payPalClient = BTPayPalClient(
apiClient: apiClient,
universalLink: universalLink: URL(string: "https://my-universal-link.com/braintree-payments")! // required for this flow
)
setUpButton()
}
private func setUpButton() {
payPalButton.translatesAutoresizingMaskIntoConstraints = false
payPalButton.setTitle("PayPal Checkout", for: .normal)
payPalButton.setTitleColor(.blue, for: .normal)
payPalButton.addTarget(self, action: #selector(payPalButtonTapped), for: .touchUpInside)
view.addSubview(payPalButton)
}
@objc func payPalButtonTapped(_ sender: UIButton) {
sender.isEnabled = false
// one time checkout flows
let request = BTPayPalCheckoutRequest(
amount: amount
userAuthenticationEmail: "[email protected]",
enablePayPalAppSwitch: true
)
// userAuthenticationEmail and enablePayPalAppSwitch are required for this flow
// Configure other values on 'request' as needed.
payPalClient.tokenize(request) { payPalNonce, error in
sender.isEnabled = true
if let payPalNonce {
// send payPalNonce.nonce to server
} else {
// handle error
}
}
}
}Complete Example - Vaulted Payments with App Switch
- Swift
import UIKit
import BraintreePayPal
class VaultedPaymentViewController: UIViewController {
var apiClient: BTAPIClient!
var payPalClient: BTPayPalClient!
override func viewDidLoad() {
super.viewDidLoad()
apiClient = BTAPIClient(authorization: "<#CLIENT_AUTHORIZATION#>")
payPalClient = BTPayPalClient(
apiClient: apiClient,
universalLink: URL(string: "https://my-universal-link.com/braintree-payments")!
)
}
private func payPalButtonTapped() {
// vault flows
let request = BTPayPalVaultRequest(
enablePayPalAppSwitch: true,
userAuthenticationEmail: "[email protected]",
userPhoneNumber: BTPayPalPhoneNumber(
countryCode: "1",
nationalNumber: "2223334444"
)
)
// enablePayPalAppSwitch are required for this flow
// Configure other values on 'request' as needed.
payPalClient.tokenize(request) { payPalNonce, error in
if let payPalNonce {
// send payPalNonce.nonce to server
} else {
// handle error
}
}
}
}For detailed testing procedures and production deployment guidance, see the Testing and Go Live section.