diff --git a/stripe/src/main/java/com/stripe/android/model/BankAccount.kt b/stripe/src/main/java/com/stripe/android/model/BankAccount.kt index 5d4cc64aac6..11ce6530c09 100644 --- a/stripe/src/main/java/com/stripe/android/model/BankAccount.kt +++ b/stripe/src/main/java/com/stripe/android/model/BankAccount.kt @@ -1,7 +1,9 @@ package com.stripe.android.model +import android.os.Parcelable import androidx.annotation.Size import androidx.annotation.StringDef +import kotlinx.android.parcel.Parcelize import org.json.JSONObject /** @@ -10,6 +12,7 @@ import org.json.JSONObject * [the Stripe * documentation.](https://stripe.com/docs/api/java#create_bank_account_token) */ +@Parcelize data class BankAccount internal constructor( val accountNumber: String?, val accountHolderName: String?, @@ -23,7 +26,7 @@ data class BankAccount internal constructor( val fingerprint: String?, val last4: String?, val routingNumber: String? -) : StripeParamsModel { +) : StripeParamsModel, Parcelable { @Retention(AnnotationRetention.SOURCE) @StringDef(BankAccountType.COMPANY, BankAccountType.INDIVIDUAL) diff --git a/stripe/src/main/java/com/stripe/android/model/Customer.kt b/stripe/src/main/java/com/stripe/android/model/Customer.kt index 66c7522729c..4c6b144557c 100644 --- a/stripe/src/main/java/com/stripe/android/model/Customer.kt +++ b/stripe/src/main/java/com/stripe/android/model/Customer.kt @@ -3,6 +3,7 @@ package com.stripe.android.model import com.stripe.android.model.StripeJsonUtils.optBoolean import com.stripe.android.model.StripeJsonUtils.optInteger import com.stripe.android.model.StripeJsonUtils.optString +import kotlinx.android.parcel.Parcelize import org.json.JSONArray import org.json.JSONException import org.json.JSONObject @@ -10,7 +11,8 @@ import org.json.JSONObject /** * Model for a Stripe Customer object */ -data class Customer private constructor( +@Parcelize +data class Customer internal constructor( val id: String?, val defaultSource: String?, val shippingInformation: ShippingInformation?, diff --git a/stripe/src/main/java/com/stripe/android/model/CustomerSource.kt b/stripe/src/main/java/com/stripe/android/model/CustomerSource.kt index 11b53467b7f..1bf1cd77e66 100644 --- a/stripe/src/main/java/com/stripe/android/model/CustomerSource.kt +++ b/stripe/src/main/java/com/stripe/android/model/CustomerSource.kt @@ -1,12 +1,14 @@ package com.stripe.android.model import com.stripe.android.model.StripeJsonUtils.optString +import kotlinx.android.parcel.Parcelize import org.json.JSONObject /** * Model of the "data" object inside a [Customer] "source" object. */ -data class CustomerSource private constructor( +@Parcelize +data class CustomerSource internal constructor( private val stripePaymentSource: StripePaymentSource ) : StripeModel(), StripePaymentSource { diff --git a/stripe/src/main/java/com/stripe/android/model/PaymentIntent.kt b/stripe/src/main/java/com/stripe/android/model/PaymentIntent.kt index 400bf8795a3..fff63df7ecb 100644 --- a/stripe/src/main/java/com/stripe/android/model/PaymentIntent.kt +++ b/stripe/src/main/java/com/stripe/android/model/PaymentIntent.kt @@ -1,11 +1,14 @@ package com.stripe.android.model import android.net.Uri +import android.os.Parcelable import com.stripe.android.model.StripeJsonUtils.optBoolean import com.stripe.android.model.StripeJsonUtils.optCurrency import com.stripe.android.model.StripeJsonUtils.optLong import com.stripe.android.model.StripeJsonUtils.optMap import com.stripe.android.model.StripeJsonUtils.optString +import kotlinx.android.parcel.Parcelize +import kotlinx.android.parcel.RawValue import org.json.JSONException import org.json.JSONObject @@ -15,6 +18,7 @@ import org.json.JSONObject * - [Payment Intents Overview](https://stripe.com/docs/payments/payment-intents) * - [PaymentIntents API](https://stripe.com/docs/api/payment_intents) */ +@Parcelize data class PaymentIntent internal constructor( /** * @return Unique identifier for the object. @@ -103,7 +107,7 @@ data class PaymentIntent internal constructor( * @return If present, this property tells you what actions you need to take in order for your * customer to fulfill a payment using the provided source. */ - val nextAction: Map?, + val nextAction: Map?, /** * @return ID of the payment method (a PaymentMethod, Card, BankAccount, or saved Source object) @@ -186,7 +190,8 @@ data class PaymentIntent internal constructor( * * See [last_payment_error](https://stripe.com/docs/api/payment_intents/object#payment_intent_object-last_payment_error). */ - data class Error private constructor( + @Parcelize + data class Error internal constructor( /** * For card errors, the ID of the failed charge. @@ -233,7 +238,7 @@ data class PaymentIntent internal constructor( * The type of error returned. */ val type: Type? - ) { + ) : Parcelable { enum class Type(val code: String) { ApiConnectionError("api_connection_error"), ApiError("api_error"), diff --git a/stripe/src/main/java/com/stripe/android/model/SetupIntent.kt b/stripe/src/main/java/com/stripe/android/model/SetupIntent.kt index bcbdb474b6c..a0dbce58fd1 100644 --- a/stripe/src/main/java/com/stripe/android/model/SetupIntent.kt +++ b/stripe/src/main/java/com/stripe/android/model/SetupIntent.kt @@ -1,8 +1,11 @@ package com.stripe.android.model import android.net.Uri +import android.os.Parcelable import com.stripe.android.model.StripeJsonUtils.optMap import com.stripe.android.model.StripeJsonUtils.optString +import kotlinx.android.parcel.Parcelize +import kotlinx.android.parcel.RawValue import org.json.JSONException import org.json.JSONObject @@ -10,7 +13,8 @@ import org.json.JSONObject * A SetupIntent guides you through the process of setting up a customer's payment credentials for * future payments. */ -data class SetupIntent private constructor( +@Parcelize +data class SetupIntent internal constructor( /** * @return Unique identifier for the object. @@ -50,7 +54,7 @@ data class SetupIntent private constructor( */ override val isLiveMode: Boolean, - private val nextAction: Map?, + private val nextAction: Map?, override val nextActionType: StripeIntent.NextActionType? = null, @@ -137,7 +141,8 @@ data class SetupIntent private constructor( * * See [last_setup_error](https://stripe.com/docs/api/setup_intents/object#setup_intent_object-last_setup_error). */ - data class Error private constructor( + @Parcelize + data class Error internal constructor( /** * For some errors that could be handled programmatically, a short string indicating the @@ -179,7 +184,7 @@ data class SetupIntent private constructor( * The type of error returned. */ val type: Type? - ) { + ) : Parcelable { enum class Type(val code: String) { ApiConnectionError("api_connection_error"), ApiError("api_error"), diff --git a/stripe/src/main/java/com/stripe/android/model/Source.kt b/stripe/src/main/java/com/stripe/android/model/Source.kt index 4cb6a67e2bf..ac260b13659 100644 --- a/stripe/src/main/java/com/stripe/android/model/Source.kt +++ b/stripe/src/main/java/com/stripe/android/model/Source.kt @@ -1,11 +1,14 @@ package com.stripe.android.model +import android.os.Parcelable import androidx.annotation.Size import androidx.annotation.StringDef import com.stripe.android.model.Source.SourceFlow import com.stripe.android.model.Source.SourceType import com.stripe.android.model.StripeJsonUtils.optLong import com.stripe.android.model.StripeJsonUtils.optString +import kotlinx.android.parcel.Parcelize +import kotlinx.android.parcel.RawValue import org.json.JSONException import org.json.JSONObject @@ -14,6 +17,7 @@ import org.json.JSONObject * * See [Sources API Reference](https://stripe.com/docs/api/sources/object). */ +@Parcelize data class Source internal constructor( /** * Unique identifier for the object. @@ -95,7 +99,8 @@ data class Source internal constructor( @param:SourceStatus @field:SourceStatus @get:SourceStatus val status: String? = null, - val sourceTypeData: Map? = null, + val sourceTypeData: Map? = null, + val sourceTypeModel: StripeSourceTypeModel? = null, /** @@ -138,7 +143,7 @@ data class Source internal constructor( * every time you charge the source. */ val statementDescriptor: String? = null -) : StripeModel(), StripePaymentSource { +) : StripeModel(), StripePaymentSource, Parcelable { val weChat: WeChat get() { diff --git a/stripe/src/main/java/com/stripe/android/model/SourceCardData.kt b/stripe/src/main/java/com/stripe/android/model/SourceCardData.kt index 9037fa5444a..1324ee4a0be 100644 --- a/stripe/src/main/java/com/stripe/android/model/SourceCardData.kt +++ b/stripe/src/main/java/com/stripe/android/model/SourceCardData.kt @@ -4,14 +4,14 @@ import androidx.annotation.StringDef import androidx.annotation.VisibleForTesting import com.stripe.android.model.StripeJsonUtils.optInteger import com.stripe.android.model.StripeJsonUtils.optString -import org.json.JSONException +import kotlinx.android.parcel.Parcelize import org.json.JSONObject /** * Model for data contained in the SourceTypeData of a Card Source. */ -@Suppress("MemberVisibilityCanBePrivate") -data class SourceCardData private constructor( +@Parcelize +data class SourceCardData internal constructor( val addressLine1Check: String?, val addressZipCheck: String?, @@ -50,101 +50,6 @@ data class SourceCardData private constructor( } } - private class Builder : StripeSourceTypeModel.BaseBuilder() { - var addressLine1Check: String? = null - var addressZipCheck: String? = null - @Card.CardBrand - var brand: String? = null - var country: String? = null - var cvcCheck: String? = null - var dynamicLast4: String? = null - var expiryMonth: Int? = null - var expiryYear: Int? = null - @Card.FundingType - var funding: String? = null - var last4: String? = null - @ThreeDSecureStatus - var threeDSecureStatus: String? = null - var tokenizationMethod: String? = null - - fun setAddressLine1Check(addressLine1Check: String?): Builder { - this.addressLine1Check = addressLine1Check - return this - } - - fun setAddressZipCheck(addressZipCheck: String?): Builder { - this.addressZipCheck = addressZipCheck - return this - } - - fun setBrand(brand: String?): Builder { - this.brand = brand - return this - } - - fun setCountry(country: String?): Builder { - this.country = country - return this - } - - fun setCvcCheck(cvcCheck: String?): Builder { - this.cvcCheck = cvcCheck - return this - } - - fun setDynamicLast4(dynamicLast4: String?): Builder { - this.dynamicLast4 = dynamicLast4 - return this - } - - fun setExpiryMonth(expiryMonth: Int?): Builder { - this.expiryMonth = expiryMonth - return this - } - - fun setExpiryYear(expiryYear: Int?): Builder { - this.expiryYear = expiryYear - return this - } - - fun setFunding(funding: String?): Builder { - this.funding = funding - return this - } - - fun setLast4(last4: String?): Builder { - this.last4 = last4 - return this - } - - fun setThreeDSecureStatus(threeDSecureStatus: String?): Builder { - this.threeDSecureStatus = threeDSecureStatus - return this - } - - fun setTokenizationMethod(tokenizationMethod: String?): Builder { - this.tokenizationMethod = tokenizationMethod - return this - } - - fun build(): SourceCardData { - return SourceCardData( - addressLine1Check = addressLine1Check, - addressZipCheck = addressZipCheck, - brand = brand, - country = country, - cvcCheck = cvcCheck, - dynamicLast4 = dynamicLast4, - expiryMonth = expiryMonth, - expiryYear = expiryYear, - funding = funding, - last4 = last4, - threeDSecureStatus = threeDSecureStatus, - tokenizationMethod = tokenizationMethod - ) - } - } - companion object { private const val FIELD_ADDRESS_LINE1_CHECK = "address_line1_check" private const val FIELD_ADDRESS_ZIP_CHECK = "address_zip_check" @@ -159,63 +64,34 @@ data class SourceCardData private constructor( private const val FIELD_THREE_D_SECURE = "three_d_secure" private const val FIELD_TOKENIZATION_METHOD = "tokenization_method" - private val STANDARD_FIELDS = setOf( - FIELD_ADDRESS_LINE1_CHECK, - FIELD_ADDRESS_ZIP_CHECK, - FIELD_BRAND, - FIELD_COUNTRY, - FIELD_CVC_CHECK, - FIELD_DYNAMIC_LAST4, - FIELD_EXP_MONTH, - FIELD_EXP_YEAR, - FIELD_FUNDING, - FIELD_LAST4, - FIELD_THREE_D_SECURE, - FIELD_TOKENIZATION_METHOD - ) - @JvmStatic fun fromJson(jsonObject: JSONObject?): SourceCardData? { if (jsonObject == null) { return null } - val cardData = Builder() - .setAddressLine1Check(optString(jsonObject, FIELD_ADDRESS_LINE1_CHECK)) - .setAddressZipCheck(optString(jsonObject, FIELD_ADDRESS_ZIP_CHECK)) - .setBrand(Card.asCardBrand(optString(jsonObject, FIELD_BRAND))) - .setCountry(optString(jsonObject, FIELD_COUNTRY)) - .setCvcCheck(optString(jsonObject, FIELD_CVC_CHECK)) - .setDynamicLast4(optString(jsonObject, FIELD_DYNAMIC_LAST4)) - .setExpiryMonth(optInteger(jsonObject, FIELD_EXP_MONTH)) - .setExpiryYear(optInteger(jsonObject, FIELD_EXP_YEAR)) - .setFunding(Card.asFundingType(optString(jsonObject, FIELD_FUNDING))) - .setLast4(optString(jsonObject, FIELD_LAST4)) - .setThreeDSecureStatus(asThreeDSecureStatus(optString(jsonObject, - FIELD_THREE_D_SECURE))) - .setTokenizationMethod(optString(jsonObject, FIELD_TOKENIZATION_METHOD)) - - jsonObjectToMapWithoutKeys(jsonObject, STANDARD_FIELDS)?.let { additionalFields -> - cardData.setAdditionalFields(additionalFields) - } - - return cardData.build() - } - - @JvmStatic - @VisibleForTesting - fun fromString(jsonString: String): SourceCardData? { - return try { - fromJson(JSONObject(jsonString)) - } catch (badJson: JSONException) { - null - } + return SourceCardData( + addressLine1Check = optString(jsonObject, FIELD_ADDRESS_LINE1_CHECK), + addressZipCheck = optString(jsonObject, FIELD_ADDRESS_ZIP_CHECK), + brand = Card.asCardBrand(optString(jsonObject, FIELD_BRAND)), + country = optString(jsonObject, FIELD_COUNTRY), + cvcCheck = optString(jsonObject, FIELD_CVC_CHECK), + dynamicLast4 = optString(jsonObject, FIELD_DYNAMIC_LAST4), + expiryMonth = optInteger(jsonObject, FIELD_EXP_MONTH), + expiryYear = optInteger(jsonObject, FIELD_EXP_YEAR), + funding = Card.asFundingType(optString(jsonObject, FIELD_FUNDING)), + last4 = optString(jsonObject, FIELD_LAST4), + threeDSecureStatus = asThreeDSecureStatus( + optString(jsonObject, FIELD_THREE_D_SECURE) + ), + tokenizationMethod = optString(jsonObject, FIELD_TOKENIZATION_METHOD) + ) } - @JvmStatic + @JvmSynthetic @VisibleForTesting @ThreeDSecureStatus - fun asThreeDSecureStatus(threeDSecureStatus: String?): String? { + internal fun asThreeDSecureStatus(threeDSecureStatus: String?): String? { if (StripeJsonUtils.nullIfNullOrEmpty(threeDSecureStatus) == null) { return null } diff --git a/stripe/src/main/java/com/stripe/android/model/SourceCodeVerification.kt b/stripe/src/main/java/com/stripe/android/model/SourceCodeVerification.kt index 49f978424a8..fcb78cebbe5 100644 --- a/stripe/src/main/java/com/stripe/android/model/SourceCodeVerification.kt +++ b/stripe/src/main/java/com/stripe/android/model/SourceCodeVerification.kt @@ -1,7 +1,9 @@ package com.stripe.android.model +import android.os.Parcelable import androidx.annotation.StringDef import com.stripe.android.model.StripeJsonUtils.optString +import kotlinx.android.parcel.Parcelize import org.json.JSONObject /** @@ -10,10 +12,11 @@ import org.json.JSONObject * * *Not* source code verification. */ -data class SourceCodeVerification private constructor( +@Parcelize +data class SourceCodeVerification internal constructor( val attemptsRemaining: Int, @param:Status @field:Status @get:Status val status: String? -) : StripeModel() { +) : StripeModel(), Parcelable { // Note: these are the same as the values for the @Redirect.Status StringDef. // They don't have to stay the same forever, so they are redefined here. diff --git a/stripe/src/main/java/com/stripe/android/model/SourceOrder.kt b/stripe/src/main/java/com/stripe/android/model/SourceOrder.kt index 85881b7ef16..268028dbed3 100644 --- a/stripe/src/main/java/com/stripe/android/model/SourceOrder.kt +++ b/stripe/src/main/java/com/stripe/android/model/SourceOrder.kt @@ -1,6 +1,8 @@ package com.stripe.android.model +import android.os.Parcelable import com.stripe.android.model.SourceOrder.Item.Type +import kotlinx.android.parcel.Parcelize import org.json.JSONArray import org.json.JSONObject @@ -10,6 +12,7 @@ import org.json.JSONObject * * [API reference](https://stripe.com/docs/api/sources/object#source_object-source_order) */ +@Parcelize data class SourceOrder internal constructor( /** * A positive integer in the smallest currency unit (that is, 100 cents for $1.00, or 1 for ¥1, @@ -37,12 +40,13 @@ data class SourceOrder internal constructor( * The shipping address for the order. Present if the order is for goods to be shipped. */ val shipping: Shipping? = null -) { +) : Parcelable { /** * List of items constituting the order. * * [API reference](https://stripe.com/docs/api/sources/object#source_object-source_order-items) */ + @Parcelize data class Item internal constructor( /** * The type of this order item. Must be [Type.Sku], [Type.Tax], or [Type.Shipping]. @@ -69,7 +73,7 @@ data class SourceOrder internal constructor( * instances of the SKU to be ordered. */ val quantity: Int? = null - ) { + ) : Parcelable { enum class Type(private val code: String) { Sku("sku"), Tax("tax"), @@ -113,6 +117,7 @@ data class SourceOrder internal constructor( * * [API reference](https://stripe.com/docs/api/sources/object#source_object-source_order-shipping) */ + @Parcelize data class Shipping internal constructor( /** * Shipping address. @@ -140,7 +145,7 @@ data class SourceOrder internal constructor( * them with commas. */ val trackingNumber: String? = null - ) { + ) : Parcelable { internal companion object { private const val FIELD_ADDRESS = "address" private const val FIELD_CARRIER = "carrier" diff --git a/stripe/src/main/java/com/stripe/android/model/SourceOwner.kt b/stripe/src/main/java/com/stripe/android/model/SourceOwner.kt index 8bf19c38357..c3513fd0870 100644 --- a/stripe/src/main/java/com/stripe/android/model/SourceOwner.kt +++ b/stripe/src/main/java/com/stripe/android/model/SourceOwner.kt @@ -1,6 +1,8 @@ package com.stripe.android.model +import android.os.Parcelable import com.stripe.android.model.StripeJsonUtils.optString +import kotlinx.android.parcel.Parcelize import org.json.JSONException import org.json.JSONObject @@ -8,6 +10,7 @@ import org.json.JSONObject * Model for a [owner](https://stripe.com/docs/api#source_object-owner) object * in the Source api. */ +@Parcelize data class SourceOwner internal constructor( val address: Address?, val email: String?, @@ -17,7 +20,7 @@ data class SourceOwner internal constructor( val verifiedEmail: String?, val verifiedName: String?, val verifiedPhone: String? -) : StripeModel() { +) : StripeModel(), Parcelable { companion object { private const val VERIFIED = "verified_" diff --git a/stripe/src/main/java/com/stripe/android/model/SourceReceiver.kt b/stripe/src/main/java/com/stripe/android/model/SourceReceiver.kt index a9f39c123db..2100e5e5ae1 100644 --- a/stripe/src/main/java/com/stripe/android/model/SourceReceiver.kt +++ b/stripe/src/main/java/com/stripe/android/model/SourceReceiver.kt @@ -1,5 +1,7 @@ package com.stripe.android.model +import android.os.Parcelable +import kotlinx.android.parcel.Parcelize import org.json.JSONException import org.json.JSONObject @@ -8,12 +10,13 @@ import org.json.JSONObject * [receiver](https://stripe.com/docs/api/sources/object#source_object-receiver) object * in the Sources API. Present if the [Source] is a receiver. */ -data class SourceReceiver private constructor( +@Parcelize +data class SourceReceiver internal constructor( val address: String?, val amountCharged: Long, val amountReceived: Long, val amountReturned: Long -) : StripeModel() { +) : StripeModel(), Parcelable { companion object { private const val FIELD_ADDRESS = "address" diff --git a/stripe/src/main/java/com/stripe/android/model/SourceRedirect.kt b/stripe/src/main/java/com/stripe/android/model/SourceRedirect.kt index 1719f577c50..d7e6a863128 100644 --- a/stripe/src/main/java/com/stripe/android/model/SourceRedirect.kt +++ b/stripe/src/main/java/com/stripe/android/model/SourceRedirect.kt @@ -1,8 +1,10 @@ package com.stripe.android.model +import android.os.Parcelable import androidx.annotation.StringDef import androidx.annotation.VisibleForTesting import com.stripe.android.model.StripeJsonUtils.optString +import kotlinx.android.parcel.Parcelize import org.json.JSONException import org.json.JSONObject @@ -10,11 +12,12 @@ import org.json.JSONObject * Model for a [redirect](https://stripe.com/docs/api/sources/object#source_object-redirect) object * in the Sources API. */ -data class SourceRedirect private constructor( +@Parcelize +data class SourceRedirect internal constructor( val returnUrl: String?, @param:Status @field:Status @get:Status val status: String?, val url: String? -) : StripeModel() { +) : StripeModel(), Parcelable { @Retention(AnnotationRetention.SOURCE) @StringDef(Status.PENDING, Status.SUCCEEDED, Status.FAILED, Status.NOT_REQUIRED) diff --git a/stripe/src/main/java/com/stripe/android/model/SourceSepaDebitData.kt b/stripe/src/main/java/com/stripe/android/model/SourceSepaDebitData.kt index 7d1c7287e4c..0c230c038df 100644 --- a/stripe/src/main/java/com/stripe/android/model/SourceSepaDebitData.kt +++ b/stripe/src/main/java/com/stripe/android/model/SourceSepaDebitData.kt @@ -1,13 +1,13 @@ package com.stripe.android.model -import androidx.annotation.VisibleForTesting import com.stripe.android.model.StripeJsonUtils.optString -import org.json.JSONException +import kotlinx.android.parcel.Parcelize import org.json.JSONObject /** * Model for the SourceTypeData contained in a SEPA Debit Source object. */ +@Parcelize data class SourceSepaDebitData internal constructor( val bankCode: String?, val branchCode: String?, @@ -18,63 +18,6 @@ data class SourceSepaDebitData internal constructor( val mandateUrl: String? ) : StripeSourceTypeModel() { - private class Builder : StripeSourceTypeModel.BaseBuilder() { - var bankCode: String? = null - var branchCode: String? = null - var country: String? = null - var fingerPrint: String? = null - var last4: String? = null - var mandateReference: String? = null - var mandateUrl: String? = null - - internal fun setBankCode(bankCode: String?): Builder { - this.bankCode = bankCode - return this - } - - internal fun setBranchCode(branchCode: String?): Builder { - this.branchCode = branchCode - return this - } - - internal fun setCountry(country: String?): Builder { - this.country = country - return this - } - - internal fun setFingerPrint(fingerPrint: String?): Builder { - this.fingerPrint = fingerPrint - return this - } - - internal fun setLast4(last4: String?): Builder { - this.last4 = last4 - return this - } - - internal fun setMandateReference(mandateReference: String?): Builder { - this.mandateReference = mandateReference - return this - } - - internal fun setMandateUrl(mandateUrl: String?): Builder { - this.mandateUrl = mandateUrl - return this - } - - fun build(): SourceSepaDebitData { - return SourceSepaDebitData( - bankCode = bankCode, - branchCode = branchCode, - country = country, - fingerPrint = fingerPrint, - last4 = last4, - mandateReference = mandateReference, - mandateUrl = mandateUrl - ) - } - } - companion object { private const val FIELD_BANK_CODE = "bank_code" private const val FIELD_BRANCH_CODE = "branch_code" @@ -84,46 +27,21 @@ data class SourceSepaDebitData internal constructor( private const val FIELD_MANDATE_REFERENCE = "mandate_reference" private const val FIELD_MANDATE_URL = "mandate_url" - private val STANDARD_FIELDS = setOf( - FIELD_BANK_CODE, - FIELD_BRANCH_CODE, - FIELD_COUNTRY, - FIELD_FINGERPRINT, - FIELD_LAST4, - FIELD_MANDATE_REFERENCE, - FIELD_MANDATE_URL - ) - @JvmStatic fun fromJson(jsonObject: JSONObject?): SourceSepaDebitData? { if (jsonObject == null) { return null } - val sepaData = Builder() - .setBankCode(optString(jsonObject, FIELD_BANK_CODE)) - .setBranchCode(optString(jsonObject, FIELD_BRANCH_CODE)) - .setCountry(optString(jsonObject, FIELD_COUNTRY)) - .setFingerPrint(optString(jsonObject, FIELD_FINGERPRINT)) - .setLast4(optString(jsonObject, FIELD_LAST4)) - .setMandateReference(optString(jsonObject, FIELD_MANDATE_REFERENCE)) - .setMandateUrl(optString(jsonObject, FIELD_MANDATE_URL)) - - val nonStandardFields = - jsonObjectToMapWithoutKeys(jsonObject, STANDARD_FIELDS) - if (nonStandardFields != null) { - sepaData.setAdditionalFields(nonStandardFields) - } - return sepaData.build() - } - - @VisibleForTesting - internal fun fromString(jsonString: String): SourceSepaDebitData? { - return try { - fromJson(JSONObject(jsonString)) - } catch (badJson: JSONException) { - null - } + return SourceSepaDebitData( + bankCode = optString(jsonObject, FIELD_BANK_CODE), + branchCode = optString(jsonObject, FIELD_BRANCH_CODE), + country = optString(jsonObject, FIELD_COUNTRY), + fingerPrint = optString(jsonObject, FIELD_FINGERPRINT), + last4 = optString(jsonObject, FIELD_LAST4), + mandateReference = optString(jsonObject, FIELD_MANDATE_REFERENCE), + mandateUrl = optString(jsonObject, FIELD_MANDATE_URL) + ) } } } diff --git a/stripe/src/main/java/com/stripe/android/model/StripeModel.kt b/stripe/src/main/java/com/stripe/android/model/StripeModel.kt index 8c5ea02a6e8..5c514288731 100644 --- a/stripe/src/main/java/com/stripe/android/model/StripeModel.kt +++ b/stripe/src/main/java/com/stripe/android/model/StripeModel.kt @@ -1,11 +1,12 @@ package com.stripe.android.model +import android.os.Parcelable import org.json.JSONArray /** * Model for a Stripe API object. */ -abstract class StripeModel { +abstract class StripeModel : Parcelable { abstract override fun hashCode(): Int diff --git a/stripe/src/main/java/com/stripe/android/model/StripePaymentSource.kt b/stripe/src/main/java/com/stripe/android/model/StripePaymentSource.kt index 6db6e7a7a78..f745a6641d4 100644 --- a/stripe/src/main/java/com/stripe/android/model/StripePaymentSource.kt +++ b/stripe/src/main/java/com/stripe/android/model/StripePaymentSource.kt @@ -1,8 +1,10 @@ package com.stripe.android.model +import android.os.Parcelable + /** * Represents an object that has an ID field that can be used to create payments with Stripe. */ -interface StripePaymentSource { +interface StripePaymentSource : Parcelable { val id: String? } diff --git a/stripe/src/main/java/com/stripe/android/model/StripeSourceTypeModel.kt b/stripe/src/main/java/com/stripe/android/model/StripeSourceTypeModel.kt index b954f539eef..464b870a376 100644 --- a/stripe/src/main/java/com/stripe/android/model/StripeSourceTypeModel.kt +++ b/stripe/src/main/java/com/stripe/android/model/StripeSourceTypeModel.kt @@ -1,50 +1,5 @@ package com.stripe.android.model -import org.json.JSONArray -import org.json.JSONObject +import android.os.Parcelable -abstract class StripeSourceTypeModel : StripeModel() { - abstract class BaseBuilder { - var additionalFields: Map? = null - - fun setAdditionalFields(additionalFields: Map): BaseBuilder { - this.additionalFields = additionalFields - return this - } - } - - companion object { - /** - * Convert a [JSONObject] to a flat, string-keyed map. - * - * @param jsonObject the input [JSONObject] to be converted - * @param omitKeys a set of keys to be omitted from the map - * @return a [Map] representing the input, or `null` if the input is `null` - * or if the output would be an empty map. - */ - @JvmStatic - fun jsonObjectToMapWithoutKeys( - jsonObject: JSONObject?, - omitKeys: Set? - ): Map? { - if (jsonObject == null) { - return null - } - - val keysToOmit = omitKeys ?: emptySet() - val keys = jsonObject.names() ?: JSONArray() - return (0 until keys.length()) - .map { keys.getString(it) } - .filterNot { keysToOmit.contains(it) } - .mapNotNull { key -> - if (jsonObject.isNull(key)) { - null - } else { - key to jsonObject.opt(key) - } - } - .toMap() - .takeIf { it.isNotEmpty() } - } - } -} +abstract class StripeSourceTypeModel : StripeModel(), Parcelable diff --git a/stripe/src/main/java/com/stripe/android/model/Token.kt b/stripe/src/main/java/com/stripe/android/model/Token.kt index 5ce73ab2b09..cbbc826e329 100644 --- a/stripe/src/main/java/com/stripe/android/model/Token.kt +++ b/stripe/src/main/java/com/stripe/android/model/Token.kt @@ -3,6 +3,7 @@ package com.stripe.android.model import androidx.annotation.StringDef import com.stripe.android.model.Token.TokenType import java.util.Date +import kotlinx.android.parcel.Parcelize import org.json.JSONException import org.json.JSONObject @@ -11,7 +12,8 @@ import org.json.JSONObject * account details or personally identifiable information (PII), directly from your customers in a * secure manner. A Token representing this information is returned to you to use. */ -data class Token private constructor( +@Parcelize +data class Token internal constructor( /** * @return the Token id diff --git a/stripe/src/main/java/com/stripe/android/model/WeChat.kt b/stripe/src/main/java/com/stripe/android/model/WeChat.kt index e9a131b9749..865685590c3 100644 --- a/stripe/src/main/java/com/stripe/android/model/WeChat.kt +++ b/stripe/src/main/java/com/stripe/android/model/WeChat.kt @@ -1,10 +1,13 @@ package com.stripe.android.model +import android.os.Parcelable +import kotlinx.android.parcel.Parcelize import org.json.JSONObject /** * [WeChat Pay Payments with Sources](https://stripe.com/docs/sources/wechat-pay) */ +@Parcelize data class WeChat internal constructor( val statementDescriptor: String?, val appId: String?, @@ -15,7 +18,7 @@ data class WeChat internal constructor( val sign: String?, val timestamp: String?, val qrCodeUrl: String? = null -) : StripeModel() { +) : StripeModel(), Parcelable { internal companion object { private const val FIELD_APPID = "android_appId" private const val FIELD_NONCE = "android_nonceStr" diff --git a/stripe/src/test/java/com/stripe/android/model/StripeSourceTypeModelTest.kt b/stripe/src/test/java/com/stripe/android/model/StripeSourceTypeModelTest.kt deleted file mode 100644 index 756c7c2e9f0..00000000000 --- a/stripe/src/test/java/com/stripe/android/model/StripeSourceTypeModelTest.kt +++ /dev/null @@ -1,55 +0,0 @@ -package com.stripe.android.model - -import com.stripe.android.model.StripeSourceTypeModel.Companion.jsonObjectToMapWithoutKeys -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertFalse -import kotlin.test.assertNull -import org.json.JSONObject - -/** - * Test class for [StripeSourceTypeModel]. - */ -class StripeSourceTypeModelTest { - - @Test - fun jsonObjectToMapWithoutKeys_whenHasKeyInput_returnsMapOmittingKeys() { - val jsonObject = JSONObject() - .put("a_key", "a_value") - .put("b_key", "b_value") - .put("c_key", "c_value") - .put("d_key", "d_value") - - val omitKeys = setOf("a_key", "d_key") - - val resultMap = jsonObjectToMapWithoutKeys(jsonObject, omitKeys)!! - assertEquals(2, resultMap.size) - assertEquals("b_value", resultMap["b_key"]) - assertEquals("c_value", resultMap["c_key"]) - assertFalse(resultMap.containsKey("a_key")) - assertFalse(resultMap.containsKey("d_key")) - } - - @Test - fun jsonObjectToMapWithoutKeys_whenAllKeysGiven_returnsNull() { - val jsonObject = JSONObject() - .put("a_key", "a_value") - .put("b_key", "b_value") - - val omitKeys = setOf("a_key", "b_key") - val resultMap = jsonObjectToMapWithoutKeys(jsonObject, omitKeys) - assertNull(resultMap) - } - - @Test - fun jsonObjectToMapWithoutKeys_whenOtherKeysGiven_returnsFullMap() { - val jsonObject = JSONObject() - .put("a_key", "a_value") - .put("b_key", "b_value") - - val omitKeys = setOf("c_key", "d_key") - val resultMap = jsonObjectToMapWithoutKeys(jsonObject, omitKeys)!! - assertEquals("a_value", resultMap["a_key"]) - assertEquals("b_value", resultMap["b_key"]) - } -}