diff --git a/app/src/main/java/org/mozilla/fenix/settings/creditcards/CreditCardEditorFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/creditcards/CreditCardEditorFragment.kt index 20f91c480..3cd844501 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/creditcards/CreditCardEditorFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/creditcards/CreditCardEditorFragment.kt @@ -85,9 +85,5 @@ class CreditCardEditorFragment : SecureFragment(R.layout.fragment_credit_card_ed companion object { // Number of years to show in the expiry year dropdown. const val NUMBER_OF_YEARS_TO_SHOW = 10 - - // Placeholder for the card type. This will be replaced when we can identify the card type. - // This is dependent on https://github.com/mozilla-mobile/android-components/issues/9813. - const val CARD_TYPE_PLACEHOLDER = "" } } diff --git a/app/src/main/java/org/mozilla/fenix/settings/creditcards/String.kt b/app/src/main/java/org/mozilla/fenix/settings/creditcards/String.kt index 329034d34..0702b6c5f 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/creditcards/String.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/creditcards/String.kt @@ -5,9 +5,8 @@ package org.mozilla.fenix.settings.creditcards import androidx.annotation.VisibleForTesting +import mozilla.components.support.utils.creditCardIIN -private const val MAX_CREDIT_CARD_NUMBER_LENGTH = 19 -private const val MIN_CREDIT_CARD_NUMBER_LENGTH = 12 // Number of last digits to be shown when credit card number is obfuscated. private const val LAST_VISIBLE_DIGITS_COUNT = 4 @@ -27,17 +26,15 @@ fun String.last4Digits(): String { } /** - * Uses string size and Luhn Algorithm validation to validate a credit card number. + * Returns true if the provided string is a valid credit card by checking if it has a matching + * credit card issuer network passes the Luhn Algorithm, and false otherwise. */ fun String.validateCreditCardNumber(): Boolean { val creditCardNumber = this.toCreditCardNumber() - if (creditCardNumber != this) return false - - // credit card numbers have at least 12 digits and at most 19 digits - if (creditCardNumber.length < MIN_CREDIT_CARD_NUMBER_LENGTH || - creditCardNumber.length > MAX_CREDIT_CARD_NUMBER_LENGTH - ) return false + if (creditCardNumber != this || creditCardNumber.creditCardIIN() == null) { + return false + } return luhnAlgorithmValidation(creditCardNumber) } diff --git a/app/src/main/java/org/mozilla/fenix/settings/creditcards/view/CreditCardEditorView.kt b/app/src/main/java/org/mozilla/fenix/settings/creditcards/view/CreditCardEditorView.kt index 679b97eb1..797dce123 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/creditcards/view/CreditCardEditorView.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/creditcards/view/CreditCardEditorView.kt @@ -14,9 +14,9 @@ import mozilla.components.concept.storage.NewCreditCardFields import mozilla.components.concept.storage.UpdatableCreditCardFields import mozilla.components.support.ktx.android.content.getColorFromAttr import mozilla.components.support.ktx.android.view.hideKeyboard +import mozilla.components.support.utils.creditCardIIN import org.mozilla.fenix.R import org.mozilla.fenix.ext.toEditable -import org.mozilla.fenix.settings.creditcards.CreditCardEditorFragment.Companion.CARD_TYPE_PLACEHOLDER import org.mozilla.fenix.settings.creditcards.CreditCardEditorState import org.mozilla.fenix.settings.creditcards.interactor.CreditCardEditorInteractor import org.mozilla.fenix.settings.creditcards.last4Digits @@ -80,7 +80,7 @@ class CreditCardEditorView( cardNumberLast4 = cardNumber.last4Digits(), expiryMonth = (expiry_month_drop_down.selectedItemPosition + 1).toLong(), expiryYear = expiry_year_drop_down.selectedItem.toString().toLong(), - cardType = CARD_TYPE_PLACEHOLDER + cardType = cardNumber.creditCardIIN()?.creditCardIssuerNetwork?.name ?: "" ) interactor.onUpdateCreditCard(state.guid, fields) } else { @@ -90,7 +90,7 @@ class CreditCardEditorView( cardNumberLast4 = cardNumber.last4Digits(), expiryMonth = (expiry_month_drop_down.selectedItemPosition + 1).toLong(), expiryYear = expiry_year_drop_down.selectedItem.toString().toLong(), - cardType = CARD_TYPE_PLACEHOLDER + cardType = cardNumber.creditCardIIN()?.creditCardIssuerNetwork?.name ?: "" ) interactor.onSaveCreditCard(fields) } diff --git a/app/src/main/java/org/mozilla/fenix/settings/creditcards/view/CreditCardItemViewHolder.kt b/app/src/main/java/org/mozilla/fenix/settings/creditcards/view/CreditCardItemViewHolder.kt index 0ac77e17a..0e733bfb1 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/creditcards/view/CreditCardItemViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/creditcards/view/CreditCardItemViewHolder.kt @@ -7,6 +7,7 @@ package org.mozilla.fenix.settings.creditcards.view import android.view.View import kotlinx.android.synthetic.main.credit_card_list_item.* import mozilla.components.concept.storage.CreditCard +import mozilla.components.support.utils.creditCardIssuerNetwork import org.mozilla.fenix.R import org.mozilla.fenix.settings.creditcards.interactor.CreditCardsManagementInteractor import org.mozilla.fenix.utils.view.ViewHolder @@ -23,6 +24,8 @@ class CreditCardItemViewHolder( ) : ViewHolder(view) { fun bind(creditCard: CreditCard) { + credit_card_logo.setImageResource(creditCard.cardType.creditCardIssuerNetwork().icon) + credit_card_number.text = creditCard.obfuscatedCardNumber bindCreditCardExpiryDate(creditCard) diff --git a/app/src/main/res/layout/credit_card_list_item.xml b/app/src/main/res/layout/credit_card_list_item.xml index 386eed434..121e4b494 100644 --- a/app/src/main/res/layout/credit_card_list_item.xml +++ b/app/src/main/res/layout/credit_card_list_item.xml @@ -10,19 +10,30 @@ android:background="?android:attr/selectableItemBackground" android:minHeight="?android:attr/listPreferredItemHeight"> + + @@ -38,7 +49,7 @@ android:textColor="?secondaryText" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" + app:layout_constraintStart_toEndOf="@+id/credit_card_logo" app:layout_constraintTop_toBottomOf="@id/credit_card_number" app:layout_constraintVertical_chainStyle="packed" tools:text="02/2022" /> diff --git a/app/src/test/java/org/mozilla/fenix/settings/creditcards/CreditCardEditorStateTest.kt b/app/src/test/java/org/mozilla/fenix/settings/creditcards/CreditCardEditorStateTest.kt index bf583b15f..78d3bfde0 100644 --- a/app/src/test/java/org/mozilla/fenix/settings/creditcards/CreditCardEditorStateTest.kt +++ b/app/src/test/java/org/mozilla/fenix/settings/creditcards/CreditCardEditorStateTest.kt @@ -6,6 +6,7 @@ package org.mozilla.fenix.settings.creditcards import mozilla.components.concept.storage.CreditCard import mozilla.components.concept.storage.CreditCardNumber +import mozilla.components.support.utils.CreditCardNetworkType import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue @@ -22,7 +23,7 @@ class CreditCardEditorStateTest { cardNumberLast4 = "1110", expiryMonth = 5, expiryYear = 2030, - cardType = "amex", + cardType = CreditCardNetworkType.AMEX.cardName, timeCreated = 1L, timeLastUsed = 1L, timeLastModified = 1L, diff --git a/app/src/test/java/org/mozilla/fenix/settings/creditcards/CreditCardEditorViewTest.kt b/app/src/test/java/org/mozilla/fenix/settings/creditcards/CreditCardEditorViewTest.kt index cdbec24fa..8fbe1390a 100644 --- a/app/src/test/java/org/mozilla/fenix/settings/creditcards/CreditCardEditorViewTest.kt +++ b/app/src/test/java/org/mozilla/fenix/settings/creditcards/CreditCardEditorViewTest.kt @@ -15,6 +15,7 @@ import mozilla.components.concept.storage.CreditCardNumber import mozilla.components.concept.storage.NewCreditCardFields import mozilla.components.concept.storage.UpdatableCreditCardFields import mozilla.components.support.test.robolectric.testContext +import mozilla.components.support.utils.CreditCardNetworkType import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue @@ -24,7 +25,6 @@ import org.junit.runner.RunWith import org.mozilla.fenix.R import org.mozilla.fenix.ext.toEditable import org.mozilla.fenix.helpers.FenixRobolectricTestRunner -import org.mozilla.fenix.settings.creditcards.CreditCardEditorFragment.Companion.CARD_TYPE_PLACEHOLDER import org.mozilla.fenix.settings.creditcards.CreditCardEditorFragment.Companion.NUMBER_OF_YEARS_TO_SHOW import org.mozilla.fenix.settings.creditcards.interactor.CreditCardEditorInteractor import org.mozilla.fenix.settings.creditcards.view.CreditCardEditorView @@ -40,11 +40,11 @@ class CreditCardEditorViewTest { private val creditCard = CreditCard( guid = "id", billingName = "Banana Apple", - encryptedCardNumber = CreditCardNumber.Encrypted("371449635398431"), - cardNumberLast4 = "8431", + encryptedCardNumber = CreditCardNumber.Encrypted("4111111111111111"), + cardNumberLast4 = "1111", expiryMonth = 5, expiryYear = 2030, - cardType = "amex", + cardType = CreditCardNetworkType.VISA.cardName, timeCreated = 1L, timeLastUsed = 1L, timeLastModified = 1L, @@ -133,7 +133,7 @@ class CreditCardEditorViewTest { val calendar = Calendar.getInstance() val billingName = "Banana Apple" - val cardNumber = "4111111111111110" + val cardNumber = "2221000000000000" val expiryMonth = 5 val expiryYear = calendar.get(Calendar.YEAR) @@ -154,10 +154,10 @@ class CreditCardEditorViewTest { NewCreditCardFields( billingName = billingName, plaintextCardNumber = CreditCardNumber.Plaintext(cardNumber), - cardNumberLast4 = "1110", + cardNumberLast4 = "0000", expiryMonth = expiryMonth.toLong(), expiryYear = expiryYear.toLong(), - cardType = CARD_TYPE_PLACEHOLDER + cardType = CreditCardNetworkType.MASTERCARD.cardName ) ) } @@ -170,7 +170,7 @@ class CreditCardEditorViewTest { val calendar = Calendar.getInstance() val billingName = "Banana Apple" - val cardNumber = "371449635398431" + val cardNumber = "2720994326581252" val expiryMonth = 5 val expiryYear = calendar.get(Calendar.YEAR) @@ -191,10 +191,10 @@ class CreditCardEditorViewTest { NewCreditCardFields( billingName = billingName, plaintextCardNumber = CreditCardNumber.Plaintext(cardNumber), - cardNumberLast4 = "8431", + cardNumberLast4 = "1252", expiryMonth = expiryMonth.toLong(), expiryYear = expiryYear.toLong(), - cardType = CARD_TYPE_PLACEHOLDER + cardType = CreditCardNetworkType.MASTERCARD.cardName ) ) } @@ -215,7 +215,7 @@ class CreditCardEditorViewTest { cardNumberLast4 = creditCard.cardNumberLast4, expiryMonth = creditCard.expiryMonth, expiryYear = creditCard.expiryYear, - cardType = CARD_TYPE_PLACEHOLDER + cardType = creditCard.cardType ) ) } diff --git a/app/src/test/java/org/mozilla/fenix/settings/creditcards/CreditCardItemViewHolderTest.kt b/app/src/test/java/org/mozilla/fenix/settings/creditcards/CreditCardItemViewHolderTest.kt index 16a31a31d..daf7ccc78 100644 --- a/app/src/test/java/org/mozilla/fenix/settings/creditcards/CreditCardItemViewHolderTest.kt +++ b/app/src/test/java/org/mozilla/fenix/settings/creditcards/CreditCardItemViewHolderTest.kt @@ -12,6 +12,7 @@ import kotlinx.android.synthetic.main.credit_card_list_item.view.* import mozilla.components.concept.storage.CreditCard import mozilla.components.concept.storage.CreditCardNumber import mozilla.components.support.test.robolectric.testContext +import mozilla.components.support.utils.CreditCardNetworkType import org.junit.Assert.assertEquals import org.junit.Before import org.junit.Test @@ -33,7 +34,7 @@ class CreditCardItemViewHolderTest { cardNumberLast4 = "1110", expiryMonth = 1, expiryYear = 2030, - cardType = "amex", + cardType = CreditCardNetworkType.AMEX.cardName, timeCreated = 1L, timeLastUsed = 1L, timeLastModified = 1L, diff --git a/app/src/test/java/org/mozilla/fenix/settings/creditcards/CreditCardsAdapterTest.kt b/app/src/test/java/org/mozilla/fenix/settings/creditcards/CreditCardsAdapterTest.kt index f68bca7df..1f74564e0 100644 --- a/app/src/test/java/org/mozilla/fenix/settings/creditcards/CreditCardsAdapterTest.kt +++ b/app/src/test/java/org/mozilla/fenix/settings/creditcards/CreditCardsAdapterTest.kt @@ -6,6 +6,7 @@ package org.mozilla.fenix.settings.creditcards import mozilla.components.concept.storage.CreditCard import mozilla.components.concept.storage.CreditCardNumber +import mozilla.components.support.utils.CreditCardNetworkType import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import org.junit.Test @@ -22,7 +23,7 @@ class CreditCardsAdapterTest { cardNumberLast4 = "1110", expiryMonth = 1, expiryYear = 2030, - cardType = "amex", + cardType = CreditCardNetworkType.AMEX.cardName, timeCreated = 1L, timeLastUsed = 1L, timeLastModified = 1L, @@ -35,7 +36,7 @@ class CreditCardsAdapterTest { cardNumberLast4 = "1110", expiryMonth = 1, expiryYear = 2030, - cardType = "amex", + cardType = CreditCardNetworkType.AMEX.cardName, timeCreated = 1L, timeLastUsed = 1L, timeLastModified = 1L, @@ -56,7 +57,7 @@ class CreditCardsAdapterTest { cardNumberLast4 = "1110", expiryMonth = 1, expiryYear = 2030, - cardType = "amex", + cardType = CreditCardNetworkType.AMEX.cardName, timeCreated = 1L, timeLastUsed = 1L, timeLastModified = 1L, diff --git a/app/src/test/java/org/mozilla/fenix/settings/creditcards/DefaultCreditCardEditorControllerTest.kt b/app/src/test/java/org/mozilla/fenix/settings/creditcards/DefaultCreditCardEditorControllerTest.kt index d0844d93a..f9429242f 100644 --- a/app/src/test/java/org/mozilla/fenix/settings/creditcards/DefaultCreditCardEditorControllerTest.kt +++ b/app/src/test/java/org/mozilla/fenix/settings/creditcards/DefaultCreditCardEditorControllerTest.kt @@ -18,6 +18,7 @@ import mozilla.components.concept.storage.NewCreditCardFields import mozilla.components.concept.storage.UpdatableCreditCardFields import mozilla.components.service.sync.autofill.AutofillCreditCardsAddressesStorage import mozilla.components.support.test.rule.MainCoroutineRule +import mozilla.components.support.utils.CreditCardNetworkType import org.junit.After import org.junit.Before import org.junit.Rule @@ -85,7 +86,7 @@ class DefaultCreditCardEditorControllerTest { cardNumberLast4 = "1112", expiryMonth = 1, expiryYear = 2030, - cardType = "discover" + cardType = CreditCardNetworkType.DISCOVER.cardName ) controller.handleSaveCreditCard(creditCardFields) @@ -105,7 +106,7 @@ class DefaultCreditCardEditorControllerTest { cardNumberLast4 = "1112", expiryMonth = 1, expiryYear = 2034, - cardType = "discover" + cardType = CreditCardNetworkType.DISCOVER.cardName ) controller.handleUpdateCreditCard(creditCardId, creditCardFields) diff --git a/app/src/test/java/org/mozilla/fenix/settings/creditcards/DefaultCreditCardEditorInteractorTest.kt b/app/src/test/java/org/mozilla/fenix/settings/creditcards/DefaultCreditCardEditorInteractorTest.kt index 890dbbad0..31d7fa5d9 100644 --- a/app/src/test/java/org/mozilla/fenix/settings/creditcards/DefaultCreditCardEditorInteractorTest.kt +++ b/app/src/test/java/org/mozilla/fenix/settings/creditcards/DefaultCreditCardEditorInteractorTest.kt @@ -10,6 +10,7 @@ import mozilla.components.concept.storage.CreditCard import mozilla.components.concept.storage.CreditCardNumber import mozilla.components.concept.storage.NewCreditCardFields import mozilla.components.concept.storage.UpdatableCreditCardFields +import mozilla.components.support.utils.CreditCardNetworkType import org.junit.Before import org.junit.Test import org.mozilla.fenix.settings.creditcards.controller.CreditCardEditorController @@ -41,7 +42,7 @@ class DefaultCreditCardEditorInteractorTest { cardNumberLast4 = "1110", expiryMonth = 1, expiryYear = 2030, - cardType = "amex", + cardType = CreditCardNetworkType.AMEX.cardName, timeCreated = 1L, timeLastUsed = 1L, timeLastModified = 1L, @@ -59,7 +60,7 @@ class DefaultCreditCardEditorInteractorTest { cardNumberLast4 = "1112", expiryMonth = 1, expiryYear = 2030, - cardType = "discover" + cardType = CreditCardNetworkType.DISCOVER.cardName ) interactor.onSaveCreditCard(creditCardFields) verify { controller.handleSaveCreditCard(creditCardFields) } @@ -74,7 +75,7 @@ class DefaultCreditCardEditorInteractorTest { cardNumberLast4 = "1112", expiryMonth = 1, expiryYear = 2034, - cardType = "discover" + cardType = CreditCardNetworkType.DISCOVER.cardName ) interactor.onUpdateCreditCard(guid, creditCardFields) verify { controller.handleUpdateCreditCard(guid, creditCardFields) } diff --git a/app/src/test/java/org/mozilla/fenix/settings/creditcards/DefaultCreditCardsManagementControllerTest.kt b/app/src/test/java/org/mozilla/fenix/settings/creditcards/DefaultCreditCardsManagementControllerTest.kt index 438a6c788..8d5139c3a 100644 --- a/app/src/test/java/org/mozilla/fenix/settings/creditcards/DefaultCreditCardsManagementControllerTest.kt +++ b/app/src/test/java/org/mozilla/fenix/settings/creditcards/DefaultCreditCardsManagementControllerTest.kt @@ -10,6 +10,7 @@ import io.mockk.spyk import io.mockk.verify import mozilla.components.concept.storage.CreditCard import mozilla.components.concept.storage.CreditCardNumber +import mozilla.components.support.utils.CreditCardNetworkType import org.junit.Before import org.junit.Rule import org.junit.Test @@ -43,7 +44,7 @@ class DefaultCreditCardsManagementControllerTest { encryptedCardNumber = CreditCardNumber.Encrypted("4111111111111110"), cardNumberLast4 = "1110", expiryYear = 2030, - cardType = "amex", + cardType = CreditCardNetworkType.AMEX.cardName, timeCreated = 1L, timeLastUsed = 1L, timeLastModified = 1L, diff --git a/app/src/test/java/org/mozilla/fenix/settings/creditcards/StringTest.kt b/app/src/test/java/org/mozilla/fenix/settings/creditcards/StringTest.kt index e222c862d..e8f2b8289 100644 --- a/app/src/test/java/org/mozilla/fenix/settings/creditcards/StringTest.kt +++ b/app/src/test/java/org/mozilla/fenix/settings/creditcards/StringTest.kt @@ -42,7 +42,6 @@ class StringTest { val jcbCard = "3530111333300000" val masterCardCard = "5555555555554444" val visaCard = "4111111111111111" - val voyagerCard = "869941728035895" assertTrue(americanExpressCard.validateCreditCardNumber()) assertTrue(dinnersClubCard.validateCreditCardNumber()) @@ -50,7 +49,6 @@ class StringTest { assertTrue(jcbCard.validateCreditCardNumber()) assertTrue(masterCardCard.validateCreditCardNumber()) assertTrue(visaCard.validateCreditCardNumber()) - assertTrue(voyagerCard.validateCreditCardNumber()) } @Test