iOS v3 is deprecated. We recommend migrating to the latest version of our iOS SDK. The best way to start is by making an incremental upgrade from v3 to v4.

The PayPal authorization flow includes PayPal One Touch™, which allows customers to pay by authenticating in-app via a modally presented UIViewController. After account authentication and payment authorization, customers are returned back to your app.


Before you can add PayPal:

  1. Integrate the Braintree iOS SDK into your app
  2. Create, verify, and link your PayPal account in the Braintree Control Panel

Setup for app switch

To handle workflows that involve switching to another app or SFSafariViewController for authentication, you must register a URL type and configure your app to handle return URLs.

Register a URL type

  1. In Xcode, click on your project in the Project Navigator and navigate to App Target > Info > URL Types
  2. Click [+] to add a new URL type
  3. Under URL Schemes, enter your app switch return URL scheme. This scheme must start with your app's Bundle ID and be dedicated to Braintree app switch returns. For example, if the app bundle ID is com.your-company.your-app, then your URL scheme could be com.your-company.your-app.payments.

If you have multiple app targets, be sure to add the return URL type for all of the targets.

Testing the URL type

You can test out your new URL scheme by opening up a URL that starts with it (e.g. com.your-company.your-app.payments://test) in Mobile Safari on your iOS Device or Simulator.

In addition, always test your app switching on a real device.

Set your return URL

In your AppDelegate's application:didFinishLaunchingWithOptions: implementation, use setReturnURLScheme: with the value you set above.

For example:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [Braintree setReturnURLScheme:@"com.your-company.your-app.payments"];
    return YES;

Handle app switch

Then pass the payment authorization URL to Braintree for finalization.

If you're using UISceneDelegate (introduced in iOS 13), call BTAppSwitch's handleOpenURLContext method from within the scene:openURLContexts scene delegate method.

- (void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts {
    for (UIOpenURLContext *urlContext in URLContexts) {
        NSURL *url = [urlContext URL];
        if ([url.scheme localizedCaseInsensitiveCompare:@"com.my-app.your-app.payments"] == NSOrderedSame) {
            [BTAppSwitch handleOpenURLContext:urlContext];      

Otherwise, if you aren't using UISceneDelegate, call BTAppSwitch's handleOpenURL method from within the application:openURL:options app delegate method.

- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
            options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
    if ([url.scheme localizedCaseInsensitiveCompare:@"com.your-company.your-app.payments"] == NSOrderedSame) {
        return [Braintree handleOpenURL:url sourceApplication:options[UIApplicationOpenURLOptionsSourceApplicationKey]];
    return NO;


To start, define a class that implements BTPaymentMethodCreationDelegate:

// MyViewController.m
#import <Braintree/Braintree.h>

@interface MyViewController () <BTPaymentMethodCreationDelegate>
@property (nonatomic, strong) Braintree *braintree;
  • paymentMethodCreator:didCreatePaymentMethod: Payment method creation is complete with success.
  • paymentMethodCreator:requestsDismissalOfViewController: Your implementation should ensure that the view controller is dismissed.
  • paymentMethodCreator:requestsPresentationOfViewController: The creator requires presentation of a view controller in order to proceed.
  • paymentMethodCreatorDidCancel: The creator has canceled.
  • paymentMethodCreatorWillPerformAppSwitch: Your implementation of this method should set your app to the state it should be in if the user manually switches back to your app. For example, re-enable any controls that are disabled.
  • paymentMethodCreatorWillProcess: This typically indicates asynchronous network activity. When you receive this message, your UI should indicate activity.
  • paymentMethodCreator:didFailWithError: The creator failed to create a payment method for a reason such as:
    • The authorization provider (PayPal) encountered an error
    • A network or gateway error occurred
    • The user-provided credentials led to a non-transactable payment method

Your paymentMethodCreator:didCreatePaymentMethod: implementation should communicate the nonce to your server. See Hello, Client for an overview and some sample code.

Showing a PayPal button

The Braintree SDK has a drop-in payment button that handles the boilerplate UI and code for accepting payments from PayPal.


The drop-in button only supports the PayPal Vault flow.

When setting up your view controller's view hierarchy, create a BTPaymentButton and add it to your view:

- (void)viewDidLoad {
    [super viewDidLoad];

    // Create a `Braintree` instance, if you haven't already.
    self.braintree = [Braintree braintreeWithClientToken:self.clientToken];

    // Instantiate BTPaymentButton
    BTPaymentButton *button = [braintree paymentButtonWithDelegate:self];
    [button setFrame:CGRectMake(0, 0, 60, 120)];
    [self.view addSubview:button];

If you would like to only support a specific provider, you can specify that when creating the BTPaymentButton:

NSOrderedSet *types = [NSOrderedSet orderedSetWithObjects:@(BTPaymentProviderTypePayPal), nil];
BTPaymentButton *button = [braintree paymentButtonWithDelegate:self paymentProviderTypes:types];

For either flow, you should be receiving paymentMethodCreator:didCreatePaymentMethod: which gives to you a paymentMethod.nonce that can be sent to your server for processing.

Using a custom UI

You can implement a custom UI, such as your own PayPal button.

BTPaymentProvider *provider = [braintree paymentProviderWithDelegate:self];
// Start PayPal Flow
[provider createPaymentMethod:BTPaymentProviderTypePayPal];

Collecting additional data

You can gather additional data about your customers as they complete the payment process.

Billing address

To collect billing addresses you will need to enable the PayPal Billing Address Request feature in your PayPal account. To enable this feature, contact PayPal.

If you want to collect billing addresses, first set the proper scopes:

self.braintree.client.additionalPayPalScopes = [NSSet setWithObjects:BTPayPalScopeAddress, nil];

Once the scopes are set, the billingAddress property of the returned BTPayPalPaymentMethod should be populated with a BTPostalAddress:

BTPostalAddress *postalAddress = paypalPaymentMethod.billingAddress;
// Access the properties of the address
NSString *streetAddress = [postalAddress streetAddress];
NSString *extendedAddress = [postalAddress extendedAddress];
NSString *locality = [postalAddress locality];
NSString *countryCodeAlpha2 = [postalAddress countryCodeAlpha2];
NSString *postalCode = [postalAddress postalCode];
NSString *region = [postalAddress region];

If a credit card is not the underlying funding source of the transaction, the customer's primary account address will be returned instead.


See Braintree iOS Client SDK PayPal header files for in-depth documentation and additional custom PayPal integration options.

Next Page: Vault →