On this page
No Headings
Last updated: September 14, 2026
This guide describes how to move an existing PayPal Mobile SDK v2.x Android integration to v3.0.0. The largest changes are in PayPal Checkout: the client was renamed, checkout is now session-first, CoreConfig requires a merchantId, and return URLs moved out of the Orders API into a URL config.
The following table summarizes the key PayPal Checkout changes from v2 to v3.
| Area | v2 | v3 |
|---|---|---|
| Client class | PayPalWebCheckoutClient | PayPalClient |
CoreConfig | clientId + environment | adds required merchantId, optional bnCode; environment renamed to coreEnvironment |
| Session | none | createPayPalSession() is required before start() / vault() |
| Return URLs | urlScheme on the client + experienceContext URLs in the Orders API | ReturnToAppUrlConfig passed to createPayPalSession(); not set in the Orders API |
start() | start(activity, request) | start(activity, orderId, callback) |
| Result | PayPalWebCheckoutFinishStartResult through finishStart(intent) | start()'s callback reports PayPalPresentAuthChallengeResult (Success/Failure), showing only whether the checkout UI was presented. The actual checkout outcome, PayPalFinishStartResult (Success/Canceled/Failure/NoResult), is delivered separately by finishStart(intent) when the buyer returns |
| Return handling | finishStart(intent) returns the result | Same method name, finishStart(intent), called from onNewIntent; now returns PayPalFinishStartResult? |
Card (ACDC) keeps its own client; the main change it inherits is the merchantId on CoreConfig. Card's approveOrder() / presentAuthChallenge() / finishApproveOrder() result-type pattern is unchanged from 2.x.
Bump each PayPal module to the v3 release. The PayPal Checkout artifact is renamed from paypal-web-payments to paypal-payments; the other module names are unchanged:
dependencies {
implementation 'com.paypal.android:paypal-payments:3.0.0' // was paypal-web-payments in v2
implementation 'com.paypal.android:payment-buttons:3.0.0'
implementation 'com.paypal.android:fraud-protection:3.0.0'
}Use this diff to guide the change:
val config = CoreConfig(
clientId = "<CLIENT_ID>",
+ merchantId = "<MERCHANT_ID>", // now required, distinct from your client ID
- environment = Environment.SANDBOX
+ coreEnvironment = CoreEnvironment.SANDBOX // renamed from `environment` in v3
)
- val client = PayPalWebCheckoutClient(context, config, "my-url-scheme")
+ val client = PayPalClient(context, config)
+ val urlConfig = ReturnToAppUrlConfig(
+ returnAppUrl = "https://example.com/merchant-app/return",
+ cancelAppUrl = "https://example.com/merchant-app/cancel",
+ fallbackSchemeUrl = "merchantapp://return"
+ )
fun onPayPalButtonTapped() {
+ // NEW: prepare the session before start()
+ client.createPayPalSession(
+ tokenType = TokenType.ORDER_ID,
+ userIdentity = PayPalUserIdentity(email = "buyer@example.com"),
+ urlConfig = urlConfig,
+ userAction = PayPalUserAction.CONTINUE
+ )
val orderId = myServer.createOrder()
- client.start(this, PayPalWebCheckoutRequest(orderId)) { /* PayPalPresentAuthChallengeResult */ }
+ client.start(this, orderId, object : PayPalResultCallback {
+ override fun onPayPalResult(result: PayPalPresentAuthChallengeResult) {
+ when (result) {
+ is PayPalPresentAuthChallengeResult.Success -> { /* checkout UI presented; the outcome arrives in onNewIntent */ }
+ is PayPalPresentAuthChallengeResult.Failure -> showError(result.error)
+ }
+ }
+ })
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
setIntent(intent)
- client.finishStart(intent)?.let { /* PayPalWebCheckoutFinishStartResult */ }
+ client.finishStart(intent)?.let { result ->
+ when (result) {
+ is PayPalFinishStartResult.Success -> captureOrder(result.orderId)
+ is PayPalFinishStartResult.Canceled -> showCheckoutScreen()
+ is PayPalFinishStartResult.Failure -> showError(result.error)
+ PayPalFinishStartResult.NoResult -> { /* intent was not a checkout return */ }
+ }
+ }
}In v2, you set experienceContext.returnUrl / cancelUrl when creating the order. In v3, those move to the SDK through ReturnToAppUrlConfig. Remove them from your Orders v2 create call for the session-based flow. Your manifest App Link and custom-scheme fallback stay as they were.
In v2, selecting PAY_LATER / PAYPAL_CREDIT funding required the non-session start(activity, request: PayPalWebCheckoutRequest, callback) overload. Both that overload and PayPalWebCheckoutRequest were removed in v3.
Funding-source selection moves entirely to your server: set payment_source.paypal.experience_context.payment_method_selected to PAYPAL (default), PAYPAL_PAY_LATER, or PAYPAL_CREDIT when you create the order. The client-side createPayPalSession() → start(activity, orderId, callback) flow is identical regardless of funding source.
PayPalClient and no references to PayPalWebCheckoutClient remain.createPayPalSession() → start(activity, orderId, callback) → finishStart(intent) in onNewIntent → capture.PayPalEvent.SESSION_NOT_STARTED does not fire, confirming createPayPalSession() runs before start().CoreConfig, and register your return links.Cards
Accept an Advanced Credit and Debit Card (ACDC) payment in your Android app with PayPal Mobile SDK v3.0.0, including vault.
From v1 to v2
Update your Android integration from PayPal Mobile SDK v1 to v2. Move to sealed result callbacks, manual 3D Secure handling, and remove PayPal Native Payments.