From 26d6a6593be373d81ac75867141f93ce498988b2 Mon Sep 17 00:00:00 2001 From: Rich Herrera Date: Mon, 2 Dec 2024 10:25:02 -0600 Subject: [PATCH 1/4] Add Contact Information request object (#1224) * Add contact information data class * Add ContactInformation request model * Add UTs * Update CHANGELOG --- CHANGELOG.md | 3 ++ .../api/paypal/PayPalCheckoutRequest.kt | 6 ++++ .../api/paypal/PayPalContactInformation.kt | 16 +++++++++ .../api/paypal/PayPalRequest.kt | 2 ++ .../paypal/PayPalCheckoutRequestUnitTest.java | 33 +++++++++++++++++++ 5 files changed, 60 insertions(+) create mode 100644 PayPal/src/main/java/com/braintreepayments/api/paypal/PayPalContactInformation.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 18b3f5d9b8..da5c5e6c59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ * LocalPayment * Make LocalPaymentAuthRequestParams public (fixes #1207) +* PayPal + * Add `PayPalContactInformation` request object + * Add `PayPalCheckoutRequest.contactInformation` optional property ## 5.2.0 (2024-10-30) diff --git a/PayPal/src/main/java/com/braintreepayments/api/paypal/PayPalCheckoutRequest.kt b/PayPal/src/main/java/com/braintreepayments/api/paypal/PayPalCheckoutRequest.kt index e95d708813..8410a0abd5 100644 --- a/PayPal/src/main/java/com/braintreepayments/api/paypal/PayPalCheckoutRequest.kt +++ b/PayPal/src/main/java/com/braintreepayments/api/paypal/PayPalCheckoutRequest.kt @@ -64,6 +64,7 @@ class PayPalCheckoutRequest @JvmOverloads constructor( var currencyCode: String? = null, var shouldRequestBillingAgreement: Boolean = false, var shouldOfferPayLater: Boolean = false, + var contactInformation: PayPalContactInformation? = null, override var localeCode: String? = null, override var billingAgreementDescription: String? = null, override var isShippingAddressRequired: Boolean = false, @@ -126,6 +127,11 @@ class PayPalCheckoutRequest @JvmOverloads constructor( userPhoneNumber?.let { parameters.put(PHONE_NUMBER_KEY, it.toJson()) } + contactInformation?.let { info -> + info.recipientEmail?.let { parameters.put(RECIPIENT_EMAIL_KEY, it) } + info.recipentPhoneNumber?.let { parameters.put(RECIPIENT_PHONE_NUMBER_KEY, it.toJson()) } + } + if (currencyCode == null) { currencyCode = configuration?.payPalCurrencyIsoCode } diff --git a/PayPal/src/main/java/com/braintreepayments/api/paypal/PayPalContactInformation.kt b/PayPal/src/main/java/com/braintreepayments/api/paypal/PayPalContactInformation.kt new file mode 100644 index 0000000000..a0357db5b6 --- /dev/null +++ b/PayPal/src/main/java/com/braintreepayments/api/paypal/PayPalContactInformation.kt @@ -0,0 +1,16 @@ +package com.braintreepayments.api.paypal + +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +/** + * Representation of a recipient Contact Information for the order. + * + * @property recipientEmail Email address of the recipient. + * @property recipentPhoneNumber Phone number of the recipient. + */ +@Parcelize +data class PayPalContactInformation( + val recipientEmail: String? = null, + val recipentPhoneNumber: PayPalPhoneNumber? = null +) : Parcelable diff --git a/PayPal/src/main/java/com/braintreepayments/api/paypal/PayPalRequest.kt b/PayPal/src/main/java/com/braintreepayments/api/paypal/PayPalRequest.kt index adfd68924c..3c2dced877 100644 --- a/PayPal/src/main/java/com/braintreepayments/api/paypal/PayPalRequest.kt +++ b/PayPal/src/main/java/com/braintreepayments/api/paypal/PayPalRequest.kt @@ -132,5 +132,7 @@ 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 RECIPIENT_EMAIL_KEY: String = "recipient_email" + internal const val RECIPIENT_PHONE_NUMBER_KEY: String = "international_phone" } } diff --git a/PayPal/src/test/java/com/braintreepayments/api/paypal/PayPalCheckoutRequestUnitTest.java b/PayPal/src/test/java/com/braintreepayments/api/paypal/PayPalCheckoutRequestUnitTest.java index 8752cde5f0..0ec5eac6a9 100644 --- a/PayPal/src/test/java/com/braintreepayments/api/paypal/PayPalCheckoutRequestUnitTest.java +++ b/PayPal/src/test/java/com/braintreepayments/api/paypal/PayPalCheckoutRequestUnitTest.java @@ -171,4 +171,37 @@ public void createRequestBody_sets_userPhoneNumber_when_not_null() throws JSONEx assertTrue(requestBody.contains("\"phone_number\":{\"country_code\":\"1\",\"national_number\":\"1231231234\"}")); } + + @Test + public void createRequestBody_sets_contactInformation_when_not_null() throws JSONException { + PayPalCheckoutRequest request = new PayPalCheckoutRequest("1.00", true); + + request.setContactInformation(new PayPalContactInformation("some@email.com", new PayPalPhoneNumber("1", "1234567890"))); + String requestBody = request.createRequestBody( + mock(Configuration.class), + mock(Authorization.class), + "success_url", + "cancel_url", + null + ); + + assertTrue(requestBody.contains("\"recipient_email\":\"some@email.com\"")); + assertTrue(requestBody.contains("\"international_phone\":{\"country_code\":\"1\",\"national_number\":\"1234567890\"}")); + } + + @Test + public void createRequestBody_does_not_set_contactInformation_when_contactInformation_is_null() throws JSONException { + PayPalCheckoutRequest request = new PayPalCheckoutRequest("1.00", true); + + String requestBody = request.createRequestBody( + mock(Configuration.class), + mock(Authorization.class), + "success_url", + "cancel_url", + null + ); + + assertFalse(requestBody.contains("\"recipient_email\":\"some@email.com\"")); + assertFalse(requestBody.contains("\"international_phone\":{\"country_code\":\"1\",\"national_number\":\"1234567890\"}")); + } } \ No newline at end of file From cdda93402aa8916590de6e6dd8ba31bc3a63be8c Mon Sep 17 00:00:00 2001 From: Rich Herrera Date: Mon, 2 Dec 2024 10:25:34 -0600 Subject: [PATCH 2/4] Add contact information toggle (#1225) * Add contact information data class * Add ContactInformation request model * Add UTs * Update CHANGELOG * Add contact information toggle --- .../demo/PayPalFragment.java | 21 ++++++++++++------- .../demo/PayPalRequestFactory.java | 8 ++++++- Demo/src/main/res/layout/fragment_paypal.xml | 6 ++++++ 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/Demo/src/main/java/com/braintreepayments/demo/PayPalFragment.java b/Demo/src/main/java/com/braintreepayments/demo/PayPalFragment.java index fa90df0b62..d417fa1378 100644 --- a/Demo/src/main/java/com/braintreepayments/demo/PayPalFragment.java +++ b/Demo/src/main/java/com/braintreepayments/demo/PayPalFragment.java @@ -9,6 +9,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.Button; +import android.widget.Switch; import android.widget.Toast; import androidx.annotation.NonNull; @@ -49,13 +50,15 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c TextInputEditText buyerPhoneNationalNumberEditText = view.findViewById(R.id.buyer_phone_national_number_edit_text); Button billingAgreementButton = view.findViewById(R.id.paypal_billing_agreement_button); Button singlePaymentButton = view.findViewById(R.id.paypal_single_payment_button); + Switch contactInformationSwitch = view.findViewById(R.id.contact_info_switch); singlePaymentButton.setOnClickListener(v -> { launchPayPal( false, buyerEmailEditText.getText().toString(), buyerPhoneCountryCodeEditText.getText().toString(), - buyerPhoneNationalNumberEditText.getText().toString() + buyerPhoneNationalNumberEditText.getText().toString(), + contactInformationSwitch.isChecked() ); }); billingAgreementButton.setOnClickListener(v -> { @@ -70,7 +73,8 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c true, buyerEmailEditText.getText().toString(), buyerPhoneCountryCodeEditText.getText().toString(), - buyerPhoneNationalNumberEditText.getText().toString() + buyerPhoneNationalNumberEditText.getText().toString(), + false ); }); @@ -115,7 +119,8 @@ private void launchPayPal( boolean isBillingAgreement, String buyerEmailAddress, String buyerPhoneCountryCode, - String buyerPhoneNationalNumber + String buyerPhoneNationalNumber, + Boolean isContactInformationEnabled ) { FragmentActivity activity = getActivity(); activity.setProgressBarIndeterminateVisibility(true); @@ -127,10 +132,10 @@ private void launchPayPal( if (dataCollectorResult instanceof DataCollectorResult.Success) { deviceData = ((DataCollectorResult.Success) dataCollectorResult).getDeviceData(); } - launchPayPal(activity, isBillingAgreement, amount, buyerEmailAddress, buyerPhoneCountryCode, buyerPhoneNationalNumber); + launchPayPal(activity, isBillingAgreement, amount, buyerEmailAddress, buyerPhoneCountryCode, buyerPhoneNationalNumber, isContactInformationEnabled); }); } else { - launchPayPal(activity, isBillingAgreement, amount, buyerEmailAddress, buyerPhoneCountryCode, buyerPhoneNationalNumber); + launchPayPal(activity, isBillingAgreement, amount, buyerEmailAddress, buyerPhoneCountryCode, buyerPhoneNationalNumber, isContactInformationEnabled); } } @@ -140,7 +145,8 @@ private void launchPayPal( String amount, String buyerEmailAddress, String buyerPhoneCountryCode, - String buyerPhoneNationalNumber + String buyerPhoneNationalNumber, + Boolean isContactInformationEnabled ) { PayPalRequest payPalRequest; if (isBillingAgreement) { @@ -156,7 +162,8 @@ private void launchPayPal( amount, buyerEmailAddress, buyerPhoneCountryCode, - buyerPhoneNationalNumber + buyerPhoneNationalNumber, + isContactInformationEnabled ); } payPalClient.createPaymentAuthRequest(requireContext(), payPalRequest, diff --git a/Demo/src/main/java/com/braintreepayments/demo/PayPalRequestFactory.java b/Demo/src/main/java/com/braintreepayments/demo/PayPalRequestFactory.java index efdc0d8bd5..8f342a776f 100644 --- a/Demo/src/main/java/com/braintreepayments/demo/PayPalRequestFactory.java +++ b/Demo/src/main/java/com/braintreepayments/demo/PayPalRequestFactory.java @@ -7,6 +7,7 @@ import com.braintreepayments.api.paypal.PayPalBillingInterval; import com.braintreepayments.api.paypal.PayPalBillingPricing; import com.braintreepayments.api.paypal.PayPalCheckoutRequest; +import com.braintreepayments.api.paypal.PayPalContactInformation; import com.braintreepayments.api.paypal.PayPalLandingPageType; import com.braintreepayments.api.paypal.PayPalPaymentIntent; import com.braintreepayments.api.paypal.PayPalPaymentUserAction; @@ -111,7 +112,8 @@ public static PayPalCheckoutRequest createPayPalCheckoutRequest( String amount, String buyerEmailAddress, String buyerPhoneCountryCode, - String buyerPhoneNationalNumber + String buyerPhoneNationalNumber, + Boolean isContactInformationEnabled ) { PayPalCheckoutRequest request = new PayPalCheckoutRequest(amount, true); @@ -158,6 +160,10 @@ public static PayPalCheckoutRequest createPayPalCheckoutRequest( request.setShippingAddressOverride(shippingAddress); } + if (isContactInformationEnabled) { + request.setContactInformation(new PayPalContactInformation("some@email.com", new PayPalPhoneNumber("1", "1234567890"))); + } + return request; } } diff --git a/Demo/src/main/res/layout/fragment_paypal.xml b/Demo/src/main/res/layout/fragment_paypal.xml index 7f6dd173e3..8ef1c17075 100644 --- a/Demo/src/main/res/layout/fragment_paypal.xml +++ b/Demo/src/main/res/layout/fragment_paypal.xml @@ -49,6 +49,12 @@ + +