Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update paypal request #1211

Merged
merged 12 commits into from
Nov 20, 2024
Merged
1 change: 1 addition & 0 deletions AmericanExpress/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ dependencies {
testImplementation libs.robolectric
testImplementation libs.mockito.core
testImplementation libs.json.assert
testImplementation libs.test.parameter.injector
testImplementation project(':TestUtils')
}

Expand Down
1 change: 1 addition & 0 deletions BraintreeCore/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ dependencies {
testImplementation libs.mockito.core
testImplementation libs.json.assert
testImplementation libs.mockk
testImplementation libs.test.parameter.injector
testImplementation libs.kotlin.test
testImplementation project(':PayPal')
testImplementation project(':TestUtils')
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Braintree Android SDK Release Notes

## unreleased

* PayPal
* Add `enablePayPalAppSwitch` property to `PayPalCheckoutRequest`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add an entry similar to what exists in 5.0.0? That way we can more easily indicate this is in beta for the checkout flow as well.


## 5.2.0 (2024-10-30)

* GooglePay
Expand Down
1 change: 1 addition & 0 deletions Card/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ dependencies {
testImplementation libs.androidx.core.ktx
testImplementation libs.kotlin.stdlib
testImplementation libs.kotlin.test
testImplementation libs.test.parameter.injector

androidTestImplementation project(':TestUtils')
androidTestImplementation libs.androidx.test.rules
Expand Down
1 change: 1 addition & 0 deletions DataCollector/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ dependencies {
testImplementation libs.json.assert
testImplementation libs.mockito.core
testImplementation libs.mockk
testImplementation libs.test.parameter.injector

testImplementation project(':TestUtils')

Expand Down
1 change: 1 addition & 0 deletions Demo/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ dependencies {
androidTestImplementation project(':TestUtils')

testImplementation libs.junit
testImplementation libs.test.parameter.injector
}

task demoApkSize {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ public static PayPalCheckoutRequest createPayPalCheckoutRequest(
request.setUserPhoneNumber(new PayPalPhoneNumber(buyerPhoneCountryCode, buyerPhoneNationalNumber));
}

if (Settings.isPayPalAppSwithEnabled(context)) {
request.setEnablePayPalAppSwitch(true);
}

request.setDisplayName(Settings.getPayPalDisplayName(context));

String landingPageType = Settings.getPayPalLandingPageType(context);
Expand Down
2 changes: 1 addition & 1 deletion Demo/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<string name="nonce_placeholder">Nonce: %s</string>
<string name="device_data_placeholder">Device Data: %s</string>
<string name="google_pay">Google Pay</string>
<string name="paypal_button">PayPal Web</string>
<string name="paypal_button">PayPal</string>
<string name="visa_checkout_button">Visa Checkout</string>
<string name="ideal_button">Pay with iDEAL</string>
<string name="local_payment_button">Local Payment</string>
Expand Down
1 change: 1 addition & 0 deletions GooglePay/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ dependencies {
testImplementation libs.kotlin.stdlib
testImplementation libs.coroutines.core
testImplementation libs.mockk
testImplementation libs.test.parameter.injector
testImplementation libs.androidx.test.core
}

Expand Down
1 change: 1 addition & 0 deletions LocalPayment/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ dependencies {
testImplementation libs.mockito.core
testImplementation libs.json.assert
testImplementation libs.mockk
testImplementation libs.test.parameter.injector
testImplementation project(':TestUtils')

androidTestImplementation project(':TestUtils')
Expand Down
1 change: 1 addition & 0 deletions PayPal/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ dependencies {
testImplementation libs.json.assert
testImplementation libs.mockito.core
testImplementation libs.mockk
testImplementation libs.test.parameter.injector
testImplementation project(':TestUtils')
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.braintreepayments.api.paypal

import android.os.Build
import android.text.TextUtils
import com.braintreepayments.api.core.Authorization
import com.braintreepayments.api.core.ClientToken
Expand Down Expand Up @@ -64,6 +65,7 @@ class PayPalCheckoutRequest @JvmOverloads constructor(
var currencyCode: String? = null,
var shouldRequestBillingAgreement: Boolean = false,
var shouldOfferPayLater: Boolean = false,
override var enablePayPalAppSwitch: Boolean = false,
override var localeCode: String? = null,
override var billingAgreementDescription: String? = null,
override var isShippingAddressRequired: Boolean = false,
Expand All @@ -87,6 +89,7 @@ class PayPalCheckoutRequest @JvmOverloads constructor(
displayName = displayName,
merchantAccountId = merchantAccountId,
riskCorrelationId = riskCorrelationId,
enablePayPalAppSwitch = enablePayPalAppSwitch,
userAuthenticationEmail = userAuthenticationEmail,
lineItems = lineItems
) {
Expand Down Expand Up @@ -126,6 +129,13 @@ class PayPalCheckoutRequest @JvmOverloads constructor(

userPhoneNumber?.let { parameters.put(PHONE_NUMBER_KEY, it.toJson()) }

if (enablePayPalAppSwitch && !appLink.isNullOrEmpty() && !userAuthenticationEmail.isNullOrEmpty()) {
parameters.put(ENABLE_APP_SWITCH_KEY, enablePayPalAppSwitch)
parameters.put(OS_VERSION_KEY, Build.VERSION.SDK_INT.toString())
parameters.put(OS_TYPE_KEY, "Android")
parameters.put(MERCHANT_APP_RETURN_URL_KEY, appLink)
}

if (currencyCode == null) {
currencyCode = configuration?.payPalCurrencyIsoCode
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,8 @@ internal class PayPalInternalClient(
CREATE_SINGLE_PAYMENT_ENDPOINT
}
val url = "/v1/$endpoint"
val appLinkReturn = if (isBillingAgreement) appLink else null

if (isBillingAgreement && (payPalRequest as PayPalVaultRequest).enablePayPalAppSwitch) {
if (payPalRequest.enablePayPalAppSwitch) {
payPalRequest.enablePayPalAppSwitch = isPayPalInstalled(context)
}

Expand All @@ -55,7 +54,7 @@ internal class PayPalInternalClient(
authorization = merchantRepository.authorization,
successUrl = successUrl,
cancelUrl = cancelUrl,
appLink = appLinkReturn
appLink = appLink
) ?: throw JSONException("Error creating requestBody")

sendPost(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ import org.json.JSONException
* tokenization.
* @property riskCorrelationId A risk correlation ID created with Set Transaction Context on your
* server.
* @property enablePayPalAppSwitch Used to determine if the customer will use the PayPal app switch
* @property userAuthenticationEmail User email to initiate a quicker authentication flow in cases
* where the user has a PayPal Account with the same email.
* @property userPhoneNumber User phone number used to initiate a quicker authentication flow in
Expand All @@ -85,6 +86,7 @@ abstract class PayPalRequest internal constructor(
open var displayName: String? = null,
open var merchantAccountId: String? = null,
open var riskCorrelationId: String? = null,
open var enablePayPalAppSwitch: Boolean = false,
open var userAuthenticationEmail: String? = null,
open var userPhoneNumber: PayPalPhoneNumber? = null,
open var lineItems: List<PayPalLineItem> = emptyList()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class PayPalVaultRequest
var shouldOfferCredit: Boolean = false,
var recurringBillingDetails: PayPalRecurringBillingDetails? = null,
var recurringBillingPlanType: PayPalRecurringBillingPlanType? = null,
var enablePayPalAppSwitch: Boolean = false,
override var enablePayPalAppSwitch: Boolean = false,
saperi22 marked this conversation as resolved.
Show resolved Hide resolved
override var localeCode: String? = null,
override var billingAgreementDescription: String? = null,
override var isShippingAddressRequired: Boolean = false,
Expand All @@ -61,6 +61,7 @@ class PayPalVaultRequest
displayName = displayName,
merchantAccountId = merchantAccountId,
riskCorrelationId = riskCorrelationId,
enablePayPalAppSwitch = enablePayPalAppSwitch,
userAuthenticationEmail = userAuthenticationEmail,
lineItems = lineItems
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
import com.braintreepayments.api.core.Authorization;
import com.braintreepayments.api.core.Configuration;
import com.braintreepayments.api.core.PostalAddress;
import com.google.testing.junit.testparameterinjector.TestParameter;

import org.json.JSONException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RobolectricTestParameterInjector;

import java.util.ArrayList;

Expand All @@ -20,7 +21,7 @@
import static org.junit.Assert.assertNotNull;
import static org.mockito.Mockito.mock;

@RunWith(RobolectricTestRunner.class)
@RunWith(RobolectricTestParameterInjector.class)
public class PayPalCheckoutRequestUnitTest {

@Test
Expand All @@ -37,11 +38,13 @@ public void newPayPalCheckoutRequest_setsDefaultValues() {
assertNull(request.getLandingPageType());
assertNull(request.getBillingAgreementDescription());
assertFalse(request.getShouldOfferPayLater());
assertFalse(request.getEnablePayPalAppSwitch());
assertNull(request.getUserAuthenticationEmail());
assertFalse(request.getHasUserLocationConsent());
}

@Test
public void setsValuesCorrectly() {
public void setsValuesCorrectly(@TestParameter boolean appSwitchEnabled) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not familiar with Robolectric's TestParameter. Will it run the test with a random value? Or run the test multiple times with different values?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'd usually have to provide which values to run.
In this case though, since the value is a boolean, it just runs for false and true.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW, to be precise, @TestParameter is from the TestParameterInjector library.
We can't have two @RunWith classes; with 4.14-beta-1 robolectric now supports integration with TestParameterInjector, which IMO, has a better and concise way of doing parameterized tests. Robolectric used to do it differently.

PostalAddress postalAddress = new PostalAddress();
PayPalCheckoutRequest request = new PayPalCheckoutRequest("1.00", true);
request.setCurrencyCode("USD");
Expand All @@ -56,6 +59,8 @@ public void setsValuesCorrectly() {
request.setUserAction(PayPalPaymentUserAction.USER_ACTION_COMMIT);
request.setDisplayName("Display Name");
request.setRiskCorrelationId("123-correlation");
request.setEnablePayPalAppSwitch(appSwitchEnabled);
request.setUserAuthenticationEmail("test-email");
request.setLandingPageType(PayPalLandingPageType.LANDING_PAGE_TYPE_LOGIN);

assertEquals("1.00", request.getAmount());
Expand All @@ -69,13 +74,15 @@ public void setsValuesCorrectly() {
assertEquals(PayPalPaymentUserAction.USER_ACTION_COMMIT, request.getUserAction());
assertEquals("Display Name", request.getDisplayName());
assertEquals("123-correlation", request.getRiskCorrelationId());
assertEquals(appSwitchEnabled, request.getEnablePayPalAppSwitch());
assertEquals("test-email", request.getUserAuthenticationEmail());
assertEquals(PayPalLandingPageType.LANDING_PAGE_TYPE_LOGIN, request.getLandingPageType());
assertTrue(request.getShouldOfferPayLater());
assertTrue(request.getHasUserLocationConsent());
}

@Test
public void parcelsCorrectly() {
public void parcelsCorrectly(@TestParameter boolean appSwitchEnabled) {
PayPalCheckoutRequest request = new PayPalCheckoutRequest("12.34", true);
request.setCurrencyCode("USD");
request.setLocaleCode("en-US");
Expand All @@ -93,6 +100,8 @@ public void parcelsCorrectly() {
request.setDisplayName("Display Name");
request.setRiskCorrelationId("123-correlation");
request.setMerchantAccountId("merchant_account_id");
request.setEnablePayPalAppSwitch(appSwitchEnabled);
request.setUserAuthenticationEmail("test-email");

ArrayList<PayPalLineItem> lineItems = new ArrayList<>();
lineItems.add(new PayPalLineItem(PayPalLineItemKind.DEBIT, "An Item", "1", "1"));
Expand All @@ -110,6 +119,8 @@ public void parcelsCorrectly() {
result.getBillingAgreementDescription());
assertTrue(result.isShippingAddressRequired());
assertTrue(result.isShippingAddressEditable());
assertEquals(appSwitchEnabled, result.getEnablePayPalAppSwitch());
assertEquals("test-email", result.getUserAuthenticationEmail());
assertEquals("Postal Address", result.getShippingAddressOverride().getRecipientName());
assertEquals(PayPalPaymentIntent.SALE, result.getIntent());
assertEquals(PayPalLandingPageType.LANDING_PAGE_TYPE_LOGIN, result.getLandingPageType());
Expand Down Expand Up @@ -171,4 +182,5 @@ public void createRequestBody_sets_userPhoneNumber_when_not_null() throws JSONEx

assertTrue(requestBody.contains("\"phone_number\":{\"country_code\":\"1\",\"national_number\":\"1231231234\"}"));
}

}
1 change: 1 addition & 0 deletions PayPalMessaging/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ dependencies {
testImplementation libs.androidx.junit
testImplementation libs.mockk
testImplementation libs.mockito.core
testImplementation libs.test.parameter.injector
testImplementation project(':TestUtils')
}

Expand Down
1 change: 1 addition & 0 deletions SEPADirectDebit/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ dependencies {
testImplementation libs.androidx.junit
testImplementation libs.mockito.core
testImplementation libs.mockk
testImplementation libs.test.parameter.injector
testImplementation project(':TestUtils')

androidTestImplementation project(':TestUtils')
Expand Down
1 change: 1 addition & 0 deletions SharedUtils/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ dependencies {
testImplementation libs.androidx.test.core
testImplementation libs.mockito.core
testImplementation libs.robolectric
testImplementation libs.test.parameter.injector

androidTestImplementation libs.androidx.test.runner
androidTestImplementation libs.androidx.junit
Expand Down
1 change: 1 addition & 0 deletions ShopperInsights/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ dependencies {
testImplementation libs.mockk
testImplementation libs.robolectric
testImplementation libs.androidx.junit
testImplementation libs.test.parameter.injector
testImplementation project(':TestUtils')
}

Expand Down
1 change: 1 addition & 0 deletions TestUtils/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ dependencies {
compileOnly libs.json.assert
compileOnly libs.mockk
compileOnly libs.mockito.core
compileOnly libs.test.parameter.injector

implementation project(':BraintreeCore')
implementation project(':ThreeDSecure')
Expand Down
1 change: 1 addition & 0 deletions ThreeDSecure/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ dependencies {
testImplementation libs.mockito.core
testImplementation libs.json.assert
testImplementation libs.androidx.test.core
testImplementation libs.test.parameter.injector
testImplementation project(':TestUtils')

androidTestImplementation libs.androidx.test.rules
Expand Down
1 change: 1 addition & 0 deletions Venmo/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ dependencies {
testImplementation libs.mockito.core
testImplementation libs.json.assert
testImplementation libs.mockk
testImplementation libs.test.parameter.injector
testImplementation project(':TestUtils')
}

Expand Down
1 change: 1 addition & 0 deletions VisaCheckout/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ dependencies {
testImplementation libs.mockk
testImplementation libs.mockito.core
testImplementation libs.json.assert
testImplementation libs.test.parameter.injector
}

/* maven deploy + signing */
Expand Down
4 changes: 3 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ cardinal = "2.2.7-5"
navigationSafeArgsGradlePlugin = "2.5.0"
playServices = "19.4.0"
junit = "4.13.2"
robolectric = "4.11.1"
testParameterInjector = "1.18"
robolectric = "4.14-beta-1"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

google/TestParameterInjector#5

The 4.14-beta-1 release of Robolectric includes the new RobolectricTestParameterInjector that integrates with TestParameterInjector using the newly exposed APIs in TestParameterInjector 1.18.

mockito = "5.7.0"
jsonAssert = "1.5.1"
mockk = "1.13.8"
Expand Down Expand Up @@ -73,6 +74,7 @@ robolectric = { group = "org.robolectric", name = "robolectric", version.ref = "
mockito-core = { group = "org.mockito", name = "mockito-core", version.ref = "mockito" }
json-assert = { group = "org.skyscreamer", name = "jsonassert", version.ref = "jsonAssert" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
test-parameter-injector = { group = "com.google.testparameterinjector", name = "test-parameter-injector", version.ref = "testParameterInjector" }
mockk = { group = "io.mockk", name = "mockk", version.ref = "mockk" }
detekt-rules-libraries = { module = "io.gitlab.arturbosch.detekt:detekt-rules-libraries", version.ref = "detekt" }
detekt-formatting = { module = "io.gitlab.arturbosch.detekt:detekt-formatting", version.ref = "detekt" }
Expand Down
Loading