-
Notifications
You must be signed in to change notification settings - Fork 238
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Payment Insights Client public API shell (#844)
* Added Shopper Insights client, request, result, stubs and docs * Added Shopper Insights client unit test Added Shopper Insights client unit test * Added insight callback updated unit test * adding unit test documentation * remove coroutines * add new line * remove open * fix detekt * Update BraintreeCore/src/main/java/com/braintreepayments/api/BraintreeShopperInsightsClient.kt Co-authored-by: Sarah Koop <[email protected]> * rename ShopperInsightsClient * lighten ShopperInsight docs * change ShopperInsightRequest from val to var * remove special char e.g. * rename response to info * Add Email and Phone request sub classes with unit tests * rename methods * updated unit tests * Added Email and Phone data class * Add docs and make interface a functional interface * simplify syntax * updating dependency * Rename parameters * fix lint issues * Addressing PR comment: making email a simple string * fix tests * Refactoring tests * linter fixes * refactoring * Renaming class * formatting * compact code * add docs * add kdoc * more kdocs * use constants for key strings * fix suppress params * Update BraintreeCore/src/test/java/com/braintreepayments/api/ShopperInsightsClientUnitTest.kt Co-authored-by: sshropshire <[email protected]> * Rename classes * Address PR comments. Move the object to json conversion to API class * move class to its own file * Change the ShopperInsightsRequest class signature * Moving the validation logic * adding kdoc --------- Co-authored-by: Sarah Koop <[email protected]> Co-authored-by: saperi <[email protected]> Co-authored-by: saperi22 <[email protected]> Co-authored-by: sshropshire <[email protected]>
- Loading branch information
1 parent
ed09dab
commit 5cc27c1
Showing
10 changed files
with
295 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
14 changes: 14 additions & 0 deletions
14
BraintreeCore/src/main/java/com/braintreepayments/api/BuyerPhone.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package com.braintreepayments.api | ||
|
||
/** | ||
* Representation of a user phone number. | ||
* @property countryCode The international country code for the shopper's phone number | ||
* (e.g., "1" for the United States). | ||
* @property nationalNumber The national segment of the shopper's phone number | ||
* (excluding the country code). | ||
*/ | ||
|
||
data class BuyerPhone( | ||
var countryCode: String, | ||
var nationalNumber: String | ||
) |
30 changes: 30 additions & 0 deletions
30
BraintreeCore/src/main/java/com/braintreepayments/api/PaymentReadyApi.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package com.braintreepayments.api | ||
|
||
import org.json.JSONObject | ||
|
||
// TODO: Implementation, documentation and interface. | ||
internal class PaymentReadyApi { | ||
fun processRequest(request: ShopperInsightsRequest): String = request.toJson() | ||
|
||
private fun ShopperInsightsRequest.toJson(): String { | ||
return JSONObject().apply { | ||
put(KEY_CUSTOMER, JSONObject().apply { | ||
putOpt(KEY_EMAIL, email) | ||
phone?.let { | ||
put(KEY_PHONE, JSONObject().apply { | ||
put(KEY_COUNTRY_CODE, it.countryCode) | ||
put(KEY_NATIONAL_NUMBER, it.nationalNumber) | ||
}) | ||
} | ||
}) | ||
}.toString() | ||
} | ||
|
||
companion object { | ||
internal const val KEY_COUNTRY_CODE = "countryCode" | ||
internal const val KEY_NATIONAL_NUMBER = "nationalNumber" | ||
internal const val KEY_CUSTOMER = "customer" | ||
internal const val KEY_EMAIL = "email" | ||
internal const val KEY_PHONE = "phone" | ||
} | ||
} |
8 changes: 8 additions & 0 deletions
8
BraintreeCore/src/main/java/com/braintreepayments/api/ShopperInsightsCallback.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package com.braintreepayments.api | ||
|
||
/** | ||
* A callback that returns information on whether someone is a PayPal or a Venmo shopper. | ||
*/ | ||
fun interface ShopperInsightsCallback { | ||
fun onResult(result: ShopperInsightsResult) | ||
} |
50 changes: 50 additions & 0 deletions
50
BraintreeCore/src/main/java/com/braintreepayments/api/ShopperInsightsClient.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package com.braintreepayments.api | ||
|
||
import androidx.annotation.VisibleForTesting | ||
|
||
/** | ||
* Use [ShopperInsightsClient] to optimize your checkout experience | ||
* by prioritizing the customer’s preferred payment methods in your UI. | ||
* By customizing each customer’s checkout experience, | ||
* you can improve conversion, increase sales/repeat buys and boost user retention/loyalty. | ||
* | ||
* Note: **This feature is in beta. It's public API may change in future releases.** | ||
*/ | ||
class ShopperInsightsClient @VisibleForTesting internal constructor( | ||
private val paymentReadyAPI: PaymentReadyApi | ||
) { | ||
/** | ||
* Retrieves recommended payment methods based on the provided shopper insights request. | ||
* | ||
* @param request The [ShopperInsightsRequest] containing information about the shopper. | ||
* @return A [ShopperInsightsResult] object indicating the recommended payment methods. | ||
*/ | ||
fun getRecommendedPaymentMethods( | ||
request: ShopperInsightsRequest, | ||
callback: ShopperInsightsCallback | ||
) { | ||
if (request.email == null && request.phone == null) { | ||
callback.onResult( | ||
ShopperInsightsResult.Failure( | ||
IllegalArgumentException( | ||
"One of ShopperInsightsRequest.email or " + | ||
"ShopperInsightsRequest.phone must be non-null." | ||
) | ||
) | ||
) | ||
return | ||
} | ||
|
||
// TODO: - Add isAppInstalled checks for PP & Venmo. DTBTSDK-3176 | ||
paymentReadyAPI.processRequest(request) | ||
// Hardcoded result | ||
callback.onResult( | ||
ShopperInsightsResult.Success( | ||
ShopperInsightsInfo( | ||
isPayPalRecommended = false, | ||
isVenmoRecommended = false | ||
) | ||
) | ||
) | ||
} | ||
} |
20 changes: 20 additions & 0 deletions
20
BraintreeCore/src/main/java/com/braintreepayments/api/ShopperInsightsInfo.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package com.braintreepayments.api | ||
|
||
/** | ||
* Data class encapsulating the result of a shopper insight api request. | ||
* | ||
* This class holds information about the recommended payment methods for a shopper | ||
* The recommendations include flags for whether payment methods like PayPal or Venmo | ||
* should be displayed with high priority in the user interface. | ||
* | ||
* @property isPayPalRecommended If true, indicates that the PayPal payment option | ||
* should be given high priority in the checkout UI. | ||
* @property isVenmoRecommended If true, indicates that the Venmo payment option | ||
* should be given high priority in the checkout UI. | ||
* | ||
* Note: **This feature is in beta. It's public API may change in future releases.** | ||
*/ | ||
data class ShopperInsightsInfo( | ||
val isPayPalRecommended: Boolean, | ||
val isVenmoRecommended: Boolean | ||
) |
16 changes: 16 additions & 0 deletions
16
BraintreeCore/src/main/java/com/braintreepayments/api/ShopperInsightsRequest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package com.braintreepayments.api | ||
|
||
/** | ||
* Data class representing a request for shopper insights. | ||
* | ||
* @property email The shopper's email address | ||
* @property phone The shopper's phone number | ||
* | ||
* One of [email] or [phone] must be provided to get shopper insights. | ||
* | ||
* Note: **This feature is in beta. It's public API may change in future releases.** | ||
*/ | ||
data class ShopperInsightsRequest( | ||
var email: String?, | ||
var phone: BuyerPhone? | ||
) |
17 changes: 17 additions & 0 deletions
17
BraintreeCore/src/main/java/com/braintreepayments/api/ShopperInsightsResult.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package com.braintreepayments.api | ||
|
||
/** | ||
* The result object returned when insights about a shopper is requested. | ||
*/ | ||
sealed class ShopperInsightsResult { | ||
|
||
/** | ||
* @property response The response object describing the shopper's insights. | ||
*/ | ||
class Success(val response: ShopperInsightsInfo) : ShopperInsightsResult() | ||
|
||
/** | ||
* @property error An object that describes the error that occurred. | ||
*/ | ||
class Failure(val error: Exception) : ShopperInsightsResult() | ||
} |
82 changes: 82 additions & 0 deletions
82
BraintreeCore/src/test/java/com/braintreepayments/api/PaymentReadyApiTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
package com.braintreepayments.api | ||
|
||
import org.junit.Test | ||
import org.skyscreamer.jsonassert.JSONAssert | ||
|
||
class PaymentReadyApiTest { | ||
|
||
private val paymentReadyApi = PaymentReadyApi() | ||
|
||
@Test | ||
fun `test phone to json string conversion`() { | ||
val testCountryCode = "1" | ||
val testNationalNumber = "123456789" | ||
val request = ShopperInsightsRequest( | ||
null, | ||
BuyerPhone( | ||
countryCode = testCountryCode, | ||
nationalNumber = testNationalNumber | ||
) | ||
) | ||
|
||
val observedJsonString = paymentReadyApi.processRequest(request) | ||
val expectedJsonString = """ | ||
{ | ||
"customer": { | ||
"phone": { | ||
"countryCode": "$testCountryCode", | ||
"nationalNumber": "$testNationalNumber" | ||
} | ||
} | ||
} | ||
""".trimIndent() | ||
|
||
JSONAssert.assertEquals(expectedJsonString, observedJsonString, true) | ||
} | ||
|
||
@Test | ||
fun `test email to json string conversion`() { | ||
val email = "[email protected]" | ||
val request = ShopperInsightsRequest(email, null) | ||
|
||
val observedJsonString = paymentReadyApi.processRequest(request) | ||
val expectedJsonString = """ | ||
{ | ||
"customer": { | ||
"email": "$email" | ||
} | ||
} | ||
""".trimIndent() | ||
|
||
JSONAssert.assertEquals(expectedJsonString, observedJsonString, true) | ||
} | ||
|
||
@Test | ||
fun `test email and phone to json string conversion`() { | ||
val email = "[email protected]" | ||
val testCountryCode = "1" | ||
val testNationalNumber = "123456789" | ||
val request = ShopperInsightsRequest( | ||
email, | ||
BuyerPhone( | ||
countryCode = testCountryCode, | ||
nationalNumber = testNationalNumber | ||
) | ||
) | ||
|
||
val observedJsonString = paymentReadyApi.processRequest(request) | ||
val expectedJsonString = """ | ||
{ | ||
"customer": { | ||
"phone": { | ||
"countryCode": "$testCountryCode", | ||
"nationalNumber": "$testNationalNumber" | ||
}, | ||
"email": "$email" | ||
} | ||
} | ||
""".trimIndent() | ||
|
||
JSONAssert.assertEquals(expectedJsonString, observedJsonString, true) | ||
} | ||
} |
57 changes: 57 additions & 0 deletions
57
BraintreeCore/src/test/java/com/braintreepayments/api/ShopperInsightsClientUnitTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package com.braintreepayments.api | ||
|
||
import io.mockk.mockk | ||
import kotlin.test.assertEquals | ||
import kotlin.test.assertIs | ||
import org.junit.Assert.assertNotNull | ||
import org.junit.Before | ||
import org.junit.Test | ||
|
||
/** | ||
* Unit tests for BraintreeShopperInsightsClient. | ||
* | ||
* This class contains tests for the shopper insights functionality within the Braintree SDK. | ||
* It focuses on testing how the client handles different scenarios when fetching recommended | ||
* payment methods. | ||
*/ | ||
class ShopperInsightsClientUnitTest { | ||
|
||
private lateinit var sut: ShopperInsightsClient | ||
private lateinit var paymentApi: PaymentReadyApi | ||
|
||
@Before | ||
fun beforeEach() { | ||
paymentApi = mockk(relaxed = true) | ||
sut = ShopperInsightsClient(paymentApi) | ||
} | ||
|
||
/** | ||
* Tests if the getRecommendedPaymentMethods method returns paypal and venmo recommendations | ||
* when providing a shopping insight request. | ||
*/ | ||
@Test | ||
fun testGetRecommendedPaymentMethods_returnsDefaultRecommendations() { | ||
val request = ShopperInsightsRequest("fake-email", null) | ||
sut.getRecommendedPaymentMethods(request) { result -> | ||
assertNotNull(result) | ||
val successResult = assertIs<ShopperInsightsResult.Success>(result) | ||
assertNotNull(successResult.response.isPayPalRecommended) | ||
assertNotNull(successResult.response.isVenmoRecommended) | ||
} | ||
} | ||
|
||
@Test | ||
fun `testGetRecommendedPaymentMethods - request object has null properties`() { | ||
val request = ShopperInsightsRequest(null, null) | ||
sut.getRecommendedPaymentMethods(request) { result -> | ||
assertNotNull(result) | ||
val error = assertIs<ShopperInsightsResult.Failure>(result) | ||
val iae = assertIs<IllegalArgumentException>(error.error) | ||
assertEquals( | ||
"One of ShopperInsightsRequest.email or " + | ||
"ShopperInsightsRequest.phone must be non-null.", | ||
iae.message | ||
) | ||
} | ||
} | ||
} |