diff --git a/stripe/src/main/java/com/stripe/android/model/PaymentMethod.java b/stripe/src/main/java/com/stripe/android/model/PaymentMethod.java index 2f2d56836c0..3198d001ea1 100644 --- a/stripe/src/main/java/com/stripe/android/model/PaymentMethod.java +++ b/stripe/src/main/java/com/stripe/android/model/PaymentMethod.java @@ -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; @@ -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"), @@ -135,6 +137,7 @@ private PaymentMethod(@NonNull Builder builder) { cardPresent = builder.mCardPresent; fpx = builder.mFpx; ideal = builder.mIdeal; + sepaDebit = builder.mSepaDebit; } /** @@ -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(); @@ -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); } @@ -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) { @@ -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) { @@ -292,11 +300,11 @@ public static final class Builder implements ObjectBuilder { private BillingDetails mBillingDetails; private Map 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) { @@ -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); @@ -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 CREATOR = + new Parcelable.Creator() { + @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; diff --git a/stripe/src/test/java/com/stripe/android/model/PaymentMethodFixtures.kt b/stripe/src/test/java/com/stripe/android/model/PaymentMethodFixtures.kt index cf46ca79670..fd330ab5da9 100644 --- a/stripe/src/test/java/com/stripe/android/model/PaymentMethodFixtures.kt +++ b/stripe/src/test/java/com/stripe/android/model/PaymentMethodFixtures.kt @@ -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 @@ -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() diff --git a/stripe/src/test/java/com/stripe/android/model/PaymentMethodTest.kt b/stripe/src/test/java/com/stripe/android/model/PaymentMethodTest.kt index 5a62faf026f..c0d64da94fd 100644 --- a/stripe/src/test/java/com/stripe/android/model/PaymentMethodTest.kt +++ b/stripe/src/test/java/com/stripe/android/model/PaymentMethodTest.kt @@ -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,