PayPal

One-time Payments

Important

The SSL certificates for all Braintree SDKs are set to expire by June 30, 2025. This will impact existing versions of the SDK in published versions of your app. To reduce the impact, upgrade the iOS SDK to version 6.17.0+ for the new SSL certifications.

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.

Pay with PayPal's One-time Payments is a one-click solution that accelerates your buyer's checkout experience by skipping manual data entry. Buyers can use PayPal to check out anywhere in their shopping journey. Placing payment buttons on the cart, product details page, or another page as a checkout shortcut can reduce steps to pay.

Invoking the One-time Payments flowAnchorIcon

Use BTPayPalClient and BTPayPalCheckoutRequest to start the process. A transaction amount is required to invoke the one-time payment flow. An example integration might look similar to this:

  1. Swift
class MyViewController: UIViewController {
    var braintreeClient: BTAPIClient?
    func startCheckout() {
        // Example: Initialize BTAPIClient, if you haven't already
        braintreeClient = BTAPIClient(authorization: "<#CLIENT_AUTHORIZATION#>")!
        let payPalClient = BTPayPalClient(apiClient: braintreeClient)
        // Specify the transaction amount here. "2.32" is used in this example.
        let request = BTPayPalCheckoutRequest(amount: "2.32")
        request.currencyCode = "USD" // Optional; see BTPayPalCheckoutRequest for more options
        payPalClient.tokenize(request) { (tokenizedPayPalAccount, error) in
            if let tokenizedPayPalAccount = tokenizedPayPalAccount {
                print("Got a nonce: \(tokenizedPayPalAccount.nonce)")
                // Access additional information
                let email = tokenizedPayPalAccount.email
                let firstName = tokenizedPayPalAccount.firstName
                let lastName = tokenizedPayPalAccount.lastName
                let phone = tokenizedPayPalAccount.phone
                // See BTPostalAddress for details
                let billingAddress = tokenizedPayPalAccount.billingAddress
                let shippingAddress = tokenizedPayPalAccount.shippingAddress
            } else if let error = error {
                // Handle error here...
            } else {
                // Buyer canceled payment approval
            }
        }
      }
    }

Customizing One-time PaymentsAnchorIcon

We can customize One-time Payments with the following features:

  • Contact Module
  • Shipping Module
  • Pass Buyer Identifier
  • Pass Line-item Details
  • Pay Now or Continue
  • App Switch

Integrating Contact ModuleAnchorIcon

When customers purchase digital goods (such as gift cards, movies, and software) and check out with PayPal, merchants can ask the customers to input the digital good recipient's information (email and phone).

To integrate the Contact Module, use the code provided below

  1. Swift
let request = BTPayPalCheckoutRequest()
            request.contactInformation = BTContactInformation(
            recipientEmail: "some@email.com",
            recipientPhoneNumber: .init(countryCode: "52", nationalNumber: "123456789")
          )

Integrating Shipping ModuleAnchorIcon

The PayPal shipping module presents shipping details to a buyer during the PayPal flow. The merchant has several ways to determine how shipping addresses and shipping options are handled. The server-side shipping callbacks allow you to update the shipping and order amount information as buyers make changes on the PayPal review page.

Buyers can use the shipping module to specify the shipping address and shipping options on the PayPal paysheet. PayPal sends a callback to the merchant's URL with the updated shipping information (buyer’s address, state, city, country code, and zip code) using the server-side shipping callbacks. In response, the merchant can send PayPal the shipping options and updated order cost amounts.

To include Shipping Module in your integration, set the server side shipping callback URL as shown below. For more information, see the Integration code samples section, below.

  1. Swift
request.shippingCallbackURL = URL(string: "www.merchant-url.com")

Integrating Pass Line-item DetailsAnchorIcon

The items a buyer purchases can be passed to PayPal through a request.lineItems request. When a buyer checks out their purchase, PayPal displays these invoice-line-item details (item name, quantity, detailed description, price, etc.) for buyer verification. The details passed to PayPal are presented to the buyer:

  • On the PayPal review page during the Pay with PayPal flow.
  • In the post-purchase email sent to the buyer about their payment transaction.
  • In the buyer's PayPal account Activity > Transactions > All transactions section.

To integrate Pass Line-item Details, set the code as shown below, and for more information, see the Integration code samples section

  1. Swift
let request = BTPayPalCheckoutRequest(amount: "2.32")
  request.currencyCode = "USD" // Optional; see BTPayPalCheckoutRequest for more options

Integrating Pass Buyer IdentifierAnchorIcon

A buyer's email address can be passed as the buyer identifier to PayPal through a PayPal request. During one-time checkout, PayPal uses this email address to prefill the buyer's PayPal login page. This streamlines and quickens the buyer authentication process for an effortless login. When you run PayPal in your app, as part of the request body, send the buyer's email address in the BTPayPalRequest.userAuthenticationEmail field. After a successful request, the passed email address is used to pre-populate the PayPal login page when the buyer pays with PayPal.

