From b51ef9d32adc83949a908e33a5efaa74802aa14a Mon Sep 17 00:00:00 2001 From: Sarah Koop Date: Tue, 5 Dec 2023 09:34:13 -0600 Subject: [PATCH 1/7] Add CardResult --- .../braintreepayments/api/CardClientTest.java | 12 ++++----- .../com/braintreepayments/api/CardClient.java | 26 +++++++++---------- .../com/braintreepayments/api/CardResult.kt | 18 +++++++++++++ .../api/CardTokenizeCallback.java | 7 ++--- .../api/CardClientUnitTest.java | 10 +++---- .../braintreepayments/demo/CardFragment.java | 2 +- 6 files changed, 45 insertions(+), 30 deletions(-) create mode 100644 Card/src/main/java/com/braintreepayments/api/CardResult.kt diff --git a/Card/src/androidTest/java/com/braintreepayments/api/CardClientTest.java b/Card/src/androidTest/java/com/braintreepayments/api/CardClientTest.java index 675943606a..60cb9f31c7 100644 --- a/Card/src/androidTest/java/com/braintreepayments/api/CardClientTest.java +++ b/Card/src/androidTest/java/com/braintreepayments/api/CardClientTest.java @@ -124,7 +124,7 @@ public void tokenize_failsWithTokenizationKeyAndValidateTrue() throws Exception CardClient sut = setupCardClient(TOKENIZATION_KEY); sut.tokenize(card, new CardTokenizeCallback() { @Override - public void onResult(CardNonce cardNonce, Exception error) { + public void onCardResult(CardResult cardResult) { assertTrue(error instanceof AuthorizationException); if (requestProtocol.equals(GRAPHQL)) { @@ -167,7 +167,7 @@ public void tokenize_tokenizesCvvOnly() throws Exception { CardClient sut = setupCardClient(TOKENIZATION_KEY); sut.tokenize(card, new CardTokenizeCallback() { @Override - public void onResult(CardNonce cardNonce, Exception error) { + public void onCardResult(CardResult cardResult) { assertNotNull(cardNonce.getBinData()); assertEquals("Unknown", cardNonce.getCardType()); @@ -196,7 +196,7 @@ public void tokenize_callsErrorCallbackForInvalidCvv() throws Exception { final CountDownLatch countDownLatch = new CountDownLatch(1); CardClient sut = setupCardClient(authorization); - sut.tokenize(card, (cardNonce, error) -> { + sut.tokenize(card, (cardResult) -> { assertEquals("CVV verification failed", ((ErrorWithResponse) error).errorFor("creditCard").getFieldErrors().get(0).getMessage()); countDownLatch.countDown(); @@ -231,7 +231,7 @@ public void tokenize_callsErrorCallbackForInvalidPostalCode() throws Exception { final CountDownLatch countDownLatch = new CountDownLatch(1); CardClient sut = setupCardClient(authorization); - sut.tokenize(card, (cardNonce, error) -> { + sut.tokenize(card, (cardResult) -> { assertEquals("Postal code verification failed", ((ErrorWithResponse) error).errorFor("creditCard").errorFor("billingAddress") .getFieldErrors().get(0).getMessage()); @@ -254,7 +254,7 @@ public void tokenize_whenInvalidCountryCode_callsErrorCallbackWithDetailedError( final CountDownLatch countDownLatch = new CountDownLatch(1); CardClient sut = setupCardClient(authorization); - sut.tokenize(card, (cardNonce, error) -> { + sut.tokenize(card, (cardResult) -> { assertEquals("Country code (alpha3) is not an accepted country", ((ErrorWithResponse) error).errorFor("creditCard").errorFor("billingAddress") .getFieldErrors().get(0).getMessage()); @@ -292,7 +292,7 @@ private void assertTokenizationSuccessful(String authorization, Card card) throw CardClient sut = new CardClient(braintreeClient); final CountDownLatch countDownLatch = new CountDownLatch(1); - sut.tokenize(card, (cardNonce, error) -> { + sut.tokenize(card, (cardResult) -> { assertNotNull(cardNonce.getString()); assertEquals("Visa", cardNonce.getCardType()); diff --git a/Card/src/main/java/com/braintreepayments/api/CardClient.java b/Card/src/main/java/com/braintreepayments/api/CardClient.java index 5c23f6722a..dbaf23006e 100644 --- a/Card/src/main/java/com/braintreepayments/api/CardClient.java +++ b/Card/src/main/java/com/braintreepayments/api/CardClient.java @@ -3,7 +3,6 @@ import android.content.Context; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import org.json.JSONException; @@ -46,17 +45,18 @@ public CardClient(@NonNull Context context, @NonNull String authorization) { * The tokenization result is returned via a {@link CardTokenizeCallback} callback. * *

- * On success, the {@link CardTokenizeCallback#onResult(CardNonce, Exception)} method will be - * invoked with a nonce. + * On success, the {@link CardTokenizeCallback#onCardResult(CardResult)} method will be + * invoked with a {@link CardResult.Success} including a nonce. * *

- * If creation fails validation, the {@link CardTokenizeCallback#onResult(CardNonce, Exception)} - * method will be invoked with an {@link ErrorWithResponse} exception. + * If creation fails validation, the {@link CardTokenizeCallback#onCardResult(CardResult)} + * method will be invoked with a {@link CardResult.Failure} including an + * {@link ErrorWithResponse} exception. * *

* If an error not due to validation (server error, network issue, etc.) occurs, the - * {@link CardTokenizeCallback#onResult(CardNonce, Exception)} method will be invoked with an - * {@link Exception} describing the error. + * {@link CardTokenizeCallback#onCardResult(CardResult)} method will be invoked with a + * {@link CardResult.Failure} with an {@link Exception} describing the error. * * @param card {@link Card} * @param callback {@link CardTokenizeCallback} @@ -64,7 +64,7 @@ public CardClient(@NonNull Context context, @NonNull String authorization) { public void tokenize(@NonNull final Card card, @NonNull final CardTokenizeCallback callback) { braintreeClient.getConfiguration((configuration, error) -> { if (error != null) { - callback.onResult(null, error); + callback.onCardResult(new CardResult.Failure(error)); return; } @@ -80,7 +80,7 @@ public void tokenize(@NonNull final Card card, @NonNull final CardTokenizeCallba (tokenizationResponse, exception) -> handleTokenizeResponse( tokenizationResponse, exception, callback)); } catch (BraintreeException | JSONException e) { - callback.onResult(null, e); + callback.onCardResult(new CardResult.Failure(e)); } } else { apiClient.tokenizeREST(card, @@ -96,15 +96,15 @@ private void handleTokenizeResponse(JSONObject tokenizationResponse, Exception e try { CardNonce cardNonce = CardNonce.fromJSON(tokenizationResponse); - callback.onResult(cardNonce, null); + callback.onCardResult(new CardResult.Success(cardNonce)); braintreeClient.sendAnalyticsEvent("card.nonce-received"); } catch (JSONException e) { - callback.onResult(null, e); + callback.onCardResult(new CardResult.Failure(e)); braintreeClient.sendAnalyticsEvent("card.nonce-failed"); } - } else { - callback.onResult(null, exception); + } else if (exception != null) { + callback.onCardResult(new CardResult.Failure(exception)); braintreeClient.sendAnalyticsEvent("card.nonce-failed"); } } diff --git a/Card/src/main/java/com/braintreepayments/api/CardResult.kt b/Card/src/main/java/com/braintreepayments/api/CardResult.kt new file mode 100644 index 0000000000..2b3390c7ff --- /dev/null +++ b/Card/src/main/java/com/braintreepayments/api/CardResult.kt @@ -0,0 +1,18 @@ +package com.braintreepayments.api + +/** + * Result of tokenizing a [Card] + */ +sealed class CardResult { + + /** + * The card tokenization completed successfully. This [nonce] should be sent to your server. + */ + class Success(val nonce: CardNonce) : CardResult() + + /** + * There was an [error] during card tokenization. + */ + class Failure(val error: Exception) : CardResult() + +} diff --git a/Card/src/main/java/com/braintreepayments/api/CardTokenizeCallback.java b/Card/src/main/java/com/braintreepayments/api/CardTokenizeCallback.java index f82159b48c..145108e9a6 100644 --- a/Card/src/main/java/com/braintreepayments/api/CardTokenizeCallback.java +++ b/Card/src/main/java/com/braintreepayments/api/CardTokenizeCallback.java @@ -1,15 +1,12 @@ package com.braintreepayments.api; -import androidx.annotation.Nullable; - /** * Callback for receiving result of {@link CardClient#tokenize(Card, CardTokenizeCallback)}. */ public interface CardTokenizeCallback { /** - * @param cardNonce {@link CardNonce} - * @param error an exception that occurred while tokenizing card + * @param cardResult a {@link CardResult} containing a {@link CardNonce} or {@link Exception} */ - void onResult(@Nullable CardNonce cardNonce, @Nullable Exception error); + void onCardResult(CardResult cardResult); } diff --git a/Card/src/test/java/com/braintreepayments/api/CardClientUnitTest.java b/Card/src/test/java/com/braintreepayments/api/CardClientUnitTest.java index a14cfd559d..084a2c28d3 100644 --- a/Card/src/test/java/com/braintreepayments/api/CardClientUnitTest.java +++ b/Card/src/test/java/com/braintreepayments/api/CardClientUnitTest.java @@ -76,7 +76,7 @@ public void tokenize_whenGraphQLEnabled_tokenizesWithGraphQL() throws JSONExcept sut.tokenize(card, cardTokenizeCallback); ArgumentCaptor captor = ArgumentCaptor.forClass(CardNonce.class); - verify(cardTokenizeCallback).onResult(captor.capture(), isNull()); + verify(cardTokenizeCallback).onCardResult(captor.capture()); CardNonce cardNonce = captor.getValue(); assertEquals("3744a73e-b1ab-0dbd-85f0-c12a0a4bd3d1", cardNonce.getString()); @@ -97,7 +97,7 @@ public void tokenize_whenGraphQLDisabled_tokenizesWithREST() throws JSONExceptio sut.tokenize(card, cardTokenizeCallback); ArgumentCaptor captor = ArgumentCaptor.forClass(CardNonce.class); - verify(cardTokenizeCallback).onResult(captor.capture(), isNull()); + verify(cardTokenizeCallback).onCardResult(captor.capture()); CardNonce cardNonce = captor.getValue(); assertEquals("123456-12345-12345-a-adfa", cardNonce.getString()); @@ -149,7 +149,7 @@ public void tokenize_whenGraphQLEnabled_callsListenerWithErrorOnFailure() { CardClient sut = new CardClient(braintreeClient, apiClient); sut.tokenize(card, cardTokenizeCallback); - verify(cardTokenizeCallback).onResult(null, error); + verify(cardTokenizeCallback).onCardResult(null); } @Test @@ -166,7 +166,7 @@ public void tokenize_whenGraphQLDisabled_callsListenerWithErrorOnFailure() { CardClient sut = new CardClient(braintreeClient, apiClient); sut.tokenize(card, cardTokenizeCallback); - verify(cardTokenizeCallback).onResult(null, error); + verify(cardTokenizeCallback).onCardResult(null); } @Test @@ -213,6 +213,6 @@ public void tokenize_propagatesConfigurationFetchError() { CardClient sut = new CardClient(braintreeClient, apiClient); sut.tokenize(card, cardTokenizeCallback); - verify(cardTokenizeCallback).onResult(null, configError); + verify(cardTokenizeCallback).onCardResult(null); } } \ No newline at end of file diff --git a/Demo/src/main/java/com/braintreepayments/demo/CardFragment.java b/Demo/src/main/java/com/braintreepayments/demo/CardFragment.java index 5b6cb5fd4b..c22ba2c872 100644 --- a/Demo/src/main/java/com/braintreepayments/demo/CardFragment.java +++ b/Demo/src/main/java/com/braintreepayments/demo/CardFragment.java @@ -182,7 +182,7 @@ public void onPurchase(View v) { card.setShouldValidate(false); card.setPostalCode(cardForm.getPostalCode()); - cardClient.tokenize(card, (cardNonce, tokenizeError) -> { + cardClient.tokenize(card, (cardResult) -> { if (cardNonce != null) { handlePaymentMethodNonceCreated(cardNonce); } else { From 4d3e700ff091541fdcf402315efedb375c92836b Mon Sep 17 00:00:00 2001 From: Sarah Koop Date: Tue, 5 Dec 2023 09:58:34 -0600 Subject: [PATCH 2/7] Fix unit tests --- .../api/CardClientUnitTest.java | 37 +++++++++++++++---- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/Card/src/test/java/com/braintreepayments/api/CardClientUnitTest.java b/Card/src/test/java/com/braintreepayments/api/CardClientUnitTest.java index 084a2c28d3..09563f061c 100644 --- a/Card/src/test/java/com/braintreepayments/api/CardClientUnitTest.java +++ b/Card/src/test/java/com/braintreepayments/api/CardClientUnitTest.java @@ -1,6 +1,7 @@ package com.braintreepayments.api; import static junit.framework.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.mock; @@ -75,10 +76,12 @@ public void tokenize_whenGraphQLEnabled_tokenizesWithGraphQL() throws JSONExcept sut.tokenize(card, cardTokenizeCallback); - ArgumentCaptor captor = ArgumentCaptor.forClass(CardNonce.class); + ArgumentCaptor captor = ArgumentCaptor.forClass(CardResult.class); verify(cardTokenizeCallback).onCardResult(captor.capture()); - CardNonce cardNonce = captor.getValue(); + CardResult result = captor.getValue(); + assertTrue(result instanceof CardResult.Success); + CardNonce cardNonce = ((CardResult.Success) result).getNonce(); assertEquals("3744a73e-b1ab-0dbd-85f0-c12a0a4bd3d1", cardNonce.getString()); } @@ -96,10 +99,12 @@ public void tokenize_whenGraphQLDisabled_tokenizesWithREST() throws JSONExceptio sut.tokenize(card, cardTokenizeCallback); - ArgumentCaptor captor = ArgumentCaptor.forClass(CardNonce.class); + ArgumentCaptor captor = ArgumentCaptor.forClass(CardResult.class); verify(cardTokenizeCallback).onCardResult(captor.capture()); - CardNonce cardNonce = captor.getValue(); + CardResult result = captor.getValue(); + assertTrue(result instanceof CardResult.Success); + CardNonce cardNonce = ((CardResult.Success) result).getNonce(); assertEquals("123456-12345-12345-a-adfa", cardNonce.getString()); } @@ -149,7 +154,13 @@ public void tokenize_whenGraphQLEnabled_callsListenerWithErrorOnFailure() { CardClient sut = new CardClient(braintreeClient, apiClient); sut.tokenize(card, cardTokenizeCallback); - verify(cardTokenizeCallback).onCardResult(null); + ArgumentCaptor captor = ArgumentCaptor.forClass(CardResult.class); + verify(cardTokenizeCallback).onCardResult(captor.capture()); + + CardResult result = captor.getValue(); + assertTrue(result instanceof CardResult.Failure); + Exception actualError = ((CardResult.Failure) result).getError(); + assertEquals(error, actualError); } @Test @@ -166,7 +177,13 @@ public void tokenize_whenGraphQLDisabled_callsListenerWithErrorOnFailure() { CardClient sut = new CardClient(braintreeClient, apiClient); sut.tokenize(card, cardTokenizeCallback); - verify(cardTokenizeCallback).onCardResult(null); + ArgumentCaptor captor = ArgumentCaptor.forClass(CardResult.class); + verify(cardTokenizeCallback).onCardResult(captor.capture()); + + CardResult result = captor.getValue(); + assertTrue(result instanceof CardResult.Failure); + Exception actualError = ((CardResult.Failure) result).getError(); + assertEquals(error, actualError); } @Test @@ -213,6 +230,12 @@ public void tokenize_propagatesConfigurationFetchError() { CardClient sut = new CardClient(braintreeClient, apiClient); sut.tokenize(card, cardTokenizeCallback); - verify(cardTokenizeCallback).onCardResult(null); + ArgumentCaptor captor = ArgumentCaptor.forClass(CardResult.class); + verify(cardTokenizeCallback).onCardResult(captor.capture()); + + CardResult result = captor.getValue(); + assertTrue(result instanceof CardResult.Failure); + Exception actualError = ((CardResult.Failure) result).getError(); + assertEquals(configError, actualError); } } \ No newline at end of file From 5de963195bad2d318612b897cfe4e0731e49f95e Mon Sep 17 00:00:00 2001 From: Sarah Koop Date: Tue, 5 Dec 2023 10:01:29 -0600 Subject: [PATCH 3/7] Fix integration tests --- .../braintreepayments/api/CardClientTest.java | 60 ++++++++++--------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/Card/src/androidTest/java/com/braintreepayments/api/CardClientTest.java b/Card/src/androidTest/java/com/braintreepayments/api/CardClientTest.java index 60cb9f31c7..5298587432 100644 --- a/Card/src/androidTest/java/com/braintreepayments/api/CardClientTest.java +++ b/Card/src/androidTest/java/com/braintreepayments/api/CardClientTest.java @@ -122,21 +122,20 @@ public void tokenize_failsWithTokenizationKeyAndValidateTrue() throws Exception final CountDownLatch countDownLatch = new CountDownLatch(1); CardClient sut = setupCardClient(TOKENIZATION_KEY); - sut.tokenize(card, new CardTokenizeCallback() { - @Override - public void onCardResult(CardResult cardResult) { - assertTrue(error instanceof AuthorizationException); - - if (requestProtocol.equals(GRAPHQL)) { - assertEquals("You are unauthorized to perform input validation with the provided authentication credentials.", - error.getMessage()); - } else { - assertEquals("Tokenization key authorization not allowed for this endpoint. Please use an " + - "authentication method with upgraded permissions", error.getMessage()); - } - - countDownLatch.countDown(); + sut.tokenize(card, cardResult -> { + assertTrue(cardResult instanceof CardResult.Failure); + Exception error = ((CardResult.Failure) cardResult).getError(); + assertTrue(error instanceof AuthorizationException); + + if (requestProtocol.equals(GRAPHQL)) { + assertEquals("You are unauthorized to perform input validation with the provided authentication credentials.", + error.getMessage()); + } else { + assertEquals("Tokenization key authorization not allowed for this endpoint. Please use an " + + "authentication method with upgraded permissions", error.getMessage()); } + + countDownLatch.countDown(); }); countDownLatch.await(); @@ -165,19 +164,18 @@ public void tokenize_tokenizesCvvOnly() throws Exception { card.setCvv("123"); CardClient sut = setupCardClient(TOKENIZATION_KEY); - sut.tokenize(card, new CardTokenizeCallback() { - @Override - public void onCardResult(CardResult cardResult) { - - assertNotNull(cardNonce.getBinData()); - assertEquals("Unknown", cardNonce.getCardType()); - assertEquals("", cardNonce.getLastFour()); - assertEquals("", cardNonce.getLastTwo()); - assertFalse(cardNonce.isDefault()); - assertNotNull(cardNonce.getString()); - - countDownLatch.countDown(); - } + sut.tokenize(card, cardResult -> { + assertTrue(cardResult instanceof CardResult.Success); + CardNonce cardNonce = ((CardResult.Success) cardResult).getNonce(); + + assertNotNull(cardNonce.getBinData()); + assertEquals("Unknown", cardNonce.getCardType()); + assertEquals("", cardNonce.getLastFour()); + assertEquals("", cardNonce.getLastTwo()); + assertFalse(cardNonce.isDefault()); + assertNotNull(cardNonce.getString()); + + countDownLatch.countDown(); }); countDownLatch.await(); @@ -197,6 +195,8 @@ public void tokenize_callsErrorCallbackForInvalidCvv() throws Exception { final CountDownLatch countDownLatch = new CountDownLatch(1); CardClient sut = setupCardClient(authorization); sut.tokenize(card, (cardResult) -> { + assertTrue(cardResult instanceof CardResult.Failure); + Exception error = ((CardResult.Failure) cardResult).getError(); assertEquals("CVV verification failed", ((ErrorWithResponse) error).errorFor("creditCard").getFieldErrors().get(0).getMessage()); countDownLatch.countDown(); @@ -232,6 +232,8 @@ public void tokenize_callsErrorCallbackForInvalidPostalCode() throws Exception { final CountDownLatch countDownLatch = new CountDownLatch(1); CardClient sut = setupCardClient(authorization); sut.tokenize(card, (cardResult) -> { + assertTrue(cardResult instanceof CardResult.Failure); + Exception error = ((CardResult.Failure) cardResult).getError(); assertEquals("Postal code verification failed", ((ErrorWithResponse) error).errorFor("creditCard").errorFor("billingAddress") .getFieldErrors().get(0).getMessage()); @@ -255,6 +257,8 @@ public void tokenize_whenInvalidCountryCode_callsErrorCallbackWithDetailedError( final CountDownLatch countDownLatch = new CountDownLatch(1); CardClient sut = setupCardClient(authorization); sut.tokenize(card, (cardResult) -> { + assertTrue(cardResult instanceof CardResult.Failure); + Exception error = ((CardResult.Failure) cardResult).getError(); assertEquals("Country code (alpha3) is not an accepted country", ((ErrorWithResponse) error).errorFor("creditCard").errorFor("billingAddress") .getFieldErrors().get(0).getMessage()); @@ -294,6 +298,8 @@ private void assertTokenizationSuccessful(String authorization, Card card) throw final CountDownLatch countDownLatch = new CountDownLatch(1); sut.tokenize(card, (cardResult) -> { + assertTrue(cardResult instanceof CardResult.Success); + CardNonce cardNonce = ((CardResult.Success) cardResult).getNonce(); assertNotNull(cardNonce.getString()); assertEquals("Visa", cardNonce.getCardType()); assertEquals("1111", cardNonce.getLastFour()); From afe37b8593790095b9c45ee1213de97e9311fcb7 Mon Sep 17 00:00:00 2001 From: Sarah Koop Date: Tue, 5 Dec 2023 10:05:58 -0600 Subject: [PATCH 4/7] Fix lint --- Card/src/main/java/com/braintreepayments/api/CardResult.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/Card/src/main/java/com/braintreepayments/api/CardResult.kt b/Card/src/main/java/com/braintreepayments/api/CardResult.kt index 2b3390c7ff..001aefc17d 100644 --- a/Card/src/main/java/com/braintreepayments/api/CardResult.kt +++ b/Card/src/main/java/com/braintreepayments/api/CardResult.kt @@ -14,5 +14,4 @@ sealed class CardResult { * There was an [error] during card tokenization. */ class Failure(val error: Exception) : CardResult() - } From 200a179d21a302bfab9fde201e0e2bf391c841c4 Mon Sep 17 00:00:00 2001 From: Sarah Koop Date: Tue, 5 Dec 2023 10:15:50 -0600 Subject: [PATCH 5/7] Add CHANGELOG and migration guide --- CHANGELOG.md | 2 ++ .../braintreepayments/demo/CardFragment.java | 9 +++++---- v5_MIGRATION_GUIDE.md | 19 +++++++++++++++++++ 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e6fc68bca..8f80cda05d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -85,6 +85,8 @@ * Card * Remove `threeDSecureInfo` from `CardNonce` * Move `ThreeDSecureInfo` to `three-d-secure` module + * Add `CardResult` object + * Change `CardTokenizeCallback` parameters * SEPA Direct Debit * Remove `SEPADirectDebitLifecycleObserver` and `SEPADirectDebitListener` * Add `SEPADirectDebitLauncher`, `SEPADirectDebitLauncherCallback`, diff --git a/Demo/src/main/java/com/braintreepayments/demo/CardFragment.java b/Demo/src/main/java/com/braintreepayments/demo/CardFragment.java index c22ba2c872..7eb9d7fe25 100644 --- a/Demo/src/main/java/com/braintreepayments/demo/CardFragment.java +++ b/Demo/src/main/java/com/braintreepayments/demo/CardFragment.java @@ -20,6 +20,7 @@ import com.braintreepayments.api.Card; import com.braintreepayments.api.CardClient; import com.braintreepayments.api.CardNonce; +import com.braintreepayments.api.CardResult; import com.braintreepayments.api.DataCollector; import com.braintreepayments.api.PaymentMethodNonce; import com.braintreepayments.api.ThreeDSecureAdditionalInformation; @@ -183,10 +184,10 @@ public void onPurchase(View v) { card.setPostalCode(cardForm.getPostalCode()); cardClient.tokenize(card, (cardResult) -> { - if (cardNonce != null) { - handlePaymentMethodNonceCreated(cardNonce); - } else { - handleError(tokenizeError); + if (cardResult instanceof CardResult.Success) { + handlePaymentMethodNonceCreated(((CardResult.Success) cardResult).getNonce()); + } else if (cardResult instanceof CardResult.Failure) { + handleError(((CardResult.Failure) cardResult).getError()); } }); } diff --git a/v5_MIGRATION_GUIDE.md b/v5_MIGRATION_GUIDE.md index 607a113033..8efa3761c4 100644 --- a/v5_MIGRATION_GUIDE.md +++ b/v5_MIGRATION_GUIDE.md @@ -8,6 +8,7 @@ basics for updating your Braintree integration from v4 to v5. 1. [Android API](#android-api) 1. [Braintree Client](#braintree-client) 1. [Data Collector](#data-collector) +1. [Card](#card) 1. [Union Pay](#union-pay) 1. [Venmo](#venmo) 1. [Google Pay](#google-pay) @@ -48,6 +49,24 @@ dataCollector.collectDeviceData(context) { deviceData, error -> } ``` +## Card + +The card tokenization integration has been updated to simplify instantiation and result handling. + +```kotlin +- val braintreeClient = BraintreeClient(context, "TOKENIZATION_KEY_OR_CLIENT_TOKEN") +- val cardClient = CardClient(braintreeClient) ++ val cardClient = CardClient(context, "TOKENIZATION_KEY_OR_CLIENT_TOKEN") + +- cardClient.tokenize(card) { cardNonce, error -> ++ cardClient.tokenize(card) { cardResult -> ++ when (cardResult) { ++ is CardResult.Success -> { /* handle cardResult.nonce */ } ++ is CardResult.Failure -> { /* handle cardResult.error */ } ++ } +} +``` + ## Union Pay The `union-pay` module, and all containing classes, was removed in v5. UnionPay cards can now be From d60434297065b2150eb1108f93a863e51a031e4b Mon Sep 17 00:00:00 2001 From: Sarah Koop Date: Tue, 5 Dec 2023 10:28:12 -0600 Subject: [PATCH 6/7] Cleanup code snippet --- v5_MIGRATION_GUIDE.md | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/v5_MIGRATION_GUIDE.md b/v5_MIGRATION_GUIDE.md index 8efa3761c4..55f85d1c88 100644 --- a/v5_MIGRATION_GUIDE.md +++ b/v5_MIGRATION_GUIDE.md @@ -54,16 +54,13 @@ dataCollector.collectDeviceData(context) { deviceData, error -> The card tokenization integration has been updated to simplify instantiation and result handling. ```kotlin -- val braintreeClient = BraintreeClient(context, "TOKENIZATION_KEY_OR_CLIENT_TOKEN") -- val cardClient = CardClient(braintreeClient) -+ val cardClient = CardClient(context, "TOKENIZATION_KEY_OR_CLIENT_TOKEN") - -- cardClient.tokenize(card) { cardNonce, error -> -+ cardClient.tokenize(card) { cardResult -> -+ when (cardResult) { -+ is CardResult.Success -> { /* handle cardResult.nonce */ } -+ is CardResult.Failure -> { /* handle cardResult.error */ } -+ } +val cardClient = CardClient(context, "TOKENIZATION_KEY_OR_CLIENT_TOKEN") + +cardClient.tokenize(card) { cardResult -> + when (cardResult) { + is CardResult.Success -> { /* handle cardResult.nonce */ } + is CardResult.Failure -> { /* handle cardResult.error */ } + } } ``` From 191851b2b69e6d4e0ce739b1223d3f754cf94ae4 Mon Sep 17 00:00:00 2001 From: Sarah Koop Date: Tue, 5 Dec 2023 16:03:46 -0600 Subject: [PATCH 7/7] Fix integration tests --- .../java/com/braintreepayments/api/CardClientTest.java | 4 ++-- .../com/braintreepayments/api/LocalPaymentClientTest.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Card/src/androidTest/java/com/braintreepayments/api/CardClientTest.java b/Card/src/androidTest/java/com/braintreepayments/api/CardClientTest.java index 7d98c8a99a..5298587432 100644 --- a/Card/src/androidTest/java/com/braintreepayments/api/CardClientTest.java +++ b/Card/src/androidTest/java/com/braintreepayments/api/CardClientTest.java @@ -292,7 +292,7 @@ public void tokenize_tokenizesACardWithACompleteBillingAddress() throws Exceptio } private void assertTokenizationSuccessful(String authorization, Card card) throws Exception { - BraintreeClient braintreeClient = new BraintreeClient(new ClientParams(ApplicationProvider.getApplicationContext(), authorization)); + BraintreeClient braintreeClient = new BraintreeClient(ApplicationProvider.getApplicationContext(), authorization); CardClient sut = new CardClient(braintreeClient); final CountDownLatch countDownLatch = new CountDownLatch(1); @@ -323,7 +323,7 @@ private void assertTokenizationSuccessful(String authorization, Card card) throw } private CardClient setupCardClient(String authorization) { - BraintreeClient braintreeClient = new BraintreeClient(new ClientParams(ApplicationProvider.getApplicationContext(), authorization)); + BraintreeClient braintreeClient = new BraintreeClient(ApplicationProvider.getApplicationContext(), authorization); return new CardClient(braintreeClient); } diff --git a/LocalPayment/src/androidTest/java/com/braintreepayments/api/LocalPaymentClientTest.java b/LocalPayment/src/androidTest/java/com/braintreepayments/api/LocalPaymentClientTest.java index 5f6cf9e37e..9d871a912b 100644 --- a/LocalPayment/src/androidTest/java/com/braintreepayments/api/LocalPaymentClientTest.java +++ b/LocalPayment/src/androidTest/java/com/braintreepayments/api/LocalPaymentClientTest.java @@ -20,7 +20,7 @@ public class LocalPaymentClientTest { @Before public void setUp() { countDownLatch = new CountDownLatch(1); - braintreeClient = new BraintreeClient(new ClientParams(ApplicationProvider.getApplicationContext(), "sandbox_f252zhq7_hh4cpc39zq4rgjcg")); + braintreeClient = new BraintreeClient(ApplicationProvider.getApplicationContext(), "sandbox_f252zhq7_hh4cpc39zq4rgjcg"); } @Test(timeout = 10000)