On this page
No Headings
Last updated: June 4, 2026
Important: PayPal Here is deprecated. PayPal doesn't accept new integrations but continues to support existing integrations.
There are some additional options for handling payments within the PPH SDK. This page, outlines the various options along with the relevant code samples.
For Braintree-specific functionality of this feature, please visit the PayPal Here integration page on the Braintree developer portal. On the PayPal Here side, there are essentially two steps needed to enable the Braintree functionality within the PayPal Here SDK:
The steps are outlined below. Specific code samples are available for reference in the iOS and Android sample apps.
To authenticate, you go into your Braintree console's Processing Options page and toggle on the option to use PayPal Here. More detailed instructions for that are located in the Braintree documentation. Once this has been done, the PayPal Here SDK will get the required tokens for your Braintree account for vaulting.
Note: As noted in the Braintree documentation, when you link your PayPal and Braintree accounts ensure that you're using the client ID and client secret that is on the REST App that is created on your behalf, by Braintree. You need these credentials to generate the access token for the PayPal Here SDK so that the SDK can find your connected Braintree account.
To use the Braintree vault, there are some additional options you must set on the PPRetailTransactionBeginOptions that is used to create a payment. Keep in mind that these are in addition to any other options that are set for your normal SDK integration. There are three options that must be set:
| Payment option | Type | Description |
|---|---|---|
vaultProvider | Enum | The only option available for this currently is braintree. |
vaultCustomerId | String | This represents the Braintree customer to vault the card against. |
vaultType | Enum | payOnly – Set this option to take the payment only without vaulting anything.vaultOnly – Set this option to vault the card only and not take any payment.payAndVault – Set this option to take a payment and vault the card all in one interaction. |
Similarly to the iOS and Android SDKs, you must also set the vault provider, customer ID, and type when wanting to vault a payment method. These are added to your payment configuration and examples for pay and vault or vault only can be found in the samples below.
Note: To associate a transaction with a particular customer ID without vaulting the payment method, simply provide the vaultCustomerId and set the vaultType to payOnly.
When vaulting a card, register a separate vaultCompletedHandler to interrogate the result for success or failure:
Choose your platform:
// Set the vault completion handler before calling beginPayment to receive vault record with id
tc.setVaultCompletedHandler({ (error, vaultRecord) in
if error != nil {
// handle error accordingly
} else {
// handle success with vaultRecord
}
})It is important to note that when simultaneously accepting a payment and vaulting the card, an error when vaulting does not necessarily mean there was an error accepting payment. If there is an error with the vaultRecord, the payment may have succeeded and should be verified separately.
When vaulting a card without a payment, there is an extra helper method createVaultTransaction on the TransactionManager. This enables you to skip the standard PayPal Here transaction flow and streamline collection of vaulted payment methods:
func doVaultOnly() {
PayPalRetailSDK.transactionManager()?.createVaultTransaction(acceptVaultOnlyTransaction(error:tc:))
}
func acceptVaultOnlyTransaction(error: PPRetailError?, tc: PPRetailTransactionContext?) {
self.transactionContext = tc
// set vaultCompletionHandler, transaction options, and beginPayment as outlined above
}Note: Keep in mind the following vaulting restrictions:
During the payment, if you set the isAuthCapture payment option to true (Android & iOS) or use the .authorize() command (Web) to run the payment as an authorization, then you may need the option to capture the funds from within the integrating app. Alternatively, if you plan to capture from the server-side, you can use the Capture API.
In order to capture an authorization in-app, you need the following parameters:
The total amount is the total amount that's needed to be captured, including any gratuity. The gratuity amount is separate for reporting purposes. Therefore, if you have an authorization for $10, and want to capture $12 total after a tip, then you'd submit the total amount as $12 and the gratuity amount as $2 accordingly. Also note that the capture currency has to match the currency of the original authorization.
PayPalRetailSDK.transactionManager().captureAuthorization(authId, invoiceId: invoice.payPalId, totalAmount: amountToCapture, gratuityAmount: 0, currency: invoice.currency) { (error, captureId) in
// code to handle success or failure
// if error, check error and handle accordingly
// if success, record the capture ID for future reference
}During the payment, if you set the isAuthCapture payment option to true to run the payment as an authorization, then you may need the option to void the auth from within the integrating App. Alternatively, if you are voiding from the server-side, you can use the Void API.
PayPalRetailSDK.transactionManager().voidAuthorization(authTransactionNumber) { (error) in
// code to handle success or failure
// if error, check error and handle accordingly
}You can also enter a customer's credit card manually if needed. While following the traditional route for processing a payment, simply build a PPRetailManuallyEnteredCard instance and then add two extra options to your PPRetailTransactionBeginOptions prior to calling beginPayment(options). Those options are paymentType and manualCard.
For the Web SDK, you need to add the card object to your payment configuration similar to vaulting and then utilize the KEYIN payment method with your payment call.
let cardInfo = PPRetailManuallyEnteredCard.init()
cardInfo.setCardNumber("1234123412341234")
cardInfo.setExpiration("MMYYYY")
cardInfo.setCVV("123")
cardInfo.setPostalCode("12345")
// Be sure to add the following options before calling tc.beginPayment(options)
options.paymentType = PPRetailTransactionBeginOptionsPaymentTypes.typeskeyIn
options.manualCard = cardInfo