Skip to content

Commit

Permalink
Add support for SEPA Debit in PaymentMethod (#1693)
Browse files Browse the repository at this point in the history
* Add support for SEPA Debit in PaymentMethod

* Respond to comments
  • Loading branch information
mshafrir-stripe authored Oct 11, 2019
1 parent d46b1e8 commit 1ef1c6c
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 1 deletion.
107 changes: 106 additions & 1 deletion stripe/src/main/java/com/stripe/android/model/PaymentMethod.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public final class PaymentMethod extends StripeModel implements Parcelable {
private static final String FIELD_CARD_PRESENT = "card_present";
private static final String FIELD_FPX = "fpx";
private static final String FIELD_IDEAL = "ideal";
private static final String FIELD_SEPA_DEBIT = "sepa_debit";

@Nullable public final String id;
@Nullable public final Long created;
Expand All @@ -62,6 +63,7 @@ public final class PaymentMethod extends StripeModel implements Parcelable {
@Nullable public final CardPresent cardPresent;
@Nullable public final Fpx fpx;
@Nullable public final Ideal ideal;
@Nullable public final SepaDebit sepaDebit;

public enum Type implements Parcelable {
Card("card"),
Expand Down Expand Up @@ -135,6 +137,7 @@ private PaymentMethod(@NonNull Builder builder) {
cardPresent = builder.mCardPresent;
fpx = builder.mFpx;
ideal = builder.mIdeal;
sepaDebit = builder.mSepaDebit;
}

/**
Expand Down Expand Up @@ -182,6 +185,8 @@ public static PaymentMethod fromJson(@Nullable JSONObject paymentMethod) {
builder.setIdeal(Ideal.fromJson(paymentMethod.optJSONObject(FIELD_IDEAL)));
} else if (FIELD_FPX.equals(type)) {
builder.setFpx(Fpx.fromJson(paymentMethod.optJSONObject(FIELD_FPX)));
} else if (FIELD_SEPA_DEBIT.equals(type)) {
builder.setSepaDebit(SepaDebit.fromJson(paymentMethod.optJSONObject(FIELD_SEPA_DEBIT)));
}

return builder.build();
Expand All @@ -202,6 +207,7 @@ private boolean typedEquals(@NonNull PaymentMethod paymentMethod) {
&& Objects.equals(cardPresent, paymentMethod.cardPresent)
&& Objects.equals(fpx, paymentMethod.fpx)
&& Objects.equals(ideal, paymentMethod.ideal)
&& Objects.equals(sepaDebit, paymentMethod.sepaDebit)
&& Objects.equals(customerId, paymentMethod.customerId);
}

Expand Down Expand Up @@ -232,6 +238,7 @@ public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeParcelable(cardPresent, flags);
dest.writeParcelable(fpx, flags);
dest.writeParcelable(ideal, flags);
dest.writeParcelable(sepaDebit, flags);
dest.writeString(customerId);
dest.writeInt(metadata == null ? -1 : metadata.size());
if (metadata != null) {
Expand All @@ -252,6 +259,7 @@ private PaymentMethod(@NonNull Parcel in) {
cardPresent = in.readParcelable(CardPresent.class.getClassLoader());
fpx = in.readParcelable(Fpx.class.getClassLoader());
ideal = in.readParcelable(Ideal.class.getClassLoader());
sepaDebit = in.readParcelable(SepaDebit.class.getClassLoader());
customerId = in.readString();
final int mapSize = in.readInt();
if (mapSize >= 0) {
Expand Down Expand Up @@ -292,11 +300,11 @@ public static final class Builder implements ObjectBuilder<PaymentMethod> {
private BillingDetails mBillingDetails;
private Map<String, String> mMetadata;
private String mCustomerId;

private Card mCard;
private CardPresent mCardPresent;
private Ideal mIdeal;
private Fpx mFpx;
private SepaDebit mSepaDebit;

@NonNull
public Builder setId(@Nullable String id) {
Expand Down Expand Up @@ -364,6 +372,12 @@ public Builder setFpx(@Nullable Fpx fpx) {
return this;
}

@NonNull
public Builder setSepaDebit(@Nullable SepaDebit sepaDebit) {
this.mSepaDebit = sepaDebit;
return this;
}

@NonNull
public PaymentMethod build() {
return new PaymentMethod(this);
Expand Down Expand Up @@ -1146,6 +1160,97 @@ public Fpx build() {
}
}

public static final class SepaDebit extends PaymentMethodTypeImpl {
private static final String FIELD_BANK_CODE = "bank_code";
private static final String FIELD_BRANCH_CODE = "branch_code";
private static final String FIELD_COUNTRY = "country";
private static final String FIELD_FINGERPRINT = "fingerprint";
private static final String FIELD_LAST4 = "last4";

@Nullable public final String bankCode;
@Nullable public final String branchCode;
@Nullable public final String country;
@Nullable public final String fingerprint;
@Nullable public final String last4;

SepaDebit(
@Nullable String bankCode,
@Nullable String branchCode,
@Nullable String country,
@Nullable String fingerprint,
@Nullable String last4
) {
super(Type.SepaDebit);
this.bankCode = bankCode;
this.branchCode = branchCode;
this.country = country;
this.fingerprint = fingerprint;
this.last4 = last4;
}

private SepaDebit(@NonNull Parcel parcel) {
this(
parcel.readString(),
parcel.readString(),
parcel.readString(),
parcel.readString(),
parcel.readString()
);
}

@Override
public int hashCode() {
return Objects.hash(bankCode, branchCode, country, fingerprint, last4);
}

@Override
public boolean equals(@Nullable Object other) {
if (this == other) {
return true;
} else if (other instanceof SepaDebit) {
return typedEquals((SepaDebit) other);
} else {
return false;
}
}

private boolean typedEquals(@NonNull SepaDebit other) {
return Objects.equals(bankCode, other.bankCode) &&
Objects.equals(branchCode, other.branchCode) &&
Objects.equals(country, other.country) &&
Objects.equals(fingerprint, other.fingerprint) &&
Objects.equals(last4, other.last4);
}

protected static final Parcelable.Creator<SepaDebit> CREATOR =
new Parcelable.Creator<SepaDebit>() {
@Override
public SepaDebit createFromParcel(@NonNull Parcel parcel) {
return new SepaDebit(parcel);
}

@Override
public SepaDebit[] newArray(int size) {
return new SepaDebit[size];
}
};

@Nullable
static SepaDebit fromJson(@Nullable JSONObject sepaDebit) {
if (sepaDebit == null) {
return null;
}

return new SepaDebit(
optString(sepaDebit, FIELD_BANK_CODE),
optString(sepaDebit, FIELD_BRANCH_CODE),
optString(sepaDebit, FIELD_COUNTRY),
optString(sepaDebit, FIELD_FINGERPRINT),
optString(sepaDebit, FIELD_LAST4)
);
}
}

private abstract static class PaymentMethodTypeImpl extends StripeModel
implements Parcelable {
@NonNull public final Type type;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.stripe.android.model

import java.util.UUID
import java.util.concurrent.ThreadLocalRandom
import org.json.JSONObject

internal object PaymentMethodFixtures {
@JvmField
Expand Down Expand Up @@ -62,6 +63,41 @@ internal object PaymentMethodFixtures {
.build())
.build()

@JvmField
val SEPA_DEBIT_PAYMENT_METHOD = PaymentMethod.fromJson(JSONObject(
"""
{
"id": "pm_1FSQaJCR",
"object": "payment_method",
"billing_details": {
"address": {
"city": null,
"country": null,
"line1": null,
"line2": null,
"postal_code": null,
"state": null
},
"email": "jrosen@example.com",
"name": "Jenny Rosen",
"phone": null
},
"created": 1570809799,
"customer": null,
"livemode": false,
"metadata": {},
"sepa_debit": {
"bank_code": "3704",
"branch_code": "",
"country": "DE",
"fingerprint": "vIZc7Ywn0",
"last4": "3000"
},
"type": "sepa_debit"
}
""".trimIndent()
))!!

@JvmField
val CARD_PAYMENT_METHODS = listOf(
PaymentMethod.Builder()
Expand Down
28 changes: 28 additions & 0 deletions stripe/src/test/java/com/stripe/android/model/PaymentMethodTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,34 @@ class PaymentMethodTest {
PaymentMethod.fromJson(PM_FPX_JSON))
}

@Test
fun toJson_withSepaDebit_shouldCreateExpectedObject() {
assertEquals(PaymentMethodFixtures.SEPA_DEBIT_PAYMENT_METHOD,
PaymentMethod.Builder()
.setType(PaymentMethod.Type.SepaDebit.code)
.setId("pm_1FSQaJCR")
.setLiveMode(false)
.setCreated(1570809799L)
.setSepaDebit(
PaymentMethod.SepaDebit(
"3704",
null,
"DE",
"vIZc7Ywn0",
"3000"
)
)
.setBillingDetails(
PaymentMethod.BillingDetails.Builder()
.setName("Jenny Rosen")
.setEmail("jrosen@example.com")
.setAddress(Address.Builder().build())
.build()
)
.build()
)
}

@Test
fun equals_withEqualPaymentMethods_shouldReturnTrue() {
assertEquals(PaymentMethodFixtures.CARD_PAYMENT_METHOD,
Expand Down

0 comments on commit 1ef1c6c

Please sign in to comment.