# Update Android SDK from v2 to v3 (/sdk/android/update-android)

Update your PayPal Mobile SDK v2 Android integration to v3.0.0.



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.

## What's changed in PayPal Checkout [#whats-changed-in-paypal-checkout]

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.

## Before you upgrade [#before-you-upgrade]

* Get your merchant ID, the encrypted merchant account ID, from the [PayPal Developer Dashboard](/dashboard/). It is now required to initialize the SDK.
* The toolchain is unchanged from late v2.x: Java 17, a recent Android Gradle Plugin, and a compatible Kotlin version.

## Update the dependency [#update-the-dependency]

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:

```groovy
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'
}
```

## Migrate PayPal Checkout [#migrate-paypal-checkout]

Use this diff to guide the change:

```diff
  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 */ }
+         }
+     }
  }
```

## Server-side change [#server-side-change]

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.

## Pay Later / PayPal Credit [#pay-later--paypal-credit]

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.

## Verify the upgrade [#verify-the-upgrade]

* The project compiles with `PayPalClient` and no references to `PayPalWebCheckoutClient` remain.
* A sandbox checkout completes end to end: `createPayPalSession()` → `start(activity, orderId, callback)` → `finishStart(intent)` in `onNewIntent` → capture.
* `PayPalEvent.SESSION_NOT_STARTED` does not fire, confirming `createPayPalSession()` runs before `start()`.

## See also [#see-also]

* [Install and set up](/sdk/android/install-and-setup): add the SDK, initialize `CoreConfig`, and register your return links.
* [PayPal Checkout](/sdk/android/add-payment-methods/paypal-checkout): integrate One-Time Checkout, save payment methods, Pay Later, and PayPal Credit.
* [Troubleshooting](/sdk/android/troubleshooting): diagnose common build and integration failures by symptom.
