Skip to content

Commit

Permalink
Merge branch 'v5' into google_pay_single_result
Browse files Browse the repository at this point in the history
  • Loading branch information
sarahkoop authored Dec 18, 2023
2 parents 7f8e8af + 5633f12 commit 397a941
Show file tree
Hide file tree
Showing 1,087 changed files with 2,963 additions and 2,294 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,13 @@ public void getRewardsBalance(@NonNull String nonce, @NonNull String currencyIso
try {
AmericanExpressRewardsBalance rewardsBalance =
AmericanExpressRewardsBalance.fromJson(responseBody);
callback.onResult(rewardsBalance, null);
callback.onAmericanExpressResult(new AmericanExpressResult.Success(rewardsBalance));
} catch (JSONException e) {
braintreeClient.sendAnalyticsEvent("amex.rewards-balance.parse.failed");
callback.onResult(null, e);
callback.onAmericanExpressResult(new AmericanExpressResult.Failure(e));
}
} else {
callback.onResult(null, httpError);
} else if (httpError != null) {
callback.onAmericanExpressResult(new AmericanExpressResult.Failure(httpError));
braintreeClient.sendAnalyticsEvent("amex.rewards-balance.error");
}
});
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.braintreepayments.api

/**
* Callback for receiving result of
* [AmericanExpressClient.getRewardsBalance].
*/
fun interface AmericanExpressGetRewardsBalanceCallback {
/**
* @param americanExpressResult the [AmericanExpressResult]
*/
fun onAmericanExpressResult(americanExpressResult: AmericanExpressResult)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.braintreepayments.api

/**
* Result of fetching American Express rewards balance
*/
sealed class AmericanExpressResult {

/**
* The [rewardsBalance] was successfully fetched
*/
class Success(val rewardsBalance: AmericanExpressRewardsBalance) : AmericanExpressResult()

/**
* There was an [error] fetching rewards balance
*/
class Failure(val error: Exception) : AmericanExpressResult()
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.mock;
Expand Down Expand Up @@ -48,11 +49,13 @@ public void getRewardsBalance_callsListenerWithRewardsBalanceOnSuccess() {
AmericanExpressClient sut = new AmericanExpressClient(braintreeClient);
sut.getRewardsBalance("fake-nonce", "USD", amexRewardsCallback);

ArgumentCaptor<AmericanExpressRewardsBalance> amexRewardsCaptor =
ArgumentCaptor.forClass(AmericanExpressRewardsBalance.class);
verify(amexRewardsCallback).onResult(amexRewardsCaptor.capture(), (Exception) isNull());
ArgumentCaptor<AmericanExpressResult> amexRewardsCaptor =
ArgumentCaptor.forClass(AmericanExpressResult.class);
verify(amexRewardsCallback).onAmericanExpressResult(amexRewardsCaptor.capture());

AmericanExpressRewardsBalance rewardsBalance = amexRewardsCaptor.getValue();
AmericanExpressResult result = amexRewardsCaptor.getValue();
assertTrue(result instanceof AmericanExpressResult.Success);
AmericanExpressRewardsBalance rewardsBalance = ((AmericanExpressResult.Success) result).getRewardsBalance();
assertNotNull(rewardsBalance);
assertEquals("0.0070", rewardsBalance.getConversionRate());
assertEquals("316795.03", rewardsBalance.getCurrencyAmount());
Expand All @@ -73,11 +76,13 @@ public void getRewardsBalance_callsListenerWithRewardsBalanceWithErrorCode_OnIne
AmericanExpressClient sut = new AmericanExpressClient(braintreeClient);
sut.getRewardsBalance("fake-nonce", "USD", amexRewardsCallback);

ArgumentCaptor<AmericanExpressRewardsBalance> amexRewardsCaptor =
ArgumentCaptor.forClass(AmericanExpressRewardsBalance.class);
verify(amexRewardsCallback).onResult(amexRewardsCaptor.capture(), isNull());
ArgumentCaptor<AmericanExpressResult> amexRewardsCaptor =
ArgumentCaptor.forClass(AmericanExpressResult.class);
verify(amexRewardsCallback).onAmericanExpressResult(amexRewardsCaptor.capture());

AmericanExpressRewardsBalance rewardsBalance = amexRewardsCaptor.getValue();
AmericanExpressResult result = amexRewardsCaptor.getValue();
assertTrue(result instanceof AmericanExpressResult.Success);
AmericanExpressRewardsBalance rewardsBalance = ((AmericanExpressResult.Success) result).getRewardsBalance();
assertNotNull(rewardsBalance);
assertNull(rewardsBalance.getConversionRate());
assertNull(rewardsBalance.getCurrencyAmount());
Expand All @@ -98,11 +103,14 @@ public void getRewardsBalance_callsListenerWithRewardsBalanceWithErrorCode_OnIns
AmericanExpressClient sut = new AmericanExpressClient(braintreeClient);
sut.getRewardsBalance("fake-nonce", "USD", amexRewardsCallback);

ArgumentCaptor<AmericanExpressRewardsBalance> amexRewardsCaptor =
ArgumentCaptor.forClass(AmericanExpressRewardsBalance.class);
verify(amexRewardsCallback).onResult(amexRewardsCaptor.capture(), (Exception) isNull());
ArgumentCaptor<AmericanExpressResult> amexRewardsCaptor =
ArgumentCaptor.forClass(AmericanExpressResult.class);
verify(amexRewardsCallback).onAmericanExpressResult(amexRewardsCaptor.capture());

AmericanExpressRewardsBalance rewardsBalance = amexRewardsCaptor.getValue();
AmericanExpressResult result = amexRewardsCaptor.getValue();
assertTrue(result instanceof AmericanExpressResult.Success);

AmericanExpressRewardsBalance rewardsBalance = ((AmericanExpressResult.Success) result).getRewardsBalance();
assertNotNull(rewardsBalance);
assertNull(rewardsBalance.getConversionRate());
assertNull(rewardsBalance.getCurrencyAmount());
Expand All @@ -114,6 +122,27 @@ public void getRewardsBalance_callsListenerWithRewardsBalanceWithErrorCode_OnIns
assertEquals("Insufficient points on card", rewardsBalance.getErrorMessage());
}

@Test
public void getRewardsBalance_callsBackFailure_OnHttpError() {
Exception expectedError = new Exception("error");
BraintreeClient braintreeClient = new MockBraintreeClientBuilder()
.sendGETErrorResponse(expectedError)
.build();

AmericanExpressClient sut = new AmericanExpressClient(braintreeClient);
sut.getRewardsBalance("fake-nonce", "USD", amexRewardsCallback);

ArgumentCaptor<AmericanExpressResult> amexRewardsCaptor =
ArgumentCaptor.forClass(AmericanExpressResult.class);
verify(amexRewardsCallback).onAmericanExpressResult(amexRewardsCaptor.capture());

AmericanExpressResult result = amexRewardsCaptor.getValue();
assertTrue(result instanceof AmericanExpressResult.Failure);
Exception actualError = ((AmericanExpressResult.Failure) result).getError();
assertEquals(expectedError, actualError);
}


@Test
public void getRewardsBalance_sendsAnalyticsEventOnSuccess() {
BraintreeClient braintreeClient = new MockBraintreeClientBuilder()
Expand Down
39 changes: 32 additions & 7 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
* BraintreeDataCollector
* Replace `DataCollector#collectDeviceData(context, merchantId, callback)` with
`DataCollector#collectDeviceData(context, riskCorrelationId, callback)`
* Add `DataCollectorResult` and update `DataCollectorCallback` parameters
* PayPalDataCollector
* Remove `paypal-data-collector` module (use `data-collector`)
* Venmo
Expand All @@ -38,20 +39,25 @@
* Add `VenmoClient#createPaymentAuthRequest`
* GooglePay
* Remove `GooglePayListener` and `GooglePayRequestPaymentCallback`
* Add `GooglePayLauncher`, `GooglePayPaymentAuthRequest`, `GooglePayResult`,
`GooglePayReadinessResult`, `GooglePayPaymentAuthRequestCallback`,
`GooglePayPaymentAuthResult`, `GooglePayTokenizeCallback` and `GooglePayLauncherCallback`
* Add `GooglePayLauncher`, `GooglePayPaymentAuthRequest`,
`GooglePayPaymentAuthRequestCallback`, `GooglePayPaymentAuthResult`,
`GooglePayTokenizeCallback`, `GooglePayTokenizationParameters` and `GooglePayLauncherCallback`
* Remove overload constructors, `setListener, and `onActivityResult` from `GooglePayClient`
* Change `GooglePayClient#requestPayment` parameters and rename to
`GooglePayClient#createPaymentAuthRequest`
* Change `GooglePayIsReadyToPayCallback` parameters
* Add `GooglePayClient#tokenize`
* Remove `merchantId` from `GooglePayRequest`
* Change `GooglePayGetTokenizationParametersCallback` parameters
* ThreeDSecure
* Remove `ThreeDSecureListener`
* Add `ThreeDSecureLauncher`, `ThreeDSecurePaymentAuthResult`, and `ThreeDSecureLancherCallback`
* Add `ThreeDSecureLauncher`, `ThreeDSecurePaymentAuthResult`,
`ThreeDSecureTokenizeCallback`, `ThreeDSecurePaymentAuthRequest`,
`ThreeDSecurePaymentAuthRequestCallback`, `ThreeDSecurePrepareLookupResult`,
`ThreeDSecurePrepareLookupCallback`, and `ThreeDSecureLancherCallback`
* Remove overload constructors, `setListener`, `continuePerformVerification`, `onBrowserSwitchResult` and `onActivityResult` from `ThreeDSecureClient`
* Change `ThreeDSecureClient#initializeChallengeWithLookupResponse` parameters
* Convert `ThreeDSecureResult` into sealed class
* Add `ThreeDSecureClient#tokenize`
* Rename `ThreeDSecureClient#performVerification` to
`ThreeDSecureClient#createPaymentAuthRequest` and change parameters
Expand All @@ -77,8 +83,8 @@
* LocalPayment
* Remove `LocalPaymentListener`
* Add `LocalPaymentLauncher`, `LocalPaymentLauncherCallback`, `LocalPaymentTokenizeCallback`,
and `LocalPaymentAuthRequest`
* Rename `LocalPaymentResult` to `LocalPaymentAuthResult`
`LocalPaymentAuthRequest`, `LocalPaymentAuthRequestCallback` and `LocalPaymentAuthResult`
* Change `LocalPaymentResult` type
* Remove overload constructors, `setListener`, `parseBrowserSwitchResult`,
`clearActiveBrowserSwitchResult`, `approveLocalPayment`, and `approvePayment` from
`LocalPaymentClient`
Expand All @@ -89,16 +95,35 @@
* 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`,
`SEPADirectDebitPaymentAuthRequestCallback`, `SEPADirectDebitPaymentAuthRequest`,
`SEPADirectDebitPaymentAuthResult`, and `SEPADirectDebitTokenizeCallback`
`SEPADirectDebitResult`, `SEPADirectDebitPaymentAuthRequestParams` and
`SEPADirectDebitTokenizeCallback`
* Remove Fragment or Activity requirement from `SEPADirectDebitClient` constructor
* Replace `SEPADirectDebitClient#onBrowserSwitchResult` with `SEPADirectDebitClient#tokenize` and
modify parameters
* Replace `SEPADirectDebitClient#tokenize` with`SEPADirectDebitClient#createPaymentAuthRequest`
and modify parameters
* Visa Checkout
* Change parameters of `VisaCheckoutCreateProfileBuilderCallback` and
`VisaCheckoutTokenizeCallback`
* Add `VisaCheckoutProfileBuilderResult` and `VisaCheckoutTokenizeResult`
* American Express
* Change parameters of `AmericanExpressGetRewardsBalanceCallback`
* Add `AmericanExpressResult`

## 4.40.1 (2023-12-13)

* BraintreeCore
* Bump `browser-switch` version to `2.6.1` (fixes #799)
* PayPal
* Fix issue where inaccurate error message was being returned on authorization or configuration error (fixes #821)
* Venmo
* Fix NPE when `VenmoListener` is null (fixes #832)

## 4.40.0 (2023-11-16)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 onResult(CardNonce cardNonce, Exception error) {
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();
Expand Down Expand Up @@ -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 onResult(CardNonce cardNonce, Exception error) {

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();
Expand All @@ -196,7 +194,9 @@ 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) -> {
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();
Expand Down Expand Up @@ -231,7 +231,9 @@ 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) -> {
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());
Expand All @@ -254,7 +256,9 @@ public void tokenize_whenInvalidCountryCode_callsErrorCallbackWithDetailedError(

final CountDownLatch countDownLatch = new CountDownLatch(1);
CardClient sut = setupCardClient(authorization);
sut.tokenize(card, (cardNonce, error) -> {
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());
Expand Down Expand Up @@ -288,12 +292,14 @@ 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);
sut.tokenize(card, (cardNonce, error) -> {
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());
Expand All @@ -317,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);
}

Expand Down
8 changes: 4 additions & 4 deletions Card/src/main/java/com/braintreepayments/api/CardAnalytics.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.braintreepayments.api

internal enum class CardAnalytics(@JvmField val event: String) {
internal object CardAnalytics {

CARD_TOKENIZE_STARTED("card:tokenize:started"),
CARD_TOKENIZE_FAILED("card:tokenize:failed"),
CARD_TOKENIZE_SUCCEEDED("card:tokenize:succeeded")
const val CARD_TOKENIZE_STARTED = "card:tokenize:started"
const val CARD_TOKENIZE_FAILED = "card:tokenize:failed"
const val CARD_TOKENIZE_SUCCEEDED = "card:tokenize:succeeded"
}
Loading

0 comments on commit 397a941

Please sign in to comment.