This guide highlights how to migrate to the latest version of the PayPal SDK.
For evolution of this guide, see the MIGRATION_GUIDE for v2.0.0.
We refactored the CardClient API to improve the developer experience. Use this diff to guide your migration from v1 to v2:
-class SampleActivity: ComponentActivity(), ApproveOrderListener, CardVaultListener {
+class SampleActivity: ComponentActivity() {
val config = CoreConfig("<CLIENT_ID>", environment = Environment.LIVE)
- val cardClient = CardClient(requireActivity(), config)
+ val cardClient = CardClient(requireContext(), config)
- init {
- cardClient.approveOrderListener = this
- cardClient.vaultListener = this
- }
+ override fun onResume() {
+ super.onResume()
+ // Manually attempt auth challenge completion (via host activity intent deep link)
+ checkForCardAuthCompletion(intent)
+ }
override fun onNewIntent(newIntent: Intent) {
super.onNewIntent(newIntent)
- intent = newIntent
+ // Manually attempt auth challenge completion (via new intent deep link)
+ checkForCardAuthCompletion(newIntent)
}
fun approveOrder() {
val cardRequest: CardRequest = TODO("Create a card request.")
- cardClient.approveOrder(this, cardRequest)
+ when (val approveOrderResult = cardClient.approveOrder(cardRequest)) {
+ is CardApproveOrderResult.Success -> TODO("Capture or authorize order on your server.")
+ is CardApproveOrderResult.Failure -> TODO("Handle approve order failure.")
+ is CardApproveOrderResult.AuthorizationRequired -> presentAuthChallenge(result.authChallenge)
+ }
}
fun vaultCard() {
val cardVaultRequest: CardVaultRequest = TODO("Create a card vault request.")
- cardClient.vault(this, cardVaultRequest)
+ when (val vaultResult = cardClient.vault(cardVaultRequest)) {
+ is CardVaultResult.Success -> TODO("Create payment token on your server.")
+ is CardVaultResult.Failure -> TODO("Handle card vault failure.")
+ is CardVaultResult.AuthorizationRequired -> presentAuthChallenge(result.authChallenge)
+ }
}
+ fun presentAuthChallenge(authChallenge: CardAuthChallenge) {
+ // Manually present auth challenge
+ when (val result = cardClient.presentAuthChallenge(this, authChallenge)) {
+ is CardPresentAuthChallengeResult.Success -> {
+ // Auth Challenge presentation succeeded. Once the user has completed the auth challenge and
+ // the merchant app has re-entered the foreground via onResume() or onNewIntent(), make a
+ // balancing call to finishApproveOrder() / finishVault()
+ }
+ is CardPresentAuthChallengeResult.Failure -> TODO("Handle Present Auth Challenge Failure")
+ }
+ }
+ fun checkForCardAuthCompletion(intent: Intent) {
+ // check for approve order completion
+ cardClient.finishApproveOrder(intent)?.let { approveOrderResult ->
+ when (approveOrderResult) {
+ is CardFinishApproveOrderResult.Success -> TODO("Capture or authorize order on your server.")
+ is CardFinishApproveOrderResult.Failure -> TODO("Handle approve order failure.")
+ CardFinishApproveOrderResult.Canceled -> TODO("Give user the option to restart the flow.")
+ CardFinishApproveOrderResult.NoResult -> {
+ // there isn't enough information to determine the state of the auth challenge for this payment method
+ }
+ }
+ }
+
+ // check for vault completion
+ cardClient.finishVault(intent)?.let { vaultReslt
+ when (vaultResult) {
+ is CardFinishVaultResult.Success -> TODO("Create payment token on your server.")
+ is CardFinishVaultResult.Failure -> TODO("Handle card vault failure.")
+ CardFinishVaultResult.Canceled -> TODO("Give user the option to restart the flow.")
+ CardFinishVaultResult.NoResult -> {
+ // there isn't enough information to determine the state of the auth challenge for this payment method
+ }
+ }
+ }
+ }
- override fun onApproveOrderSuccess(result: CardResult) {
- TODO("Capture or authorize order on your server.")
- }
- override fun onApproveOrderFailure(error: PayPalSDKError) {
- TODO("Handle approve order failure.")
- }
- override fun onVaultSuccess(result: CardVaultResult) {
- val authChallenge = result.authChallenge
- if (authChallenge != null) {
- cardClient?.presentAuthChallenge(activity, authChallenge)
- } else {
- TODO("Create payment token on your server.")
- }
- }
- override fun onVaultFailure(error: PayPalSDKError) {
- TODO("Handle card vault failure.")
- }
- override fun onDestroy() {
- super.onDestroy()
- cardClient.removeObservers()
- }
}Notes on Changes to Card Payments in v2
Here are some detailed notes on the changes made to Card Payments in v2:
- In
v1the activity reference is only truly needed when the call toCardClient#approveOrder()orCardClient#vault()is made (to open a Chrome Custom Tab in the current Task). - In
v2theCardClientconstructor no longer requires an activity reference. - The goal of this change is to increase flexibility of
CardClientinstantiation.
- In
v1the SDK registers a lifecycle observer to parse incoming deep links when the host application comes into the foreground. - In
v2the host application is responsible for callingCardClient#completeAuthChallenge()to attempt completion of an auth challenge. - The goal of this change is to make the SDK less opinionated and give host applications more control over the auth challenge user experience.
- In
v1the SDK would notify the host application of success, failure, etc. events using a registered listener - In
v2the host application will receive a sealed classResulttype in response to each method invocation - The goal of this change is to prevent having to retain listener references and to make auth challenge presentation more explicit
- Sealed class result types also have the added benefit of explicitly calling out all possible outcomes of a related method inovcation
We refactored the PayPalWebClient API to improve the developer experience. Use this diff to guide your migration from v1 to v2:
-class SampleActivity: ComponentActivity(), PayPalWebCheckoutListener, PayPalWebVaultListener {
+class SampleActivity: ComponentActivity() {
val config = CoreConfig("<CLIENT_ID>", environment = Environment.LIVE)
- val payPalClient = PayPalWebCheckoutClient(requireActivity(), config, "my-deep-link-url-scheme")
+ val payPalClient = PayPalWebCheckoutClient(requireContext(), config, "my-deep-link-url-scheme")
- init {
- payPalClient.listener = this
- payPalClient.vaultListener = this
- }
+ override fun onResume() {
+ super.onResume()
+ // Manually attempt auth challenge completion (via host activity intent deep link)
+ checkForPayPalAuthCompletion(intent)
+ }
override fun onNewIntent(newIntent: Intent) {
super.onNewIntent(newIntent)
- intent = newIntent
+ // Manually attempt auth challenge completion (via new intent deep link)
+ checkForPayPalAuthCompletion(newIntent)
}
- override fun onDestroy() {
- super.onDestroy()
- payPalClient.removeObservers()
- }
private fun launchPayPalCheckout() {
val checkoutRequest: PayPalWebCheckoutRequest = TODO("Create a PayPal checkout request.")
- payPalClient.start(checkoutRequest)
+ when (val result = paypalClient.start(this, checkoutRequest)) {
+ is PayPalPresentAuthChallengeResult.Success -> {
+ // Auth Challenge presentation succeeded. Once the user has completed the auth challenge and
+ // the merchant app has re-entered the foreground via onResume() or onNewIntent(), make a
+ // balancing call to finishStart()
+ }
+ is PayPalPresentAuthChallengeResult.Failure -> TODO("Handle Present Auth Challenge Failure")
+ }
}
private fun launchPayPalVault() {
val vaultRequest: PayPalWebVaultRequest = TODO("Create a card vault request.")
- payPalClient.vault(vaultRequest)
+ when (val result = paypalClient.vault(this, vaultRequest)) {
+ is PayPalPresentAuthChallengeResult.Success -> {
+ // Auth Challenge presentation succeeded. Once the user has completed the auth challenge and
+ // the merchant app has re-entered the foreground via onResume() or onNewIntent(), make a
+ // balancing call to finishVault()
+ }
+ is PayPalPresentAuthChallengeResult.Failure -> TODO("Handle Present Auth Challenge Failure")
+ }
}
+ fun checkForPayPalAuthCompletion(intent: Intent) {
+ // check for checkout completion
+ payPalClient.finishStart(intent)?.let { checkoutResult ->
+ when (checkoutResult) {
+ is PayPalWebCheckoutFinishStartResult.Success -> TODO("Capture or authorize order on your server.")
+ is PayPalWebCheckoutFinishStartResult.Failure -> TODO("Handle approve order failure.")
+ is PayPalWebCheckoutFinishStartResult.Canceled -> TODO("Notify user PayPal checkout was canceled.")
+ PayPalWebCheckoutFinishStartResult.NoResult -> {
+ // there isn't enough information to determine the state of the auth challenge for this payment method
+ }
+ }
+ }
+
+ // check for vault completion
+ payPalClient.finishVault(intent)?.let { vaultResult ->
+ when (vaultResult) {
+ is PayPalWebCheckoutFinishVaultResult.Success -> TODO("Create payment token on your server.")
+ is PayPalWebCheckoutFinishVaultResult.Failure -> TODO("Handle card vault failure.")
+ is PayPalWebCheckoutFinishVaultResult.Canceled ->TODO("Notify user PayPal vault was canceled.")
+ PayPalWebCheckoutFinishVaultResult.NoResult -> {
+ // there isn't enough information to determine the state of the auth challenge for this payment method
+ }
+ }
+ }
+ }
- override fun onPayPalWebSuccess(result: PayPalWebCheckoutResult) {
- TODO("Capture or authorize order on your server.")
- }
- override fun onPayPalWebFailure(error: PayPalSDKError) {
- TODO("Handle approve order failure.")
- }
- override fun onPayPalWebCanceled() {
- TODO("Notify user PayPal checkout was canceled.")
- }
- fun onPayPalWebVaultSuccess(result: PayPalWebVaultResult) {
- TODO("Create payment token on your server.")
- }
- fun onPayPalWebVaultFailure(error: PayPalSDKError) {
- TODO("Handle card vault failure.")
- }
- fun onPayPalWebVaultCanceled() {
- TODO("Notify user PayPal vault was canceled.")
- }
}Notes on Changes to PayPal Web Payments in v2
Here are some detailed notes on the changes made to PayPal Web Payments in v2:
- In
v1the activity reference is only truly needed when the call toPayPalWebCheckoutClient#start()orPayPalWebCheckoutClient#vault()is made (to open a Chrome Custom Tab in the current Task). - In
v2thePayPalWebCheckoutClientconstructor no longer requires an activity reference. - The goal of this change is to increase flexibility of
PayPalWebCheckoutClientinstantiation.
- In
v1the SDK registers a lifecycle observer to parse incoming deep links when the host application comes into the foreground. - In
v2the host application is responsible for callingPayPalWebCheckoutClient#completeAuthChallenge()to attempt completion of an auth challenge. - The goal of this change is to make the SDK less opinionated and give host applications more control over the auth challenge user experience.
- In
v1the SDK would notify the host application of success, failure, etc. events using a registered listener - In
v2the host application will receive a sealed classResulttype in response to each method invocation - The goal of this change is to prevent having to retain listener references and to make auth challenge presentation more explicit
- Sealed class result types also have the added benefit of explicitly calling out all possible outcomes of a related method inovcation
We have removed PayPalNativeClient and all associated classes. The PayPal Native Checkout dependency this module uses has been discontinued.