Overview
App Switch enables PayPal users who have a PayPal app installed on their phone to complete payment on the app when it is available.
In this experience 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. If the switch into the PayPal App cannot be completed, we will fall back to the ASWebAuthenticationSession
experience.
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
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. This will take you to the PayPal Domain Names page.
- 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 on the top right of the page or scroll to the Specify Your Domain Names section.
- In the text box enter your list of domain names separated by commas.
- Note: The value you enter must match your fully qualified domain name exactly – including the "www." if applicable.
- Click the Add Domain Names button.
- If the domain registration was successful for all the domain names listed in the text box, a banner will display the text "Successfully added domains". The registered domain names will be displayed in alphabetical order under the + Add button.
- If the registration was not successful for any of the domain names listed in the text box, a banner will display a list of domain names that failed qualified domain name validation along with their reasons for rejection. Any domain names that were successfully registered will be displayed in alphabetical order under the + Add button.
- Note: You can re-enter the rejected domain names in the text area with the corrections applied.
Set Universal Link in SDK
You will need to use the following BTPayPalClient init 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
, you must add the onOpenURL(perform:)
modifier to your ContentView
, and then call BTAppContextSwitcher's
handleOpen(_:)
method.
- Swift
.onOpenURL { url in
BTAppContextSwitcher.sharedInstance.handleOpen(url)
}
If you're using UISceneDelegate
(introduced in iOS 13), call the handleOpen(_:)
method from within the scene(_:continue:)
scene delegate method.
- Swift
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
if let returnURL = userActivity.webpageURL, returnURL.path.contains("/my-dedicated-braintree-path") {
BTAppContextSwitcher.sharedInstance.handleOpen(returnURL)
}
}
Otherwise, if you aren't using UISceneDelegate
, call the handleOpen(_:)
method method from within the application(_:continue:restorationHandler:)
app delegate method.
- 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
from above to call BTPayPalClient.tokenize(_:completion:)
to launch the PayPal App Switch flow.
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: "sally@gmail.com",
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(
userAuthenticationEmail: "sally@gmail.com",
enablePayPalAppSwitch: true
)
// userAuthenticationEmail and 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.