Skip to content

Commit

Permalink
Merge V2 Beta Branch into Main (#293)
Browse files Browse the repository at this point in the history
* Remove PayPalNativePayments (#275)

* Remove PayPalNativePayments module from project.

* Remove Cardinal from build.gradle.

* Bump to latest version of actions/download-artifact in GitHub Actions workflow.

* Remove native checkout references.

* Remove additional Native XO referenced classes from Demo app.

* Fix lint errors.

* Migrate all GitHub actions to v4.

* Bump gson version.

* Fix versions after rebasing.

* Fix dependency error.

* Fix rebase CHANGELOG merge error.

* Add CHANGELOG update.

* V2 Beta Auth Challenge Migration (#276)

* Migrate CardClient away from observers.

* Remove activity from constructor parameters.

* Update Card and PayPal browser switch flows to include auth challenge types.

* Remove commented code.

* Remove commented code.

* Move CardPresentAuthChallengeResult to its own file.

* Move PayPalPresentAuthChallengeResult into its own file.

* Migrate all activity reference types to ComponentActivity.

* Fix compilation error.

* Modify tests to use new BrowserSwitch methods.

* Fix :Card module unit tests after refactoring.

* Fix PayPalWebCheckoutClient unit tests.

* Update PayPalWeb module unit tests.

* Fix detekt errors.

* Refactor Demo app method naming.

* Update gradle build plugin.

* Fix versions after rebasing.

* Fix detekt version catalog errors.

* Outline table of contents.

* Update migration guide with summary block.

* Update MIGRATION_GUIDE for CardClient.

* Try details region for v2/v1 snippets.

* Update markdown.

* Tweak formatting.

* Tweak formatting again.

* Make diff.

* Implement CardClient migration guide on constructor.

* Update migration guide.

* Try adding collapsable section.

* Add addtional expandable sections.

* Try h5.

* Update styling again.

* Tweak styling agaaain.

* Re-word docs.

* Re-arrange sections.

* Reword migration guide content.

* Update migration guide wording.

* Rephrase card client migration again.

* Lead with code in the migration guide.

* Use diff syntax.

* Add collapsable sections.

* Add collapsable sections.

* Reduce collapsable title verbosity.

* Update migration guide.

* Tweak collapsed layout.

* Simplify collapsed state in migration guide.

* Add approve order details to MIGRATION_GUIDE.

* Clean up migration guide.

* Update docs.

* Adjust comment again.

* Add sample activity callout.{

* Adjust naming.

* Add additional information on the approve order flow.

* Add additional information to migration guide on approve order.

* Rephrase approve order v1 details.

* Add TODO to migration guide.

* Add hyper links to table of contents.

* Update CHANGELOG.

* Browser Switch Bugfix (#281)

* Add browser switch request codes to launcher logic.

* Update Browser switch code.

* Update CardAuthLauncher to use request codes to differentiate browser switch results.

* Add request codes to browser switch requests.

* Fix build error with new CardStatus and PayPalWebStatus.

* Update BOM for Jetpack Compose.

* Update unit tests for CardAuthLauncher to include request code.

* Update unit test for browser switch options.

* Update PayPalWebLauncherUnitTest.

* Implement test for when browser switch fails.

* Add additional tests to PayPalWebLauncherUnitTest.

* Fix detekt lint errors.

* Update CHANGELOG.

* Remove metadata that's no longer needed.

* Remove request type from metadata.

* [V2 Beta] Migration Guide and Card Vault API Cleanup (#290)

* Tweak v2_MIGRATION_GUIDE table of contents.

* Remove redundant word Module in section headings.

* Tweak MIGRATION_GUIDE.

* Update wording.

* Update MIGRATION_GUIDE.

* Add additional comments.

* Update v2_MIGRATION_GUIDE format.

* Tweak migration guide formatting.

* Tweak migration guide.

* Tweak verbosity of migration guide.

* Update migration guide.

* Clean up comments.

* Update details header.

* Remove unecessary punctuation.

* Update title description.

* Rename onAuthorizationRequired to onApproveAuthorizationRequired.

* Update vault card integration.

* Update MIGRATION_GUIDE with latest interface.

* Add remove observers reference to MIGRATION_GUIDE.

* Add vault method reference in MIGRATION_GUIDE and co-locate Android lifecycle methods.

* Update migration guide for PayPal migration.

* Update CHANGELOG.

* Add to migration guide.

* Fix broken unit test.

* Fix lint errors.

* Update migration guide with PayPalWebCheckoutClient details.

* Add emoji to section headers.

* Fix section header font format.

* Fix wording.

* Update CHANGELOG.
  • Loading branch information
sshropshire authored Nov 19, 2024
1 parent 3407956 commit ef559fd
Show file tree
Hide file tree
Showing 86 changed files with 1,131 additions and 2,760 deletions.
17 changes: 1 addition & 16 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,21 +80,6 @@ jobs:
uses: ./.github/actions/unit_test_module
with:
module: PayPalWebPayments
unit_test_paypal_native:
name: PayPal Native Payments Unit Tests
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'microsoft'
- name: Run Unit Tests
uses: ./.github/actions/unit_test_module
with:
module: PayPalNativePayments
unit_test_fraud_protection:
name: Fraud Protection Unit Tests
runs-on: ubuntu-latest
Expand All @@ -112,7 +97,7 @@ jobs:
module: FraudProtection

unit_test_finished:
needs: [unit_test_card, unit_test_core, unit_test_paypal_web, unit_test_paypal_native, unit_test_fraud_protection]
needs: [unit_test_card, unit_test_core, unit_test_paypal_web, unit_test_fraud_protection]
name: All Unit Test finished
runs-on: ubuntu-latest
steps:
Expand Down
17 changes: 1 addition & 16 deletions .github/workflows/release_snapshot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,21 +83,6 @@ jobs:
uses: ./.github/actions/unit_test_module
with:
module: PayPalWebPayments
unit_test_paypal_native:
name: PayPal Native Payments Unit Tests
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'microsoft'
- name: Run Unit Tests
uses: ./.github/actions/unit_test_module
with:
module: PayPalNativePayments
unit_test_fraud_protection:
name: Fraud Protection Unit Tests
runs-on: ubuntu-latest
Expand All @@ -115,7 +100,7 @@ jobs:
module: FraudProtection

unit_test_finished:
needs: [unit_test_card, unit_test_core, unit_test_paypal_web, unit_test_paypal_native, unit_test_fraud_protection]
needs: [unit_test_card, unit_test_core, unit_test_paypal_web, unit_test_fraud_protection]
name: All Unit Test finished
runs-on: ubuntu-latest
steps:
Expand Down
4 changes: 0 additions & 4 deletions .github/workflows/static_analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ jobs:
CorePayments/build/outputs/aar/CorePayments-release.aar
CardPayments/build/outputs/aar/CardPayments-release.aar
PayPalWebPayments/build/outputs/aar/PayPalWebPayments-release.aar
PayPalNativePayments/build/outputs/aar/PayPalNativePayments-release.aar
PaymentButtons/build/outputs/aar/PaymentButtons-release.aar
FraudProtection/build/outputs/aar/FraudProtection-release.aar
Expand All @@ -75,7 +74,6 @@ jobs:
CorePayments/build/outputs/aar/CorePayments-release.aar
CardPayments/build/outputs/aar/CardPayments-release.aar
PayPalWebPayments/build/outputs/aar/PayPalWebPayments-release.aar
PayPalNativePayments/build/outputs/aar/PayPalNativePayments-release.aar
PaymentButtons/build/outputs/aar/PaymentButtons-release.aar
FraudProtection/build/outputs/aar/FraudProtection-release.aar
Expand All @@ -97,8 +95,6 @@ jobs:
run: diffuse diff --aar main-aar/CorePayments/build/outputs/aar/CorePayments-release.aar current-aar/CorePayments/build/outputs/aar/CorePayments-release.aar
- name: Run Diffuse Analysis - PayPalWebPayments
run: diffuse diff --aar main-aar/PayPalWebPayments/build/outputs/aar/PayPalWebPayments-release.aar current-aar/PayPalWebPayments/build/outputs/aar/PayPalWebPayments-release.aar
- name: Run Diffuse Analysis - PayPalNativePayments
run: diffuse diff --aar main-aar/PayPalNativePayments/build/outputs/aar/PayPalNativePayments-release.aar current-aar/PayPalNativePayments/build/outputs/aar/PayPalNativePayments-release.aar
- name: Run Diffuse Analysis - PaymentButtons
run: diffuse diff --aar main-aar/PaymentButtons/build/outputs/aar/PaymentButtons-release.aar current-aar/PaymentButtons/build/outputs/aar/PaymentButtons-release.aar
- name: Run Diffuse Analysis - FraudProtection
Expand Down
30 changes: 30 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,35 @@
# PayPal Android SDK Release Notes

# beta - unreleased
* Breaking Changes
* PayPalNativePayments
* Remove entire PayPalNativePayments module
* CardPayments
* Remove `CardClient(FragmentActivity, Config)` constructor
* Add `CardClient(Context, Config)` constructor
* Remove `CardClient.approveOrder(FragmentActivity, CardRequest)` method
* Add `CardClient.approveOrder(CardRequest)` method
* Remove `CardClient.presentAuthChallenge(FragmentActivity, CardAuthChallenge)` method
* Add `CardClient.presentAuthChallenge(ComponentActivity, CardAuthChallenge)` method
* Add `CardPresentAuthChallengeResult` type
* Add `CardClient.completeAuthChallenge(Intent, String)` method
* Add `CardStatus` type
* Add `ApproveOrderListener.onApproveOrderAuthorizationRequired(CardAuthChallenge)` method
* Add `CardVaultListener.onVaultAuthorizationRequired(CardAuthChallenge)` method
* Remove `authChallenge` property from `CardVaultResult`
* PayPalWebPayments
* Remove `PayPalWebCheckoutClient(FragmentActivity, CoreConfig, String)` constructor
* Add `PayPalWebCheckoutClient(Context, CoreConfig, String)` constructor
* Remove `PayPalWebCheckoutClient.start(PayPalWebCheckoutRequest)` method
* Add `PayPalWebCheckoutClient.start(ComponentActivity, PayPalWebCheckoutRequest)` method
* Remove `PayPalWebCheckoutClient.vault(PayPalWebVaultRequest)` method
* Add `PayPalWebCheckoutClient.vault(ComponentActivity, PayPalWebVaultRequest)` method
* Add `CardClient.completeAuthChallenge(Intent, String)` method
* Add `PayPalPresentAuthChallengeResult` type
* Add `PayPalWebStatus` type
* Gradle
* Update `browser-switch` version to `3.0.0-beta`

# unreleased
* Gradle
* Update Kotlin version to `1.9.24`
Expand Down
2 changes: 2 additions & 0 deletions CardPayments/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}

compileOptions {
sourceCompatibility modules.sourceCompatibility
targetCompatibility modules.targetCompatibility
}

kotlinOptions {
jvmTarget = modules.kotlinJvmTarget
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ interface ApproveOrderListener {
@MainThread
fun onApproveOrderSuccess(result: CardResult)

/**
* Called when authorization is required to continue.
*/
@MainThread
fun onApproveOrderAuthorizationRequired(authChallenge: CardAuthChallenge)

/**
* Called when the approval fails.
* @param error [PayPalSDKError] explaining the reason for failure.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,110 +1,84 @@
package com.paypal.android.cardpayments

import androidx.fragment.app.FragmentActivity
import android.content.Intent
import androidx.activity.ComponentActivity
import com.braintreepayments.api.BrowserSwitchClient
import com.braintreepayments.api.BrowserSwitchException
import com.braintreepayments.api.BrowserSwitchFinalResult
import com.braintreepayments.api.BrowserSwitchOptions
import com.braintreepayments.api.BrowserSwitchResult
import com.braintreepayments.api.BrowserSwitchStatus
import com.paypal.android.corepayments.PayPalSDKError
import com.braintreepayments.api.BrowserSwitchStartResult
import com.paypal.android.corepayments.BrowserSwitchRequestCodes
import org.json.JSONObject

internal class CardAuthLauncher(
private val browserSwitchClient: BrowserSwitchClient = BrowserSwitchClient(),
) {

companion object {
private const val METADATA_KEY_REQUEST_TYPE = "request_type"
private const val REQUEST_TYPE_APPROVE_ORDER = "approve_order"
private const val REQUEST_TYPE_VAULT = "vault"

private const val METADATA_KEY_ORDER_ID = "order_id"
private const val METADATA_KEY_SETUP_TOKEN_ID = "setup_token_id"
}

fun presentAuthChallenge(
activity: FragmentActivity,
activity: ComponentActivity,
authChallenge: CardAuthChallenge
): PayPalSDKError? {
): CardPresentAuthChallengeResult {
val metadata = when (authChallenge) {
is CardAuthChallenge.ApproveOrder -> {
val request = authChallenge.request
JSONObject()
.put(METADATA_KEY_REQUEST_TYPE, REQUEST_TYPE_APPROVE_ORDER)
.put(METADATA_KEY_ORDER_ID, request.orderId)
}

is CardAuthChallenge.Vault -> {
val request = authChallenge.request
JSONObject()
.put(METADATA_KEY_REQUEST_TYPE, REQUEST_TYPE_VAULT)
.put(METADATA_KEY_SETUP_TOKEN_ID, request.setupTokenId)
}
}

val requestCode = when (authChallenge) {
is CardAuthChallenge.ApproveOrder -> BrowserSwitchRequestCodes.CARD_APPROVE_ORDER
is CardAuthChallenge.Vault -> BrowserSwitchRequestCodes.CARD_VAULT
}

// launch the 3DS flow
val browserSwitchOptions = BrowserSwitchOptions()
.url(authChallenge.url)
.requestCode(requestCode)
.returnUrlScheme(authChallenge.returnUrlScheme)
.metadata(metadata)
return launchBrowserSwitch(activity, browserSwitchOptions)
}

private fun launchBrowserSwitch(
activity: FragmentActivity,
options: BrowserSwitchOptions
): PayPalSDKError? {
var error: PayPalSDKError? = null
try {
browserSwitchClient.start(activity, options)
} catch (e: BrowserSwitchException) {
error = CardError.browserSwitchError(e)
}
return error
}

fun deliverBrowserSwitchResult(activity: FragmentActivity) =
browserSwitchClient.deliverResult(activity)?.let { browserSwitchResult ->
val requestType =
browserSwitchResult.requestMetadata?.optString(METADATA_KEY_REQUEST_TYPE)
if (requestType == REQUEST_TYPE_VAULT) {
parseVaultResult(browserSwitchResult)
} else {
// Assume REQUEST_TYPE_APPROVE_ORDER
parseApproveOrderResult(browserSwitchResult)
return when (val startResult = browserSwitchClient.start(activity, browserSwitchOptions)) {
is BrowserSwitchStartResult.Started -> {
CardPresentAuthChallengeResult.Success(startResult.pendingRequest)
}
}

private fun parseVaultResult(browserSwitchResult: BrowserSwitchResult): CardStatus? {
val setupTokenId =
browserSwitchResult.requestMetadata?.optString(METADATA_KEY_SETUP_TOKEN_ID)
return when (browserSwitchResult.status) {
BrowserSwitchStatus.SUCCESS -> parseVaultSuccessResult(browserSwitchResult)
BrowserSwitchStatus.CANCELED -> CardStatus.VaultCanceled(setupTokenId)
else -> null
is BrowserSwitchStartResult.Failure -> {
val error = CardError.browserSwitchError(startResult.error)
CardPresentAuthChallengeResult.Failure(error)
}
}
}

private fun parseApproveOrderResult(browserSwitchResult: BrowserSwitchResult): CardStatus? {
val orderId = browserSwitchResult.requestMetadata?.optString(METADATA_KEY_ORDER_ID)
return if (orderId == null) {
CardStatus.ApproveOrderError(CardError.unknownError, orderId)
} else {
when (browserSwitchResult.status) {
BrowserSwitchStatus.SUCCESS ->
parseApproveOrderSuccessResult(browserSwitchResult, orderId)
fun completeAuthRequest(intent: Intent, authState: String): CardStatus =
when (val finalResult = browserSwitchClient.completeRequest(intent, authState)) {
is BrowserSwitchFinalResult.Success -> parseBrowserSwitchSuccessResult(finalResult)
is BrowserSwitchFinalResult.Failure -> CardStatus.UnknownError(finalResult.error)
BrowserSwitchFinalResult.NoResult -> CardStatus.NoResult
}

BrowserSwitchStatus.CANCELED -> CardStatus.ApproveOrderCanceled(orderId)
else -> null
}
private fun parseBrowserSwitchSuccessResult(result: BrowserSwitchFinalResult.Success): CardStatus =
when (result.requestCode) {
BrowserSwitchRequestCodes.CARD_APPROVE_ORDER -> parseApproveOrderSuccessResult(result)
BrowserSwitchRequestCodes.CARD_VAULT -> parseVaultSuccessResult(result)
else -> CardStatus.NoResult
}
}

private fun parseVaultSuccessResult(browserSwitchResult: BrowserSwitchResult): CardStatus {
val deepLinkUrl = browserSwitchResult.deepLinkUrl
val requestMetadata = browserSwitchResult.requestMetadata
private fun parseVaultSuccessResult(finalResult: BrowserSwitchFinalResult.Success): CardStatus {
val deepLinkUrl = finalResult.returnUrl
val requestMetadata = finalResult.requestMetadata

return if (deepLinkUrl == null || requestMetadata == null) {
return if (requestMetadata == null) {
CardStatus.VaultError(CardError.unknownError)
} else {
// TODO: see if there's a way that we can require the merchant to make their
Expand All @@ -113,7 +87,7 @@ internal class CardAuthLauncher(
// NOTE: this assumes that when the merchant created a setup token, they used a
// return_url with word "success" in it (or a cancel_url with the word "cancel" in it)
val setupTokenId =
browserSwitchResult.requestMetadata?.optString(METADATA_KEY_SETUP_TOKEN_ID)
finalResult.requestMetadata?.optString(METADATA_KEY_SETUP_TOKEN_ID)
val deepLinkUrlString = deepLinkUrl.toString()
val didSucceed = deepLinkUrlString.contains("success")
if (didSucceed) {
Expand All @@ -131,12 +105,14 @@ internal class CardAuthLauncher(
}

private fun parseApproveOrderSuccessResult(
browserSwitchResult: BrowserSwitchResult,
orderId: String
finalResult: BrowserSwitchFinalResult.Success,
): CardStatus {
val deepLinkUrl = browserSwitchResult.deepLinkUrl
val deepLinkUrl = finalResult.returnUrl
val orderId = finalResult.requestMetadata?.optString(METADATA_KEY_ORDER_ID)

return if (deepLinkUrl == null || deepLinkUrl.getQueryParameter("error") != null) {
return if (orderId == null) {
CardStatus.ApproveOrderError(CardError.unknownError, null)
} else if (deepLinkUrl.getQueryParameter("error") != null) {
CardStatus.ApproveOrderError(CardError.threeDSVerificationError, orderId)
} else {
val state = deepLinkUrl.getQueryParameter("state")
Expand Down
Loading

0 comments on commit ef559fd

Please sign in to comment.