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

Shopper insights rp1 feature include session #1235

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
* ShopperInsights (BETA)
* Add `isPayPalAppInstalled` and `isVenmoAppInstalled` methods
* Add `shopperSessionId` parameter to `ShopperInsightsClient`
* BraintreePayPal
* Add `shopperSessionId` to `PayPalCheckoutRequest` and `PayPalVaultRequest`

## 5.2.0 (2024-10-30)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,15 +148,17 @@ private void launchPayPal(
activity,
buyerEmailAddress,
buyerPhoneCountryCode,
buyerPhoneNationalNumber
buyerPhoneNationalNumber,
null
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: it looks like there are some extra spaces for the 2 null properties here

);
} else {
payPalRequest = createPayPalCheckoutRequest(
activity,
amount,
buyerEmailAddress,
buyerPhoneCountryCode,
buyerPhoneNationalNumber
buyerPhoneNationalNumber,
null
);
}
payPalClient.createPaymentAuthRequest(requireContext(), payPalRequest,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,27 @@ public static PayPalVaultRequest createPayPalVaultRequest(
Context context,
String buyerEmailAddress,
String buyerPhoneCountryCode,
String buyerPhoneNationalNumber
String buyerPhoneNationalNumber,
String shopperInsightsSessionId
) {

PayPalVaultRequest request = new PayPalVaultRequest(true);

if (!buyerEmailAddress.isEmpty()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need to change all these other params? It seems like it should be unaffected by this PR

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My understanding is that the original code is potentially a run time crash if the value is null. In the case of the demo app and how its setup, setting the toggles to null didn't have an impact on this flow because the values would always be true.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah ok in that case do we need to check that it's not null and it's not empty?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, great catch!

if (buyerEmailAddress != null && !buyerEmailAddress.isEmpty()) {
request.setUserAuthenticationEmail(buyerEmailAddress);
}

if (!buyerPhoneCountryCode.isEmpty() && !buyerPhoneNationalNumber.isEmpty()) {
request.setUserPhoneNumber(new PayPalPhoneNumber(buyerPhoneCountryCode, buyerPhoneNationalNumber));
if ((buyerPhoneCountryCode != null && !buyerPhoneCountryCode.isEmpty())
&& (buyerPhoneNationalNumber != null && !buyerPhoneNationalNumber.isEmpty())) {

request.setUserPhoneNumber(new PayPalPhoneNumber(
buyerPhoneCountryCode,
buyerPhoneNationalNumber)
);
}

if (shopperInsightsSessionId != null && !shopperInsightsSessionId.isEmpty()) {
request.setShopperSessionId(shopperInsightsSessionId);
}

if (Settings.isPayPalAppSwithEnabled(context)) {
Expand Down Expand Up @@ -111,16 +121,25 @@ public static PayPalCheckoutRequest createPayPalCheckoutRequest(
String amount,
String buyerEmailAddress,
String buyerPhoneCountryCode,
String buyerPhoneNationalNumber
String buyerPhoneNationalNumber,
String shopperInsightsSessionId
) {
PayPalCheckoutRequest request = new PayPalCheckoutRequest(amount, true);

if (!buyerEmailAddress.isEmpty()) {
if (buyerEmailAddress != null && !buyerEmailAddress.isEmpty()) {
request.setUserAuthenticationEmail(buyerEmailAddress);
}

if (!buyerPhoneCountryCode.isEmpty() && !buyerPhoneNationalNumber.isEmpty()) {
request.setUserPhoneNumber(new PayPalPhoneNumber(buyerPhoneCountryCode, buyerPhoneNationalNumber));
if ((buyerPhoneCountryCode != null && !buyerPhoneCountryCode.isEmpty())
&& (buyerPhoneNationalNumber != null && !buyerPhoneNationalNumber.isEmpty())) {
request.setUserPhoneNumber(new PayPalPhoneNumber(
buyerPhoneCountryCode,
buyerPhoneNationalNumber)
);
}

if (shopperInsightsSessionId != null && !shopperInsightsSessionId.isEmpty()) {
request.setShopperSessionId(shopperInsightsSessionId);
}

request.setDisplayName(Settings.getPayPalDisplayName(context));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,14 @@ class ShopperInsightsFragment : BaseFragment() {
private lateinit var venmoStartedPendingRequest: VenmoPendingRequest.Started
private lateinit var paypalStartedPendingRequest: PayPalPendingRequest.Started

private var shopperSessionId: String = "test-shopper-session-id"

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
shopperInsightsClient = ShopperInsightsClient(requireContext(), authStringArg, "test-shopper-session-id")
shopperInsightsClient = ShopperInsightsClient(requireContext(), authStringArg, shopperSessionId)

venmoClient = VenmoClient(requireContext(), super.getAuthStringArg(), null)
payPalClient = PayPalClient(
Expand Down Expand Up @@ -229,7 +231,9 @@ class ShopperInsightsFragment : BaseFragment() {
activity,
emailInput.editText?.text.toString(),
countryCodeInput.editText?.text.toString(),
nationalNumberInput.editText?.text.toString()
nationalNumberInput.editText?.text.toString(),
shopperSessionId

Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change

)
) { authRequest ->
when (authRequest) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.text.TextUtils
import com.braintreepayments.api.core.Authorization
import com.braintreepayments.api.core.ClientToken
import com.braintreepayments.api.core.Configuration
import com.braintreepayments.api.core.ExperimentalBetaApi
import com.braintreepayments.api.core.PostalAddress
import com.braintreepayments.api.core.PostalAddressParser
import kotlinx.parcelize.Parcelize
Expand Down Expand Up @@ -91,6 +92,7 @@ class PayPalCheckoutRequest @JvmOverloads constructor(
lineItems = lineItems
) {

@OptIn(ExperimentalBetaApi::class)
@Throws(JSONException::class)
@Suppress("LongMethod", "CyclomaticComplexMethod")
override fun createRequestBody(
Expand Down Expand Up @@ -126,6 +128,8 @@ class PayPalCheckoutRequest @JvmOverloads constructor(

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

parameters.putOpt(SHOPPER_SESSION_ID, shopperSessionId)

if (currencyCode == null) {
currencyCode = configuration?.payPalCurrencyIsoCode
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.os.Parcelable
import androidx.annotation.RestrictTo
import com.braintreepayments.api.core.Authorization
import com.braintreepayments.api.core.Configuration
import com.braintreepayments.api.core.ExperimentalBetaApi
import com.braintreepayments.api.core.PostalAddress
import org.json.JSONException

Expand Down Expand Up @@ -72,6 +73,8 @@ import org.json.JSONException
* where the user has a PayPal Account with the same email.
* @property userPhoneNumber User phone number used to initiate a quicker authentication flow in
* cases where the user has a PayPal Account with the phone number.
* @property shopperSessionId the shopper session ID returned from your shopper insights server SDK
* integration
* @property lineItems The line items for this transaction. It can include up to 249 line items.
*/
abstract class PayPalRequest internal constructor(
Expand All @@ -87,6 +90,9 @@ abstract class PayPalRequest internal constructor(
open var riskCorrelationId: String? = null,
open var userAuthenticationEmail: String? = null,
open var userPhoneNumber: PayPalPhoneNumber? = null,

@property:ExperimentalBetaApi
open var shopperSessionId: String? = null,
open var lineItems: List<PayPalLineItem> = emptyList()
) : Parcelable {

Expand Down Expand Up @@ -132,5 +138,6 @@ abstract class PayPalRequest internal constructor(
internal const val PLAN_TYPE_KEY: String = "plan_type"
internal const val PLAN_METADATA_KEY: String = "plan_metadata"
internal const val PHONE_NUMBER_KEY: String = "phone_number"
internal const val SHOPPER_SESSION_ID: String = "shopper_session_id"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import android.text.TextUtils
import com.braintreepayments.api.core.Authorization
import com.braintreepayments.api.core.ClientToken
import com.braintreepayments.api.core.Configuration
import com.braintreepayments.api.core.ExperimentalBetaApi
import com.braintreepayments.api.core.PostalAddress
import com.braintreepayments.api.core.PostalAddressParser
import kotlinx.parcelize.Parcelize
Expand Down Expand Up @@ -65,6 +66,7 @@ class PayPalVaultRequest
lineItems = lineItems
) {

@OptIn(ExperimentalBetaApi::class)
@Throws(JSONException::class)
@Suppress("LongMethod")
override fun createRequestBody(
Expand Down Expand Up @@ -92,6 +94,8 @@ class PayPalVaultRequest

parameters.putOpt(PAYER_EMAIL_KEY, userAuthenticationEmail)

parameters.putOpt(SHOPPER_SESSION_ID, shopperSessionId)

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

if (enablePayPalAppSwitch && !appLink.isNullOrEmpty() && !userAuthenticationEmail.isNullOrEmpty()) {
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.os.Parcel;

import com.braintreepayments.api.core.Authorization;
Expand Down Expand Up @@ -27,6 +28,7 @@ public class PayPalCheckoutRequestUnitTest {
public void newPayPalCheckoutRequest_setsDefaultValues() {
PayPalCheckoutRequest request = new PayPalCheckoutRequest("1.00", false);

assertNull(request.getShopperSessionId());
assertNotNull(request.getAmount());
assertNull(request.getCurrencyCode());
assertNull(request.getLocaleCode());
Expand All @@ -44,6 +46,7 @@ public void newPayPalCheckoutRequest_setsDefaultValues() {
public void setsValuesCorrectly() {
PostalAddress postalAddress = new PostalAddress();
PayPalCheckoutRequest request = new PayPalCheckoutRequest("1.00", true);
request.setShopperSessionId("shopper-insights-id");
request.setCurrencyCode("USD");
request.setShouldOfferPayLater(true);
request.setIntent(PayPalPaymentIntent.SALE);
Expand All @@ -58,6 +61,7 @@ public void setsValuesCorrectly() {
request.setRiskCorrelationId("123-correlation");
request.setLandingPageType(PayPalLandingPageType.LANDING_PAGE_TYPE_LOGIN);

assertEquals("shopper-insights-id", request.getShopperSessionId());
assertEquals("1.00", request.getAmount());
assertEquals("USD", request.getCurrencyCode());
assertEquals("US", request.getLocaleCode());
Expand Down Expand Up @@ -156,6 +160,21 @@ public void createRequestBody_does_not_set_userAuthenticationEmail_when_email_is
assertFalse(requestBody.contains("\"payer_email\":" + "\"" + payerEmail + "\""));
}

@Test
public void createRequestBody_sets_shopper_insights_session_id() throws JSONException {
PayPalCheckoutRequest request = new PayPalCheckoutRequest("1.00", true);
request.setShopperSessionId("shopper-insights-id");
String requestBody = request.createRequestBody(
mock(Configuration.class),
mock(Authorization.class),
"success_url",
"cancel_url",
"universal_url"
);

assertTrue(requestBody.contains("\"shopper_session_id\":" + "\"shopper-insights-id\""));
}

@Test
public void createRequestBody_sets_userPhoneNumber_when_not_null() throws JSONException {
PayPalCheckoutRequest request = new PayPalCheckoutRequest("1.00", true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import com.braintreepayments.api.testutils.Fixtures;

import org.json.JSONException;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
Expand All @@ -32,6 +33,7 @@ public class PayPalVaultRequestUnitTest {
public void newPayPalVaultRequest_setsDefaultValues() {
PayPalVaultRequest request = new PayPalVaultRequest(false);

assertNull(request.getShopperSessionId());
assertNull(request.getLocaleCode());
assertFalse(request.isShippingAddressRequired());
assertNull(request.getShippingAddressOverride());
Expand All @@ -46,6 +48,7 @@ public void newPayPalVaultRequest_setsDefaultValues() {
public void setsValuesCorrectly() {
PostalAddress postalAddress = new PostalAddress();
PayPalVaultRequest request = new PayPalVaultRequest(true);
request.setShopperSessionId("shopper-insights-id");
request.setLocaleCode("US");
request.setBillingAgreementDescription("Billing Agreement Description");
request.setShippingAddressRequired(true);
Expand Down Expand Up @@ -75,6 +78,7 @@ public void setsValuesCorrectly() {
request.setRecurringBillingDetails(billingDetails);
request.setRecurringBillingPlanType(PayPalRecurringBillingPlanType.RECURRING);

assertEquals("shopper-insights-id", request.getShopperSessionId());
assertEquals("US", request.getLocaleCode());
assertEquals("Billing Agreement Description", request.getBillingAgreementDescription());
assertTrue(request.isShippingAddressRequired());
Expand Down Expand Up @@ -212,11 +216,11 @@ public void createRequestBody_sets_userAuthenticationEmail_when_not_null() throw
assertTrue(requestBody.contains("\"payer_email\":" + "\"" + payerEmail + "\""));
}

@Test
public void createRequestBody_sets_enablePayPalSwitch_and_userAuthenticationEmail_not_null() throws JSONException {
String versionSDK = String.valueOf(Build.VERSION.SDK_INT);
String payerEmail = "payer_email@example.com";
PayPalVaultRequest request = new PayPalVaultRequest(true);

request.setEnablePayPalAppSwitch(true);
request.setUserAuthenticationEmail(payerEmail);
String requestBody = request.createRequestBody(
Expand All @@ -233,6 +237,21 @@ public void createRequestBody_sets_enablePayPalSwitch_and_userAuthenticationEmai
assertTrue(requestBody.contains("\"merchant_app_return_url\":" + "\"universal_url\""));
}

@Test
public void createRequestBody_sets_shopper_insights_session_id() throws JSONException {
PayPalVaultRequest request = new PayPalVaultRequest(true);
request.setShopperSessionId("shopper-insights-id");
String requestBody = request.createRequestBody(
mock(Configuration.class),
mock(Authorization.class),
"success_url",
"cancel_url",
"universal_url"
);

assertTrue(requestBody.contains("\"shopper_session_id\":" + "\"shopper-insights-id\""));
}

@Test
public void createRequestBody_correctlyFormatsJSON() throws JSONException {
PayPalVaultRequest request = new PayPalVaultRequest(true);
Expand Down
Loading