Skip to content

Commit

Permalink
Add getCardBuilder() method to Card widgets (#1174)
Browse files Browse the repository at this point in the history
  • Loading branch information
mshafrir-stripe committed Jul 15, 2019
1 parent e380847 commit 95bedd3
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 41 deletions.
14 changes: 1 addition & 13 deletions stripe/src/main/java/com/stripe/android/model/Card.java
Original file line number Diff line number Diff line change
Expand Up @@ -420,18 +420,6 @@ public List<String> getLoggingTokens() {
return loggingTokens;
}

/**
* Add a logging token to this {@link Card} object.
*
* @param loggingToken a token to be logged with this card
* @return {@code this}, for chaining purposes
*/
@NonNull
public Card addLoggingToken(@NonNull String loggingToken) {
loggingTokens.add(loggingToken);
return this;
}

/**
* @return the {@link #cvc} for this card
*/
Expand Down Expand Up @@ -947,7 +935,7 @@ public Builder metadata(@Nullable Map<String, String> metadata) {
}

@NonNull
private Builder loggingTokens(@NonNull List<String> loggingTokens) {
public Builder loggingTokens(@NonNull List<String> loggingTokens) {
this.loggingTokens = loggingTokens;
return this;
}
Expand Down
38 changes: 23 additions & 15 deletions stripe/src/main/java/com/stripe/android/view/CardInputWidget.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
import com.stripe.android.model.Card;
import com.stripe.android.model.PaymentMethodCreateParams;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Locale;

import static com.stripe.android.model.Card.CardBrand;
Expand All @@ -44,7 +46,7 @@
/**
* A card input widget that handles all animation on its own.
*/
public class CardInputWidget extends LinearLayout {
public class CardInputWidget extends LinearLayout implements CardWidget {

static final String LOGGING_TOKEN = "CardInputView";

Expand Down Expand Up @@ -121,7 +123,8 @@ public PaymentMethodCreateParams.Card getPaymentMethodCard() {
final String cvcValue = mCvcNumberEditText.getText().toString().trim();

// CVC/CVV is the only field not validated by the entry control itself, so we check here.
if (cardNumber == null || cardDate == null || cardDate.length != 2 || !isCvcLengthValid()) {
if (cardNumber == null || cardDate == null || cardDate.length != 2 ||
!isCvcLengthValid(cvcValue)) {
return null;
}

Expand All @@ -139,22 +142,30 @@ public PaymentMethodCreateParams.Card getPaymentMethodCard() {
* @return a valid {@link Card} object based on user input, or {@code null} if any field is
* invalid
*/
@Override
@Nullable
public Card getCard() {
String cardNumber = mCardNumberEditText.getCardNumber();
int[] cardDate = mExpiryDateEditText.getValidDateFields();
final Card.Builder builder = getCardBuilder();
return builder != null ? builder.build() : null;
}

@Override
@Nullable
public Card.Builder getCardBuilder() {
final String cardNumber = mCardNumberEditText.getCardNumber();
final int[] cardDate = mExpiryDateEditText.getValidDateFields();
if (cardNumber == null || cardDate == null || cardDate.length != 2) {
return null;
}

// CVC/CVV is the only field not validated by the entry control itself, so we check here.
String cvcValue = mCvcNumberEditText.getText().toString().trim();
if (!isCvcLengthValid()) {
final String cvcValue = mCvcNumberEditText.getText().toString().trim();
if (!isCvcLengthValid(cvcValue)) {
return null;
}

return Card.create(cardNumber, cardDate[0], cardDate[1], cvcValue)
.addLoggingToken(LOGGING_TOKEN);
return new Card.Builder(cardNumber, cardDate[0], cardDate[1], cvcValue)
.loggingTokens(new ArrayList<>(Collections.singletonList(LOGGING_TOKEN)));
}

/**
Expand Down Expand Up @@ -456,16 +467,13 @@ void updateSpaceSizes(boolean isCardViewed) {
}
}

private boolean isCvcLengthValid() {
String cvcValue = mCvcNumberEditText.getText().toString().trim();
int cvcLength = cvcValue.length();
private boolean isCvcLengthValid(@NonNull String cvcValue) {
final int cvcLength = cvcValue.length();
if (mIsAmEx && cvcLength == Card.CVC_LENGTH_AMERICAN_EXPRESS) {
return true;
}
if (cvcLength == Card.CVC_LENGTH_COMMON) {
return true;
}
return false;

return cvcLength == Card.CVC_LENGTH_COMMON;
}

private void setLayoutValues(int width, int margin, @NonNull StripeEditText editText) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Objects;

import static com.stripe.android.view.CardInputListener.FocusField.FOCUS_CARD;
Expand All @@ -43,7 +45,7 @@
* A multiline card input widget using the support design library's {@link TextInputLayout}
* to match Material Design.
*/
public class CardMultilineWidget extends LinearLayout {
public class CardMultilineWidget extends LinearLayout implements CardWidget {

static final String CARD_MULTILINE_TOKEN = "CardMultilineView";
static final long CARD_NUMBER_HINT_DELAY = 120L;
Expand Down Expand Up @@ -162,21 +164,28 @@ public PaymentMethod.BillingDetails getPaymentMethodBillingDetails() {
* @return a valid {@link Card} object based on user input, or {@code null} if any field is
* invalid
*/
@Override
@Nullable
public Card getCard() {
if (validateAllFields()) {
final String cardNumber = mCardNumberEditText.getCardNumber();
final int[] cardDate = Objects.requireNonNull(mExpiryDateEditText.getValidDateFields());
final String cvcValue = mCvcEditText.getText().toString();

final Card card = new Card.Builder(cardNumber, cardDate[0], cardDate[1], cvcValue)
.addressZip(mShouldShowPostalCode ?
mPostalCodeEditText.getText().toString() : null)
.build();
return card.addLoggingToken(CARD_MULTILINE_TOKEN);
final Card.Builder cardBuilder = getCardBuilder();
return cardBuilder != null ? cardBuilder.build() : null;
}

@Override
@Nullable
public Card.Builder getCardBuilder() {
if (!validateAllFields()) {
return null;
}

return null;
final String cardNumber = mCardNumberEditText.getCardNumber();
final int[] cardDate = Objects.requireNonNull(mExpiryDateEditText.getValidDateFields());
final String cvcValue = mCvcEditText.getText().toString();

return new Card.Builder(cardNumber, cardDate[0], cardDate[1], cvcValue)
.addressZip(mShouldShowPostalCode ?
mPostalCodeEditText.getText().toString() : null)
.loggingTokens(new ArrayList<>(Collections.singletonList(CARD_MULTILINE_TOKEN)));
}

/**
Expand Down
11 changes: 11 additions & 0 deletions stripe/src/main/java/com/stripe/android/view/CardWidget.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.stripe.android.view;

import android.support.annotation.Nullable;

import com.stripe.android.model.Card;

interface CardWidget {
@Nullable Card getCard();

@Nullable Card.Builder getCardBuilder();
}
4 changes: 3 additions & 1 deletion stripe/src/test/java/com/stripe/android/model/CardTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.junit.Test;

import java.util.Calendar;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
Expand Down Expand Up @@ -693,7 +694,8 @@ public void toBuilder_whenUnchanged_isEquals() {
@Test
public void toBuilder_withLoggingToken_whenUnchanged_isEquals() {
final Card card = Objects.requireNonNull(Card.fromString(JSON_CARD_USD));
card.addLoggingToken("hello");
card.toBuilder()
.loggingTokens(Collections.singletonList("hello"));

assertEquals(card, card.toBuilder().build());
}
Expand Down

0 comments on commit 95bedd3

Please sign in to comment.