PayPal
import { DataCollectorCodeBlock } from '~/components/CodeBlockInstances/PayPal/DataCollector.tsx' import { VaultFlowCodeBlock } from '~/components/CodeBlockInstances/PayPal/VaultFlow.tsx' import ErrorIcon from "~/components/icons/ErrorIcon";
Vault
- Select or add shipping addresses in the PayPal account
- Select or add funding instruments in the PayPal account
- Two factor authentication support (currently only for US, UK, CA, DE, AT, and AU)
Typical use cases for the vaulted payment flow:
- Faster payments for repeat customers
- Subscriptions
- Recurring billing (e.g. automatic top-up or usage based charges)
Setup
Get the SDK
Add the following in your app-level build.gradle
:
- Kotlin
- Groovy
dependencies { implementation("com.braintreepayments.api:paypal:4.49.1") }
Invoking the Vault flow
First, make sure you have
defined your URL scheme. Next, create a BraintreeClient
with a
ClientTokenProvider
or Tokenization Key. Construct a PayPalClient
and implement a
PayPalListener
to receive results. Call
PayPalClient#tokenizePayPalAccount
to launch the PayPal flow. An example integration
might look like this:
- Java
- Kotlin
public class MyActivity extends AppCompatActivity implements PayPalListener { private BraintreeClient braintreeClient; private PayPalClient payPalClient; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); braintreeClient = new BraintreeClient(this, new ExampleClientTokenProvider()); payPalClient = new PayPalClient(this, braintreeClient); dataCollector = new DataCollector(braintreeClient); payPalClient.setListener(this); } private void myTokenizePayPalAccountWithVaultMethod() { PayPalVaultRequest request = new PayPalVaultRequest(); request.setBillingAgreementDescription("Your agreement description"); payPalClient.tokenizePayPalAccount(this, request) } @Override public void onPayPalSuccess(@NonNull PayPalAccountNonce payPalAccountNonce) { // send payPalAccountNonce.getString() to server } @Override public void onPayPalFailure(@NonNull Exception error) { if (error instanceof UserCanceledException) { // user canceled } else { // handle error } } }
singleTop
,
singleTask
, or singleInstance
you will also need to override
onNewIntent
:
- Java
- Kotlin
public class MyActivity extends AppCompatActivity { @Override protected void onNewIntent(Intent newIntent) { super.onNewIntent(newIntent); setIntent(newIntent); } }
onPayPalSuccess
, you can query the
PayPalAccountNonce
result for specific customer information.
Get the SDK
Add the following in your app-level build.gradle
:
- Kotlin
- Groovy
dependencies { implementation("com.braintreepayments.api:paypal:5.2.0") }
Invoking the Vault flow
Initialization
Create a PayPalLauncher
inside of your Activity's onCreate()
. Then, create
a PayPalClient
with a Tokenization Key or Client Token and an
appLinkReturnUrl
that is used to return to your app from the PayPal payment flows.
- Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // PayPalLauncher must be initialized in onCreate payPalLauncher = PayPalLauncher() // can initialize the PayPalClient outside of onCreate if desired payPalClient = PayPalClient( context = this, authorization = "[TOKENIZATION_KEY or CLIENT_TOKEN]", appLinkReturnUrl = Uri.parse("https://merchant-app.com") // Merchant App Link ) }
Request a payment
After the user clicks the PayPal button, create a PayPalVaultRequest
and call
PayPalClient.createPaymentAuthRequest()
and handle its result. If the result is
Failure
, handle the error. If the result is ReadyToLaunch
, invoke
PayPalLauncher.launch()
and check the returned PayPalPendingRequest
. If
Started
is returned, the PayPal flow was launched and the
Started.pendingRequestString
needs to be persisted. If Failure
was
returned, handle the error.
- Kotlin
private fun onPayPalButtonClick() { val payPalVaultRequest = PayPalVaultRequest( hasUserLocationConsent = true, billingAgreementDescription = "Your agreement description" ) payPalClient.createPaymentAuthRequest(this, payPalVaultRequest) { paymentAuthRequest -> when (paymentAuthRequest) { is PayPalPaymentAuthRequest.ReadyToLaunch -> { val pendingRequest = payPalLauncher.launch(this, paymentAuthRequest) when (pendingRequest) { is PayPalPendingRequest.Started -> {/* store pending request */ } is PayPalPendingRequest.Failure -> { /* handle error */ } } } is PayPalPaymentAuthRequest.Failure -> { /* handle paymentAuthRequest.error */ } } } }
Handle the Payment Result
Once the user completes or cancels the PayPal Vault flow the Intent
needs to be
handled. If your Activity
's launch mode is SINGLE_TOP
, the
Intent
needs to be handled in onNewIntent()
. For all other launch modes,
handle the Intent
in onResume()
. Call
PayPalLauncher.handleReturnToApp()
and pass in the persisted
pendingRequestString
and Intent
. Handle the returned
PayPalPaymentAuthResult
. If NoResult
is returned, the user has canceled
the payment flow or returned to the app without completing the payPal flow. If
Failure
is returned, handle the error. If Success
is returned, pass the
Success
object to PayPalClient.tokenize()
. The
PayPalClient.tokenize()
function takes a PayPalTokenizeCallback
which
returns a PayPalResult
. When the result is Cancel
, the user canceled the
flow. When the result is Failure
, handle the error. When the result is
Success
, a nonce value is returned inside of PayPalAccountNonce
. You can
query the PayPalAccountNonce
result for specific customer information if needed.
- Kotlin
// ONLY REQUIRED IF YOUR ACTIVITY LAUNCH MODE IS SINGLE_TOP override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) handleReturnToApp(intent) } // ALL OTHER ACTIVITY LAUNCH MODES override fun onResume() { super.onResume() handleReturnToApp(intent) } private fun handleReturnToApp(intent: Intent) { // fetch stored PayPalPendingRequest.Success val pendingRequest: String = fetchPendingRequestFromPersistantStore() when (val paymentAuthResult = payPalLauncher.handleReturnToApp( pendingRequest = PayPalPendingRequest.Started(pendingRequest), intent = intent )) { is PayPalPaymentAuthResult.Success -> { completePayPalFlow(paymentAuthResult) // clear stored PayPalPendingRequest.Success } is PayPalPaymentAuthResult.NoResult -> { // user returned to app without completing PayPal flow, handle accordingly } is PayPalPaymentAuthResult.Failure -> { // handle error case } } } private fun completePayPalFlow(paymentAuthResult: PayPalPaymentAuthResult.Success) { payPalClient.tokenize(paymentAuthResult) { result -> when (result) { is PayPalResult.Success -> { /* handle result.nonce <em>/ } is PayPalResult.Failure -> { /</em> handle result.error <em>/ } is PayPalResult.Cancel -> { /</em> handle user canceled */ } } } }
Complete Integration
- Kotlin
class MyActivity : AppCompatActivity() { private lateinit var payPalLauncher: PayPalLauncher private lateinit var payPalClient: PayPalClient override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // PayPalLauncher must be initialized in onCreate payPalLauncher = PayPalLauncher() // can initialize the PayPalClient outside of onCreate if desired payPalClient = PayPalClient( context = this, authorization = "[TOKENIZATION_KEY or CLIENT_TOKEN]", appLinkReturnUrl = Uri.parse("https://merchant-app.com") // Merchant App Link ) } // ONLY REQUIRED IF YOUR ACTIVITY LAUNCH MODE IS SINGLE_TOP override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) handleReturnToApp(intent) } // ALL OTHER ACTIVITY LAUNCH MODES override fun onResume() { super.onResume() handleReturnToApp(intent) } private fun handleReturnToApp(intent: Intent) { // fetch stored PayPalPendingRequest.Success val pendingRequest: String = fetchPendingRequestFromPersistantStore() when (val paymentAuthResult = payPalLauncher.handleReturnToApp( pendingRequest = PayPalPendingRequest.Started(pendingRequest), intent = intent )) { is PayPalPaymentAuthResult.Success -> { completePayPalFlow(paymentAuthResult) // clear stored PayPalPendingRequest.Success } is PayPalPaymentAuthResult.NoResult -> { // user returned to app without completing PayPal flow, handle accordingly } is PayPalPaymentAuthResult.Failure -> { // handle error case } } } private fun completePayPalFlow(paymentAuthResult: PayPalPaymentAuthResult.Success) { payPalClient.tokenize(paymentAuthResult) { result -> when (result) { is PayPalResult.Success -> { /* handle result.nonce */ } is PayPalResult.Failure -> { /* handle result.error */ } is PayPalResult.Cancel -> { /* handle user canceled */ } } } } private fun onPayPalButtonClick() { val payPalVaultRequest = PayPalVaultRequest( hasUserLocationConsent = true, billingAgreementDescription = "Your agreement description" ) payPalClient.createPaymentAuthRequest(this, payPalVaultRequest) { paymentAuthRequest -> when (paymentAuthRequest) { is PayPalPaymentAuthRequest.ReadyToLaunch -> { val pendingRequest = payPalLauncher.launch(this, paymentAuthRequest) when (pendingRequest) { is PayPalPendingRequest.Started -> {/* store pending request */ } is PayPalPendingRequest.Failure -> { /* handle error */ } } } is PayPalPaymentAuthRequest.Failure -> { /* handle paymentAuthRequest.error */ } } } } }
Collecting device data
Collecting device data from your customers is
required when initiating non-recurring transactions from Vault records. Collecting
and passing this data with transactions will help reduce decline rates.
DataCollector
enables you to collect data about a customer's device and correlate it
with a session identifier on your server.
Shipping address
Shipping addresses may or may not be collected during the PayPal Vault flow. However, if you choose
to collect shipping addresses yourself, it can be passed along with the server side
Transaction.Sale
call. Look at the
Server-side page for more
information.
Country and language support
PayPal is available to merchants in all countries that we support and to customers in 140+ countries.
Currency presentment
In the Vault flow itself, the transaction currency and amount are not displayed to the customer. It
is up to you to display these details in your checkout flow somewhere (e.g. cart page, order review
page, etc.). Our
Server-Side guide outlines
which currencies are supported for PayPal transactions.