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

Add Shopping Insights Demo App Integration #854

Merged
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
5 changes: 4 additions & 1 deletion Demo/build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
plugins {
id 'com.android.application'
id 'androidx.navigation.safeargs'
id 'kotlin-android'
}

android {
Expand Down Expand Up @@ -75,7 +76,7 @@ android {

dependencies {
implementation 'androidx.preference:preference:1.1.1'

implementation deps.kotlinStdLib
implementation('com.squareup.retrofit:retrofit:1.9.0') {
exclude module: 'com.google.gson'
}
Expand All @@ -88,6 +89,7 @@ dependencies {
implementation project(':PayPal')
implementation project(':PayPalNativeCheckout')
implementation project(':SamsungPay')
implementation project(':ShopperInsights')
implementation project(':SEPADirectDebit')
implementation project(':ThreeDSecure')
implementation project(':UnionPay')
Expand All @@ -112,6 +114,7 @@ dependencies {
implementation 'androidx.navigation:navigation-ui:2.3.5'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'

debugImplementation 'com.facebook.stetho:stetho:1.5.0'
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.12'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c
Button samsungButton = view.findViewById(R.id.samsung_pay);
Button sepaDirectDebitButton = view.findViewById(R.id.sepa_debit);
Button payPalNativeCheckoutButton = view.findViewById(R.id.paypal_native_checkout);
Button shoppingInsightsButton = view.findViewById(R.id.shopping_insight);

cardsButton.setOnClickListener(this::launchCards);
payPalButton.setOnClickListener(this::launchPayPal);
Expand All @@ -47,6 +48,7 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c
samsungButton.setOnClickListener(this::launchSamsungPay);
payPalNativeCheckoutButton.setOnClickListener(this::launchPayPalNativeCheckout);
sepaDirectDebitButton.setOnClickListener(this::launchSEPADirectDebit);
shoppingInsightsButton.setOnClickListener(this::launchShoppingInsights);

return view;
}
Expand Down Expand Up @@ -126,4 +128,10 @@ public void launchSEPADirectDebit(View v) {
NavDirections action = MainFragmentDirections.actionMainFragmentToSepaDirectDebitFragment();
Navigation.findNavController(v).navigate(action);
}

public void launchShoppingInsights(View v) {
NavDirections action =
MainFragmentDirections.actionMainFragmentToShoppingInsightsFragment();
Navigation.findNavController(v).navigate(action);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.braintreepayments.demo

import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.braintreepayments.api.BuyerPhone
import com.braintreepayments.api.ShopperInsightsRequest
import com.braintreepayments.api.ShopperInsightsResult

/**
* ViewModel for handling shopping insights.
*/
class ShoppingInsightViewModel : ViewModel() {

private val shopperInsightsLiveData = MutableLiveData<ShopperInsightsResult>()

/**
* Fetches recommended payment methods using the provided buyer details.
*
* @param email The email address of the buyer.
* @param countryCode The country code for the buyer's phone number.
* @param nationalNumber The national number part of the buyer's phone number.
* @return MutableLiveData containing ShopperInsightsResult.
*/
fun getRecommendedPaymentMethods(
email: String?,
countryCode: String?,
nationalNumber: String?
): MutableLiveData<ShopperInsightsResult> {
@Suppress("UnusedPrivateMember")
val request = if (countryCode != null && nationalNumber != null) {
ShopperInsightsRequest(email, BuyerPhone(countryCode, nationalNumber))
} else {
ShopperInsightsRequest(email, null)
}
// TODO: Call Shopping Insight Client
// shopperInsightsClient.getRecommendedPaymentMethods(request) { result ->
// shopperInsightsLiveData.postValue(result)
// }

return shopperInsightsLiveData
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.braintreepayments.demo

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.TextView
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import com.google.android.material.switchmaterial.SwitchMaterial
import com.google.android.material.textfield.TextInputLayout

/**
* Fragment for handling shopping insights.
*/
class ShoppingInsightsFragment : Fragment() {

private lateinit var responseTextView: TextView
private lateinit var actionButton: Button
private lateinit var emailInput: TextInputLayout
private lateinit var countryCodeInput: TextInputLayout
private lateinit var nationalNumberInput: TextInputLayout
private lateinit var emailNullSwitch: SwitchMaterial
private lateinit var phoneNullSwitch: SwitchMaterial

private val viewModel: ShoppingInsightViewModel by lazy {
ViewModelProvider(this)[ShoppingInsightViewModel::class.java]
}

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_shopping_insights, container, false)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initializeViews(view)
setupActionButton()
}

private fun initializeViews(view: View) {
responseTextView = view.findViewById(R.id.responseTextView)
actionButton = view.findViewById(R.id.actionButton)
emailInput = view.findViewById(R.id.emailInput)
countryCodeInput = view.findViewById(R.id.countryCodeInput)
nationalNumberInput = view.findViewById(R.id.nationalNumberInput)
emailNullSwitch = view.findViewById(R.id.emailNullSwitch)
phoneNullSwitch = view.findViewById(R.id.phoneNullSwitch)
}

private fun setupActionButton() {
actionButton.setOnClickListener {
val email = if (emailNullSwitch.isChecked) null else emailInput.editText?.text.toString()
val countryCode = if (phoneNullSwitch.isChecked) null else countryCodeInput.editText?.text.toString()
val nationalNumber = if (phoneNullSwitch.isChecked) null else nationalNumberInput.editText?.text.toString()
viewModel.getRecommendedPaymentMethods(email, countryCode, nationalNumber)
.observe(viewLifecycleOwner) {
responseTextView.text = it.toString()
}
}
}
}
9 changes: 9 additions & 0 deletions Demo/src/main/res/layout/fragment_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@
android:text="@string/cards"
android:textSize="12sp" />

<Button
android:id="@+id/shopping_insight"
style="?android:attr/buttonStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/shopping_insights_button"
android:textSize="12sp" />
</TableRow>

<TableRow
Expand Down Expand Up @@ -119,4 +127,5 @@
android:textSize="12sp" />

</TableRow>

</TableLayout>
135 changes: 135 additions & 0 deletions Demo/src/main/res/layout/fragment_shopping_insights.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">

<View
android:id="@+id/view2"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="8dp"
android:background="@android:color/darker_gray"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/countryCodeInput" />

<TextView
android:id="@+id/responseLabel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:text="@string/insights_response_label"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/actionButton" />

<com.google.android.material.textfield.TextInputLayout
android:id="@+id/countryCodeInput"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:hint="@string/insights_text_input_country_code"
app:layout_constraintEnd_toStartOf="@+id/phoneNullSwitch"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/nationalNumberInput">

<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>

<com.google.android.material.textfield.TextInputLayout
android:id="@+id/emailInput"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
app:layout_constraintEnd_toStartOf="@+id/emailNullSwitch"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">

<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/insights_text_input_email" />
</com.google.android.material.textfield.TextInputLayout>

<com.google.android.material.textfield.TextInputLayout
android:id="@+id/nationalNumberInput"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="16dp"
app:layout_constraintEnd_toStartOf="@+id/phoneNullSwitch"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/emailInput">

<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/insights_text_input_national_number" />
</com.google.android.material.textfield.TextInputLayout>

<TextView
android:id="@+id/responseTextView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:text=""
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/responseLabel" />

<Button
android:id="@+id/actionButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="16dp"
android:text="@string/insights_action_button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/countryCodeInput" />

<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/emailNullSwitch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:text="@string/insights_null_switch"
app:layout_constraintBottom_toBottomOf="@+id/emailInput"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/emailInput" />

<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/phoneNullSwitch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:text="@string/insights_null_switch"
app:layout_constraintBottom_toBottomOf="@+id/countryCodeInput"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/nationalNumberInput" />

<View
android:id="@+id/view3"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="16dp"
android:background="@android:color/darker_gray"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/emailInput" />

</androidx.constraintlayout.widget.ConstraintLayout>
9 changes: 8 additions & 1 deletion Demo/src/main/res/navigation/nav_graph.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
<action
android:id="@+id/action_mainFragment_to_payPalNativeCheckoutFragment"
app:destination="@id/payPalNativeCheckoutFragment" />
<action
android:id="@+id/action_mainFragment_to_shoppingInsightsFragment"
app:destination="@id/shoppingInsightsFragment" />
</fragment>
<fragment
android:id="@+id/cardFragment"
Expand Down Expand Up @@ -179,5 +182,9 @@
app:popUpTo="@id/mainFragment"
app:popUpToInclusive="false" />
</fragment>

<fragment
android:id="@+id/shoppingInsightsFragment"
android:name="com.braintreepayments.demo.ShoppingInsightsFragment"
tools:layout="@layout/fragment_shopping_insights">
</fragment>
</navigation>
8 changes: 8 additions & 0 deletions Demo/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<string name="local_payment_button">Local Payment</string>
<string name="sepa_direct_debit_button">SEPA Direct Debit</string>
<string name="cards">Credit or Debit Cards</string>
<string name="shopping_insights_button">Shopping Insights</string>
<string name="paypal_native_checkout">PayPal Native Checkout</string>
<string name="samsung_pay">Samsung Pay</string>
<string name="create_transaction">Create a Transaction</string>
Expand Down Expand Up @@ -124,4 +125,11 @@
<!-- LocalPayment -->
<string name="bt_local_payment_description">This feature uses a hard-coded sandbox tokenization key that is enabled for this local payment.</string>

<!-- Shopping Insights -->
<string name="insights_text_input_email">Email</string>
<string name="insights_text_input_country_code">Country Code</string>
<string name="insights_text_input_national_number">National Number</string>
<string name="insights_action_button">Submit</string>
<string name="insights_response_label">Response:</string>
<string name="insights_null_switch">Null </string>
</resources>
Loading