On this page
No Headings
Last updated: June 16, 2026
Important: PayPal Here is deprecated. PayPal doesn't accept new integrations but continues to support existing integrations.
To prepare to process transactions with the SDK for the first time, an app must complete these setup operations:
After setup is complete, an app must complete these steps to process a basic card-present transaction:
Note: The SDK provides the UI to capture the signature and display the receipt options.
Note: These are samples only. You should review the sample apps to see how they are used in an actual application.
Choose your platform:
PayPalRetailSDK.initializeSDK()Initialize the merchant. You pass an SdkCredential object, which includes the access token, refresh URL, and the environment. For details, see Token Management.
Note: For iOS, initializeMerchant also initializes the SDK if it is not already initialized. For iOS, you can call initializeMerchant directly without calling initializeSDK.
let sdkCreds = SdkCredential.init(accessToken: "access token of merchant", refreshUrl: "refresh URL to use to refresh access token after expiry", environment: "either live or sandbox")
PayPalRetailSDK.initializeMerchant(withCredentials: sdkCreds) { (error, merchant) in
// Code to handle success or failure
// To continue, this must succeed
}Device discovery. After you initialize the SDK and merchant, connect to a card reader. The following code demonstrates how to connect:
Note: When you use the auto connect method, no SDK UI appears to select a reader because it tries to connect in the background. If you cannot connect to the last known reader, you must use one of the other methods.
// previous declaration of deviceManager
let deviceManager = PayPalRetailSDK.deviceManager()
// code to connect to last known reader or find another
deviceManager.connect(toLastActiveReader: { (error, paymentDevice) -> Void in
// Code to handle success or failure
// On error, check the error and retry
// On success for a Bluetooth reader, check for software update
})
// code to search and connect
deviceManager.searchAndConnect({ (error, paymentDevice) -> Void in
// Code to handle success or failure
// On error, check the error and retry
// On success for a Bluetooth reader, check for software update
})
// code to auto-connect to the last known reader
let lastActiveReader = deviceManager?.getLastActiveBluetoothReader()
deviceManager.scanAndAutoConnect(toBluetoothReader: lastActiveReader, callback: { (error, paymentDevice) in
// Code to handle success or failure
// On error, check error and connect by another method
// On success for a Bluetooth reader, check for software update
})reader.pendingUpdate.offer({ (error, updateComplete) in
// Code to handle success or failure
// On error, check the error and retry
// On success, continue with the payment flow
})var invoice: PPRetailInvoice?
invoice = PPRetailInvoice.init(currencyCode: "USD")
invoice.addItem("My Order", quantity: 1, unitPrice: 1.00, itemId: 123, detailId: nil)
invoice.number = "unique_invoice_number"TransactionContext using the previously created invoice.var tc: PPRetailTransactionContext?
PayPalRetailSDK.transactionManager().createTransaction(invoice, callback: { (error, context) in
// On error, handle error. Else, set transaction context to call beginPayment in next step
self.tc = context
})// Listener called once the transaction is completed
tc.setCompletedHandler { (error, txnRecord) -> Void in
// if error, handle accordingly, else pop back to view controller and handle success
self.navigationController?.popToViewController(self, animated: false)
// txnRecord would have any info needed to record the successful transaction
}
// Setting up the options for the transaction.
let options = PPRetailTransactionBeginOptions()
options.showPromptInCardReader = true
options.showPromptInApp = true
options.preferredFormFactors = []
options.tippingOnReaderEnabled = false
options.amountBasedTipping = false
options.isAuthCapture = false
options.quickChipEnabled = false
// Activates the reader to show the payment options
tc.beginPayment(options)| Payment option | Type | Description |
|---|---|---|
showPromptInCardReader | Bool | Prompts the customer to tap/insert/swipe the card and whether that appears on the reader. |
showPromptInApp | Bool | Prompts the customer to tap/insert/swipe the card and whether that UI shows in the integrating app. |
preferredFormFactors | Array | Restricts accepted payment methods (contactless, swipe, chip). |
tippingOnReaderEnabled | Bool | Defines whether the customer is prompted for a tip on the card reader. |
amountBasedTipping | Bool | Defines whether the tipping is amount based or percentage based. |
isAuthCapture | Bool | Defines whether the transaction runs as an authorization or a sale. If true, you also must implement the Receipts API. |
quickChipEnabled | Bool | Enables quick chip processing so customers don't have to leave their card inserted the whole time the transaction is processing. |
This feature is currently only available to US merchants.
Important: To use offline payments, you must enable it on your PayPal account. To enable it, send your account email address and a business case to use offline payments to pph-sdk@paypal.com.
Offline mode is only available with EMV-capable card readers. Also, offline mode forces the supported card readers to only accept swipe transactions.
To use the offline payments feature, your app must check for Internet connectivity. If you have no connectivity, your app must request that the PayPal Here SDK store the transaction as offline on the mobile device. When the Internet connectivity is regained, your app must request that PayPal Here SDK process the pending offline transaction.
You are subject to the following limits on activity with the offline payments feature:
These limits are subject to change at PayPal's sole discretion. PayPal informs you of changes by email.
As a partner, your end-user merchants assume all liability for any offline transactions, including those that are subsequently declined, expired, or disputed. Your end-user merchants cannot dispute declined offline transactions. Your end-user merchants also assume all liability for offline transactions if the device is lost, stolen, damaged, or you delete your app before re-connecting to the Internet. Any refunds are processed in the normal course after your end user merchants are re-connected to the Internet.
Before you enable the offline payments feature, you agree to communicate these terms and conditions to your end users and secure their agreement to those terms and conditions before your end users can use the feature.
initializeMerchantsuccessfully, you can proceed to step 2 to enable offline mode. You do not need to call initializeMerchantOffline if you've already completed a successful online merchant initialization. However, if you do not have an Internet connection to call initializeMerchant, you can call intializeMerchantOffline to successfully initialize the merchant before processing offline transactions.Notes:
initializeMerchantOffline only if you cannot initially call initializeMerchant.initializeMerchant and instead called initializeMerchantOffline, you must call initializeMerchant before replaying offline transactions. Before you can process online transactions, online merchant initialization must succeed.PayPalRetailSDK.initializeMerchantOffline { (error, merchant) in
// Code to handle success or failure
}PayPalRetailSDK.transactionManager().startOfflinePayment(callback: { (error, offlinePaymentInfo) in
// Code to handle success or failure
})TransactionContext using the previously created invoice in the same way as one would for a normal payment.tc.setOfflineTransactionAdditionHandler({ (error, txnRecord) in
// if error, handle accordingly, else pop back to view controller and handle success
self.navigationController?.popToViewController(self, animated: false)
// txnRecord would have any info needed to record the successful offline saved transaction
})PayPalRetailSDK.transactionManager().getOfflinePaymentStatus(callback: { (error, offlinePaymentInfo) in
// Code to handle success or failure
})PayPalRetailSDK.transactionManager().startReplayOfflineTxns(callback: { (error, offlinePaymentInfo) in
// Code to handle success or failure of the offline replay
})PayPalRetailSDK.transactionManager().stopReplayOfflineTxns(callback: { (error, info) in
// Status of the remaining offline transactions
})Note: The SDK is brought back into online mode once startReplayOfflineTxns is called. When this happens, the app does not need to call stopOfflinePayment to return to online mode.
PayPalRetailSDK.transactionManager().stopOfflinePayment({ (error, info) in
// Status of the remaining offline transactions
})Refunds can either be done within your app or you can use our Refund API to incorporate refund functionality in your back-office. These steps outline how to complete a refund within your app:
TransactionContext for the invoice you would like to refund. The createRefundTransaction method takes in the following parameters: PayPal invoice ID, transaction ID, payment method of the transaction, and a callback handler.PayPalRetailSDK.transactionManager().createRefundTransaction(paypalInvoiceId, transactionNumber: transactionNumber, paymentMethod: paymentMethod, callback: refundHandler)The callback handler accepts an error object and transaction context. If the error object is not nil, then handle accordingly. Otherwise, use the transaction context to call beginRefund.
beginRefund to determine whether the card is present for the refund, and to process the refund. This code would be used as part of the callbacks mentioned in the createRefundTransaction method.// Listener that gets called once the refund processes
tc.setCompletedHandler { (error, txnRecord) -> Void in
// if error, handle accordingly, else pop back to view controller and handle success
self.navigationController?.popToViewController(self, animated: false)
// txnRecord would have any info needed to record the successful refund
}
// Begins refund process and asks if a card is present for the refund
tc.beginRefund(true, amount: refundAmount)The SDK also supports several additional capabilities:
When your integration is complete, check the going live page to ensure that you have everything ready for activation. Once that is working, you can implement other customizations that are available with the SDK into your integration.