diff --git a/CHANGELOG.md b/CHANGELOG.md index 2dd56e16c3..f41fd6d435 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * PayPal * Fix bug to ensure that `PayPalVaultRequest.userAuthenticationEmail` is not sent as an empty string + * Add `shippingCallbackUrl` to `PayPalCheckoutRequest` * ThreeDSecure * Return error if no `dfReferenceId` is returned in the 3D Secure flow 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..c6b4888832 100644 --- a/PayPal/src/main/java/com/braintreepayments/api/paypal/PayPalCheckoutRequest.kt +++ b/PayPal/src/main/java/com/braintreepayments/api/paypal/PayPalCheckoutRequest.kt @@ -1,5 +1,6 @@ package com.braintreepayments.api.paypal +import android.net.Uri import android.text.TextUtils import com.braintreepayments.api.core.Authorization import com.braintreepayments.api.core.ClientToken @@ -54,6 +55,9 @@ import org.json.JSONObject * * @property shouldOfferPayLater Offers PayPal Pay Later if the customer qualifies. Defaults to * false. + * @property shippingCallbackUrl Server side shipping callback URL to be notified when a customer + * updates their shipping address or options. A callback request will be sent to the merchant server + * at this URL. */ @Parcelize class PayPalCheckoutRequest @JvmOverloads constructor( @@ -64,6 +68,7 @@ class PayPalCheckoutRequest @JvmOverloads constructor( var currencyCode: String? = null, var shouldRequestBillingAgreement: Boolean = false, var shouldOfferPayLater: Boolean = false, + var shippingCallbackUrl: Uri? = null, override var localeCode: String? = null, override var billingAgreementDescription: String? = null, override var isShippingAddressRequired: Boolean = false, @@ -75,7 +80,7 @@ class PayPalCheckoutRequest @JvmOverloads constructor( override var riskCorrelationId: String? = null, override var userAuthenticationEmail: String? = null, override var userPhoneNumber: PayPalPhoneNumber? = null, - override var lineItems: List = emptyList(), + override var lineItems: List = emptyList() ) : PayPalRequest( hasUserLocationConsent = hasUserLocationConsent, localeCode = localeCode, @@ -105,6 +110,10 @@ class PayPalCheckoutRequest @JvmOverloads constructor( .put(CANCEL_URL_KEY, cancelUrl) .put(OFFER_PAY_LATER_KEY, shouldOfferPayLater) + shippingCallbackUrl?.let { + if (it.toString().isNotEmpty()) parameters.put(SHIPPING_CALLBACK_URL_KEY, it) + } + if (authorization is ClientToken) { parameters.put(AUTHORIZATION_FINGERPRINT_KEY, authorization.bearer) } else { 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..eb44dd5faa 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,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 SHIPPING_CALLBACK_URL_KEY: String = "shipping_callback_url" } } diff --git a/PayPal/src/main/java/com/braintreepayments/api/paypal/PayPalVaultRequest.kt b/PayPal/src/main/java/com/braintreepayments/api/paypal/PayPalVaultRequest.kt index 973e605589..ad9cb240a2 100644 --- a/PayPal/src/main/java/com/braintreepayments/api/paypal/PayPalVaultRequest.kt +++ b/PayPal/src/main/java/com/braintreepayments/api/paypal/PayPalVaultRequest.kt @@ -49,7 +49,7 @@ class PayPalVaultRequest override var riskCorrelationId: String? = null, override var userAuthenticationEmail: String? = null, override var userPhoneNumber: PayPalPhoneNumber? = null, - override var lineItems: List = emptyList(), + override var lineItems: List = emptyList() ) : PayPalRequest( hasUserLocationConsent = hasUserLocationConsent, localeCode = localeCode, @@ -62,7 +62,7 @@ class PayPalVaultRequest merchantAccountId = merchantAccountId, riskCorrelationId = riskCorrelationId, userAuthenticationEmail = userAuthenticationEmail, - lineItems = lineItems + lineItems = lineItems, ) { @Throws(JSONException::class) 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..64ca36ba96 100644 --- a/PayPal/src/test/java/com/braintreepayments/api/paypal/PayPalCheckoutRequestUnitTest.java +++ b/PayPal/src/test/java/com/braintreepayments/api/paypal/PayPalCheckoutRequestUnitTest.java @@ -1,5 +1,6 @@ package com.braintreepayments.api.paypal; +import android.net.Uri; import android.os.Parcel; import com.braintreepayments.api.core.Authorization; @@ -7,6 +8,7 @@ import com.braintreepayments.api.core.PostalAddress; import org.json.JSONException; +import org.json.JSONObject; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; @@ -157,6 +159,58 @@ public void createRequestBody_does_not_set_userAuthenticationEmail_when_email_is } @Test + public void createRequestBody_sets_shippingCallbackUri_when_not_null() throws JSONException { + String urlString = "https://www.example.com/path"; + Uri uri = Uri.parse(urlString); + + PayPalCheckoutRequest request = new PayPalCheckoutRequest("1.00", true); + request.setShippingCallbackUrl(uri); + + String requestBody = request.createRequestBody( + mock(Configuration.class), + mock(Authorization.class), + "success_url", + "cancel_url", + null + ); + + JSONObject jsonObject = new JSONObject(requestBody); + assertEquals(urlString, jsonObject.getString("shipping_callback_url")); + } + + @Test + public void createRequestBody_does_not_set_shippingCallbackUri_when_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 + ); + + JSONObject jsonObject = new JSONObject(requestBody); + assertFalse(jsonObject.has("shipping_callback_url")); + } + + @Test + public void createRequestBody_does_not_set_shippingCallbackUri_when_empty() throws JSONException { + PayPalCheckoutRequest request = new PayPalCheckoutRequest("1.00", true); + request.setShippingCallbackUrl(Uri.parse("")); + + String requestBody = request.createRequestBody( + mock(Configuration.class), + mock(Authorization.class), + "success_url", + "cancel_url", + null + ); + + JSONObject jsonObject = new JSONObject(requestBody); + assertFalse(jsonObject.has("shipping_callback_url")); + } + public void createRequestBody_sets_userPhoneNumber_when_not_null() throws JSONException { PayPalCheckoutRequest request = new PayPalCheckoutRequest("1.00", true); @@ -171,4 +225,5 @@ public void createRequestBody_sets_userPhoneNumber_when_not_null() throws JSONEx assertTrue(requestBody.contains("\"phone_number\":{\"country_code\":\"1\",\"national_number\":\"1231231234\"}")); } -} \ No newline at end of file +} +