To include Pass Buyer Identifier in your integration, set the code as shown below. For more information, see the Integration code samples section below.

  1. Swift
// Buyer identifiers
  request.userAuthenticationEmail = "user@example.com"
  request.userPhoneNumber = BTPayPalPhoneNumber(countryCode: "1", nationalNumber: "4087463271")
  // Line item details
  request.lineItems = [BTPayPalLineItem(quantity: "1", unitAmount: "10", name: "item-name", kind: .debit)]

Integrating Pay Now or ContinueAnchorIcon

You can set User Action to control the message on the PayPal button at the bottom of the PayPal review page. There are two messaging options:

  • Pay Now: The payer will complete the transaction on the PayPal review page.
  • Continue: The payer will return to the merchant site to complete the transaction.

Pay Now

Use Pay Now for most PayPal flows. Pay Now streamlines checkout by using the payer's PayPal account information. For upstream placements (the button appears on the product or cart page), use the Pay Now User Action with the Shipping and Contact Modules to help the payer select shipping and payment details on the PayPal review page. For checkout presentment (button appears at checkout), payers can use PayPal to skip entering payment information. When a payer completes a Pay Now flow, they are returned to the merchant site. There, they will see a confirmation page with details about the transaction.

Continue

The Continue setting indicates that the payer will return to the merchant site to complete a transaction. Use this flow if the final amount will change after the payer returns to the merchant site. When the payer returns to the merchant site, they are presented with no more than one additional page to complete the transaction. When they complete a transaction, they see a confirmation page.

To integrate Pay Now or Continue, see the Integration code samples section below.

  1. Swift
request.userAction = PayPalPaymentUserAction.USER_ACTION_COMMIT

Integrating App SwitchAnchorIcon

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.

Note

Our recommendation is to instantiate the BTAPIclient during the app load phase instead of during on button click.

To integrate App Switch, follow these seps:

Get the SDKAnchorIcon

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.

CocoapodsAnchorIcon

In your Podfile, add the dependency for the PayPal Mobile Checkout module:

  1. Swift
pod 'Braintree/PayPal'

Swift Package ManagerAnchorIcon

Include the BraintreeCore, BraintreePayPal, and PayPalDataCollector frameworks.

CarthageAnchorIcon

Include the BraintreeCore, BraintreePayPal and PayPalDataCollector frameworks.

Allowlist PayPal URL SchemeAnchorIcon

You must add the following to the queries schemes allowlist in your app's info.plist:

  1. Swift
<key>LSApplicationQueriesSchemes</key>
<array>
  <string>paypal-app-switch-checkout</string>
</array>

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 may look like the following:
  1. Swift
{
  "applinks": {
    "details": [
      {
        "appID": "com.your-app-id",
        "paths": [
          "/braintree-payments/*"
        ]
      }
    ]
  }
}

Before using this feature, you must register your Universal Link domain in the Braintree Control Panel:

  1. Log into your Control Panel (e.g. Sandbox, or Production).
  2. Click on the gear icon in the top right corner. A drop-down menu will open.
  3. Click Account Settings from the drop-down menu.
  4. Scroll to the Payment Methods section.
  5. Next to PayPal, click the Options link. This will take you to your linked PayPal Account(s) page.
  6. 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.
  7. Click the + Add link on the top right of the page or scroll to the Specify Your Domain Names section.
  8. 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.
  9. Click the Add Domain Names button.
  10. 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.
  11. 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.

You will need to use the following BTPayPalClientinit to set your Universal Link:

  1. 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 SwitchingAnchorIcon

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.

  1. 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.

  1. 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.

  1. 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)
  }
}

Opt in to the App Switch flowAnchorIcon

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:

  1. Swift
import UIKit
import BraintreePayPal

class MyViewController: UIViewController {
  var apiClient: BTAPIClient!
  var payPalClient: BTPayPalClient!

  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
    )
  }

  private func payPalButtonTapped() {

    // 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
      if let payPalNonce { 
        // send payPalNonce.nonce to server 
      } else { 
        // handle error
      }
    }
  }
}
Note
In order to test App Switch flow in Sandbox, you will first need access to the TestFlight PayPal Sandbox app. For more information on testing App Switch, refer to our our Testing and Go Live section

Shipping addressAnchorIcon

Shipping addresses may or may not be collected during the Checkout with PayPal flow. However, if you choose to collect shipping addresses yourself, they can be passed along with the your server side Transaction.Sale call. Look at the Server-side page for more information.

Country supportAnchorIcon

PayPal is available to merchants in all countries that we support and to customers in 140+ countries.

Currency presentmentAnchorIcon

The currency of the transaction is presented to the customer in the Checkout with PayPal flow. We support all currencies that PayPal REST APIs support.

See the server-side section for details on charging a transaction in a specific currency.


Next Page: Recurring Payments

If you accept cookies, we’ll use them to improve and customize your experience and enable our partners to show you personalized PayPal ads when you visit other sites. Manage cookies and learn more