diff --git a/CHANGELOG.md b/CHANGELOG.md index 966871e27..5438c6cb3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # PayPal Android SDK Release Notes ## unreleased +* PayPalWebPayments + * Deprecate `PayPalWebVaultRequest(setupTokenId, approveVaultHref)` + * Add `PayPalWebVaultRequest(setupTokenId)` * PayPalNativePayments (DEPRECATED) * **NOTE:** This module is being deprecated and will be removed in the future version of the SDK. Use `PayPalWebPayments` module instead. * Add deprecated warning message to all classes diff --git a/Demo/src/main/java/com/paypal/android/api/model/PayPalSetupToken.kt b/Demo/src/main/java/com/paypal/android/api/model/PayPalSetupToken.kt index 9f1d3196b..69fbb6774 100644 --- a/Demo/src/main/java/com/paypal/android/api/model/PayPalSetupToken.kt +++ b/Demo/src/main/java/com/paypal/android/api/model/PayPalSetupToken.kt @@ -3,6 +3,5 @@ package com.paypal.android.api.model data class PayPalSetupToken( val id: String, val customerId: String, - val status: String, - val approveVaultHref: String? = null + val status: String ) diff --git a/Demo/src/main/java/com/paypal/android/api/services/SDKSampleServerAPI.kt b/Demo/src/main/java/com/paypal/android/api/services/SDKSampleServerAPI.kt index 93326afc1..fd1c38b41 100644 --- a/Demo/src/main/java/com/paypal/android/api/services/SDKSampleServerAPI.kt +++ b/Demo/src/main/java/com/paypal/android/api/services/SDKSampleServerAPI.kt @@ -13,7 +13,6 @@ import com.paypal.checkout.order.OrderRequest import okhttp3.OkHttpClient import okhttp3.ResponseBody import okhttp3.logging.HttpLoggingInterceptor -import org.json.JSONArray import org.json.JSONObject import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory @@ -255,13 +254,11 @@ class SDKSampleServerAPI { val responseJSON = JSONObject(response.string()) val customerJSON = responseJSON.getJSONObject("customer") - val approveVaultHref = findApprovalHref(responseJSON) PayPalSetupToken( id = responseJSON.getString("id"), customerId = customerJSON.getString("id"), - status = responseJSON.getString("status"), - approveVaultHref = approveVaultHref + status = responseJSON.getString("status") ) } @@ -290,15 +287,4 @@ class SDKSampleServerAPI { customerId = optNonEmptyString(vaultCustomerJSON, "id") ) } - - private fun findApprovalHref(responseJSON: JSONObject): String? { - val linksJSON = responseJSON.optJSONArray("links") ?: JSONArray() - for (i in 0 until linksJSON.length()) { - val link = linksJSON.getJSONObject(i) - if (link.getString("rel") == "approve") { - return link.getString("href") - } - } - return null - } } diff --git a/Demo/src/main/java/com/paypal/android/ui/paypalwebvault/PayPalWebVaultViewModel.kt b/Demo/src/main/java/com/paypal/android/ui/paypalwebvault/PayPalWebVaultViewModel.kt index 81e789a8b..ecd3d7874 100644 --- a/Demo/src/main/java/com/paypal/android/ui/paypalwebvault/PayPalWebVaultViewModel.kt +++ b/Demo/src/main/java/com/paypal/android/ui/paypalwebvault/PayPalWebVaultViewModel.kt @@ -69,12 +69,11 @@ class PayPalWebVaultViewModel @Inject constructor( fun vaultSetupToken(activity: AppCompatActivity) { val setupTokenId = createdSetupToken?.id - val setupTokenApprovalHref = createdSetupToken?.approveVaultHref - if (setupTokenId == null || setupTokenApprovalHref == null) { + if (setupTokenId == null) { vaultPayPalState = ActionState.Failure(Exception("Create a setup token to continue.")) } else { viewModelScope.launch { - val request = PayPalWebVaultRequest(setupTokenId, setupTokenApprovalHref) + val request = PayPalWebVaultRequest(setupTokenId) vaultSetupTokenWithRequest(activity, request) } } diff --git a/PayPalWebPayments/src/main/java/com/paypal/android/paypalwebpayments/PayPalWebLauncher.kt b/PayPalWebPayments/src/main/java/com/paypal/android/paypalwebpayments/PayPalWebLauncher.kt index 39a5dad8a..4e9843c94 100644 --- a/PayPalWebPayments/src/main/java/com/paypal/android/paypalwebpayments/PayPalWebLauncher.kt +++ b/PayPalWebPayments/src/main/java/com/paypal/android/paypalwebpayments/PayPalWebLauncher.kt @@ -56,8 +56,9 @@ internal class PayPalWebLauncher( val metadata = JSONObject() .put(METADATA_KEY_SETUP_TOKEN_ID, request.setupTokenId) .put(METADATA_KEY_REQUEST_TYPE, REQUEST_TYPE_VAULT) + val url = request.run { buildPayPalVaultUri(request.setupTokenId, coreConfig) } val browserSwitchOptions = BrowserSwitchOptions() - .url(Uri.parse(request.approveVaultHref)) + .url(url) .returnUrlScheme(urlScheme) .metadata(metadata) return launchBrowserSwitch(activity, browserSwitchOptions) @@ -95,6 +96,20 @@ internal class PayPalWebLauncher( .build() } + private fun buildPayPalVaultUri( + setupTokenId: String, + config: CoreConfig + ): Uri { + val baseURL = when (config.environment) { + Environment.LIVE -> "https://paypal.com/agreements/approve" + Environment.SANDBOX -> "https://sandbox.paypal.com/agreements/approve" + } + return Uri.parse(baseURL) + .buildUpon() + .appendQueryParameter("approval_session_id", setupTokenId) + .build() + } + fun deliverBrowserSwitchResult(activity: FragmentActivity) = browserSwitchClient.deliverResult(activity)?.let { browserSwitchResult -> val requestType = diff --git a/PayPalWebPayments/src/main/java/com/paypal/android/paypalwebpayments/PayPalWebVaultRequest.kt b/PayPalWebPayments/src/main/java/com/paypal/android/paypalwebpayments/PayPalWebVaultRequest.kt index 2088c7551..2224f049a 100644 --- a/PayPalWebPayments/src/main/java/com/paypal/android/paypalwebpayments/PayPalWebVaultRequest.kt +++ b/PayPalWebPayments/src/main/java/com/paypal/android/paypalwebpayments/PayPalWebVaultRequest.kt @@ -6,7 +6,17 @@ package com.paypal.android.paypalwebpayments * @property [setupTokenId] ID for the setup token associated with the vault approval * @property [approveVaultHref] URL for the approval web page */ -data class PayPalWebVaultRequest( +data class PayPalWebVaultRequest @Deprecated("Use PayPalWebVaultRequest(setupTokenId) instead.") +constructor( val setupTokenId: String, - val approveVaultHref: String -) + @Deprecated("The approveVaultHref property is no longer required and will be ignored.") + val approveVaultHref: String? // NEXT_MAJOR_VERSION: - Remove this property +) { + + /** + * Request to vault a PayPal payment method using [PayPalWebCheckoutClient.vault]. + * + * @property [setupTokenId] ID for the setup token associated with the vault approval + */ + constructor(setupTokenId: String) : this(setupTokenId, null) +} diff --git a/PayPalWebPayments/src/test/java/com/paypal/android/paypalwebpayments/PayPalWebCheckoutClientUnitTest.kt b/PayPalWebPayments/src/test/java/com/paypal/android/paypalwebpayments/PayPalWebCheckoutClientUnitTest.kt index 60427d0cf..36e66c86f 100644 --- a/PayPalWebPayments/src/test/java/com/paypal/android/paypalwebpayments/PayPalWebCheckoutClientUnitTest.kt +++ b/PayPalWebPayments/src/test/java/com/paypal/android/paypalwebpayments/PayPalWebCheckoutClientUnitTest.kt @@ -72,7 +72,7 @@ class PayPalWebCheckoutClientUnitTest { every { payPalWebLauncher.launchPayPalWebVault(any(), any()) } returns null val request = - PayPalWebVaultRequest("fake-setup-token-id", "https://example.com/approval/url") + PayPalWebVaultRequest("fake-setup-token-id") sut.vault(request) verify(exactly = 1) { payPalWebLauncher.launchPayPalWebVault(activity, request) } verify(exactly = 0) { vaultListener.onPayPalWebVaultFailure(any()) } @@ -86,7 +86,7 @@ class PayPalWebCheckoutClientUnitTest { every { payPalWebLauncher.launchPayPalWebVault(any(), any()) } returns sdkError val request = - PayPalWebVaultRequest("fake-setup-token-id", "https://example.com/approval/url") + PayPalWebVaultRequest("fake-setup-token-id") sut.vault(request) val slot = slot() diff --git a/PayPalWebPayments/src/test/java/com/paypal/android/paypalwebpayments/PayPalWebLauncherUnitTest.kt b/PayPalWebPayments/src/test/java/com/paypal/android/paypalwebpayments/PayPalWebLauncherUnitTest.kt index 562d63ca5..c195d6583 100644 --- a/PayPalWebPayments/src/test/java/com/paypal/android/paypalwebpayments/PayPalWebLauncherUnitTest.kt +++ b/PayPalWebPayments/src/test/java/com/paypal/android/paypalwebpayments/PayPalWebLauncherUnitTest.kt @@ -161,22 +161,46 @@ class PayPalWebLauncherUnitTest { } @Test - fun `launchPayPalWebVault() browser switches to approval url`() { + fun `launchPayPalWebVault() browser switches to SANDBOX PayPal vault checkout`() { sut = PayPalWebLauncher("custom_url_scheme", sandboxConfig, browserSwitchClient) val slot = slot() every { browserSwitchClient.start(activity, capture(slot)) } just runs - val vaultRequest = - PayPalWebVaultRequest("fake-setup-token-id", "https://example.com/approval/url") - sut.launchPayPalWebVault(activity, vaultRequest) + val request = PayPalWebVaultRequest("fake-setup-token") + sut.launchPayPalWebVault(activity, request) + + val expectedUrl = "https://sandbox.paypal.com/agreements/approve?" + + "approval_session_id=fake-setup-token" + + val browserSwitchOptions = slot.captured + expectThat(browserSwitchOptions) { + get { metadata?.get("setup_token_id") }.isEqualTo("fake-setup-token") + get { metadata?.get("request_type") }.isEqualTo("vault") + get { returnUrlScheme }.isEqualTo("custom_url_scheme") + get { url }.isEqualTo(Uri.parse(expectedUrl)) + } + } + + @Test + fun `launchPayPalWebVault() browser switches to LIVE PayPal vault checkout`() { + sut = PayPalWebLauncher("custom_url_scheme", liveConfig, browserSwitchClient) + + val slot = slot() + every { browserSwitchClient.start(activity, capture(slot)) } just runs + + val request = PayPalWebVaultRequest("fake-setup-token") + sut.launchPayPalWebVault(activity, request) + + val expectedUrl = "https://paypal.com/agreements/approve?" + + "approval_session_id=fake-setup-token" val browserSwitchOptions = slot.captured expectThat(browserSwitchOptions) { - get { metadata?.get("setup_token_id") }.isEqualTo("fake-setup-token-id") + get { metadata?.get("setup_token_id") }.isEqualTo("fake-setup-token") get { metadata?.get("request_type") }.isEqualTo("vault") get { returnUrlScheme }.isEqualTo("custom_url_scheme") - get { url }.isEqualTo(Uri.parse("https://example.com/approval/url")) + get { url }.isEqualTo(Uri.parse(expectedUrl)) } } @@ -190,7 +214,7 @@ class PayPalWebLauncherUnitTest { every { browserSwitchClient.start(any(), any()) } throws browserSwitchException val vaultRequest = - PayPalWebVaultRequest("fake-setup-token-id", "https://example.com/approval/url") + PayPalWebVaultRequest("fake-setup-token-id") sut.launchPayPalWebVault(activity, vaultRequest) val request = PayPalWebCheckoutRequest("fake-order-id")