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 178f8ae1d6b..bf00647bf2c 100644 --- a/stripe/src/main/java/com/stripe/android/model/Source.kt +++ b/stripe/src/main/java/com/stripe/android/model/Source.kt @@ -131,7 +131,13 @@ data class Source internal constructor( * Information about the items and shipping associated with the source. Required for * transactional credit (for example Klarna) sources before you can charge it. */ - val sourceOrder: SourceOrder? = null + val sourceOrder: SourceOrder? = null, + + /** + * Extra information about a source. This will appear on your customer’s statement + * every time you charge the source. + */ + val statementDescriptor: String? = null ) : StripeModel(), StripePaymentSource { val weChat: WeChat @@ -223,6 +229,7 @@ data class Source internal constructor( private const val FIELD_RECEIVER: String = "receiver" private const val FIELD_REDIRECT: String = "redirect" private const val FIELD_SOURCE_ORDER: String = "source_order" + private const val FIELD_STATEMENT_DESCRIPTOR: String = "statement_descriptor" private const val FIELD_STATUS: String = "status" private const val FIELD_TYPE: String = "type" private const val FIELD_USAGE: String = "usage" @@ -303,6 +310,10 @@ data class Source internal constructor( redirect = optStripeJsonModel( jsonObject, FIELD_REDIRECT, SourceRedirect::class.java ), + sourceOrder = jsonObject.optJSONObject(FIELD_SOURCE_ORDER)?.let { + SourceOrder.fromJson(it) + }, + statementDescriptor = optString(jsonObject, FIELD_STATEMENT_DESCRIPTOR), status = asSourceStatus(optString(jsonObject, FIELD_STATUS)), sourceTypeData = sourceTypeData, sourceTypeModel = sourceTypeModel, @@ -313,9 +324,6 @@ data class Source internal constructor( WeChat.fromJson(jsonObject.optJSONObject(FIELD_WECHAT) ?: JSONObject()) } else { null - }, - sourceOrder = jsonObject.optJSONObject(FIELD_SOURCE_ORDER)?.let { - SourceOrder.fromJson(it) } ) } diff --git a/stripe/src/test/java/com/stripe/android/model/CustomerFixtures.kt b/stripe/src/test/java/com/stripe/android/model/CustomerFixtures.kt index d946abc4886..4403e828c85 100644 --- a/stripe/src/test/java/com/stripe/android/model/CustomerFixtures.kt +++ b/stripe/src/test/java/com/stripe/android/model/CustomerFixtures.kt @@ -4,7 +4,6 @@ import org.json.JSONObject internal object CustomerFixtures { - @JvmField val CUSTOMER_JSON = JSONObject( """ { @@ -22,7 +21,6 @@ internal object CustomerFixtures { """.trimIndent() ) - @JvmField val CUSTOMER_WITH_SHIPPING = Customer.fromJson(JSONObject( """ { @@ -54,10 +52,8 @@ internal object CustomerFixtures { """.trimIndent() ))!! - @JvmField val CUSTOMER = Customer.fromJson(CUSTOMER_JSON)!! - @JvmField val OTHER_CUSTOMER = Customer.fromJson(JSONObject( """ { @@ -77,7 +73,6 @@ internal object CustomerFixtures { """.trimIndent() ))!! - @JvmField val EPHEMERAL_KEY_FIRST = JSONObject( """ { @@ -95,7 +90,6 @@ internal object CustomerFixtures { """.trimIndent() ) - @JvmField val EPHEMERAL_KEY_SECOND = JSONObject( """ { diff --git a/stripe/src/test/java/com/stripe/android/model/CustomerSourceTest.kt b/stripe/src/test/java/com/stripe/android/model/CustomerSourceTest.kt index ad721f19870..0db7c40459b 100644 --- a/stripe/src/test/java/com/stripe/android/model/CustomerSourceTest.kt +++ b/stripe/src/test/java/com/stripe/android/model/CustomerSourceTest.kt @@ -1,7 +1,7 @@ package com.stripe.android.model import com.stripe.android.model.CardTest.Companion.JSON_CARD_USD -import com.stripe.android.model.SourceTest.Companion.EXAMPLE_JSON_SOURCE_WITHOUT_NULLS +import com.stripe.android.model.SourceFixtures.CUSTOMER_SOURCE_CARD import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertNotNull @@ -36,15 +36,13 @@ class CustomerSourceTest { @Test fun fromJson_whenSource_createsCustomerSourceData() { - val sourceData = CustomerSource.fromJson(EXAMPLE_JSON_SOURCE_WITHOUT_NULLS) - assertNotNull(sourceData) - assertNotNull(sourceData.asSource()) - assertEquals("src_19t3xKBZqEXluyI4uz2dxAfQ", sourceData.id) + assertNotNull(CUSTOMER_SOURCE_CARD.asSource()) + assertEquals("src_19t3xKBZqEXluyI4uz2dxAfQ", CUSTOMER_SOURCE_CARD.id) } @Test fun fromExampleJsonSource_toJson_createsSameObject() { - assertNotNull(CustomerSource.fromJson(EXAMPLE_JSON_SOURCE_WITHOUT_NULLS)) + assertNotNull(CUSTOMER_SOURCE_CARD) } @Test diff --git a/stripe/src/test/java/com/stripe/android/model/CustomerTest.kt b/stripe/src/test/java/com/stripe/android/model/CustomerTest.kt index b9c923930ea..3800ac088c6 100644 --- a/stripe/src/test/java/com/stripe/android/model/CustomerTest.kt +++ b/stripe/src/test/java/com/stripe/android/model/CustomerTest.kt @@ -6,7 +6,6 @@ import kotlin.test.assertEquals import kotlin.test.assertFalse import kotlin.test.assertNotNull import kotlin.test.assertNull -import kotlin.test.assertTrue import org.json.JSONException import org.json.JSONObject @@ -63,28 +62,27 @@ class CustomerTest { private fun createTestCustomerObjectWithApplePaySource(): String { val rawJsonCustomer = CustomerFixtures.CUSTOMER_JSON val sourcesObject = rawJsonCustomer.getJSONObject("sources") - val sourcesArray = sourcesObject.getJSONArray("data") - sourcesObject.put("total_count", 5) - sourcesArray.put(SourceFixtures.APPLE_PAY) - - val manipulatedCard = JSONObject(JSON_CARD_USD.toString()) - manipulatedCard.put("id", "card_id55555") - manipulatedCard.put("tokenization_method", "apple_pay") - - // Note that we don't yet explicitly support bitcoin sources, but this data is - // convenient for the test because it is not an apple pay source. - sourcesArray.put(SourceTest.EXAMPLE_JSON_SOURCE_WITHOUT_NULLS) - sourcesArray.put(SourceFixtures.ALIPAY_JSON) - sourcesArray.put(JSONObject(JSON_CARD_USD.toString())) - sourcesArray.put(manipulatedCard) + val sourcesArray = sourcesObject.getJSONArray("data").apply { + put(SourceFixtures.APPLE_PAY) + + // Note that we don't yet explicitly support bitcoin sources, but this data is + // convenient for the test because it is not an apple pay source. + put(SourceFixtures.CUSTOMER_SOURCE_CARD_JSON) + put(SourceFixtures.ALIPAY_JSON) + put(JSONObject(JSON_CARD_USD.toString())) + put(JSONObject(JSON_CARD_USD.toString()).apply { + put("id", "card_id55555") + put("tokenization_method", "apple_pay") + }) + } + sourcesObject.put("data", sourcesArray) + sourcesObject.put("total_count", 5) rawJsonCustomer.put("sources", sourcesObject) // Verify JSON manipulation - assertTrue(rawJsonCustomer.has("sources")) - assertTrue(rawJsonCustomer.getJSONObject("sources").has("data")) assertEquals(5, rawJsonCustomer.getJSONObject("sources").getJSONArray("data").length()) diff --git a/stripe/src/test/java/com/stripe/android/model/SourceFixtures.kt b/stripe/src/test/java/com/stripe/android/model/SourceFixtures.kt index 8450d2c2dbd..a4d3caa8f93 100644 --- a/stripe/src/test/java/com/stripe/android/model/SourceFixtures.kt +++ b/stripe/src/test/java/com/stripe/android/model/SourceFixtures.kt @@ -305,11 +305,165 @@ internal object SourceFixtures { "livemode": false, "metadata": {}, "source_order": $SOURCE_ORDER_JSON, - "statement_descriptor": null, + "statement_descriptor": "WIDGET FACTORY", "status": "pending", "type": "klarna", "usage": "single_use" } """.trimIndent() ))) + + internal val CUSTOMER_SOURCE_CARD_JSON = JSONObject( + """ + { + "id": "src_19t3xKBZqEXluyI4uz2dxAfQ", + "object": "source", + "amount": 1000, + "client_secret": "src_client_secret_of43INi1HteJwXVe3djAUosN", + "code_verification": { + "attempts_remaining": 3, + "status": "pending" + }, + "created": 1488499654, + "currency": "usd", + "flow": "receiver", + "livemode": false, + "metadata": {}, + "owner": { + "verified_phone": "4158675309", + "address": { + "country": "US", + "city": "San Francisco", + "state": "CA", + "postal_code": "94107", + "line2": "#345", + "line1": "123 Market St" + }, + "phone": "4158675309", + "name": "Jenny Rosen", + "verified_name": "Jenny Rosen", + "verified_email": "jenny.rosen@example.com", + "verified_address": { + "country": "US", + "city": "San Francisco", + "state": "CA", + "postal_code": "94107", + "line2": "#345", + "line1": "123 Market St" + }, + "email": "jenny.rosen@example.com" + }, + "redirect": { + "return_url": "https://google.com", + "url": "examplecompany://redirect-link", + "status": "succeeded" + }, + "receiver": { + "address": "test_1MBhWS3uv4ynCfQXF3xQjJkzFPukr4K56N", + "amount_charged": 0, + "amount_received": 0, + "amount_returned": 0 + }, + "status": "pending", + "type": "card", + "usage": "single_use", + "card": { + "address_zip_check": "unchecked", + "tokenization_method": "apple_pay", + "country": "US", + "last4": "4242", + "funding": "credit", + "cvc_check": "unchecked", + "exp_month": 12, + "exp_year": 2050, + "address_line1_check": "unchecked", + "three_d_secure": "optional", + "dynamic_last4": "4242", + "brand": "Visa" + } + } + """.trimIndent() + ) + + internal val CUSTOMER_SOURCE_CARD = requireNotNull( + CustomerSource.fromJson(CUSTOMER_SOURCE_CARD_JSON) + ) + + internal const val DOGE_COIN = "dogecoin" + + internal val EXAMPLE_JSON_SOURCE_CUSTOM_TYPE = JSONObject( + """ + { + "id": "src_19t3xKBZqEXluyI4uz2dxAfQ", + "object": "source", + "amount": 1000, + "client_secret": "src_client_secret_of43INi1HteJwXVe3djAUosN", + "code_verification": { + "attempts_remaining": 3, + "status": "pending" + }, + "created": 1488499654, + "currency": "usd", + "flow": "receiver", + "livemode": false, + "metadata": {}, + "owner": { + "verified_phone": "4158675309", + "address": { + "country": "US", + "city": "San Francisco", + "state": "CA", + "postal_code": "94107", + "line2": "#345", + "line1": "123 Market St" + }, + "phone": "4158675309", + "name": "Jenny Rosen", + "verified_name": "Jenny Rosen", + "verified_email": "jenny.rosen@example.com", + "verified_address": { + "country": "US", + "city": "San Francisco", + "state": "CA", + "postal_code": "94107", + "line2": "#345", + "line1": "123 Market St" + }, + "email": "jenny.rosen@example.com" + }, + "redirect": { + "return_url": "https://google.com", + "url": "examplecompany://redirect-link", + "status": "succeeded" + }, + "receiver": { + "address": "test_1MBhWS3uv4ynCfQXF3xQjJkzFPukr4K56N", + "amount_charged": 0, + "amount_received": 0, + "amount_returned": 0 + }, + "status": "pending", + "type": "dogecoin", + "usage": "single_use", + "dogecoin": { + "address": "test_1MBhWS3uv4ynCfQXF3xQjJkzFPukr4K56N", + "amount": 2371000, + "amount_charged": 0, + "amount_received": 0, + "amount_returned": 0, + "uri": "dogecoin:test_1MBhWS3uv4ynCfQXF3xQjJkzFPukr4K56N?amount=0.02371000" + } + } + """.trimIndent() + ) + + internal val DELETED_CARD_JSON = JSONObject( + """ + { + "id": "card_1ELdAlCRMbs6FrXfNbmZEOb7", + "object": "card", + "deleted": true + } + """.trimIndent() + ) } diff --git a/stripe/src/test/java/com/stripe/android/model/SourceTest.kt b/stripe/src/test/java/com/stripe/android/model/SourceTest.kt index 5b7ae103f5b..fb1b835094c 100644 --- a/stripe/src/test/java/com/stripe/android/model/SourceTest.kt +++ b/stripe/src/test/java/com/stripe/android/model/SourceTest.kt @@ -1,11 +1,14 @@ package com.stripe.android.model +import com.stripe.android.model.SourceFixtures.CUSTOMER_SOURCE_CARD_JSON +import com.stripe.android.model.SourceFixtures.DELETED_CARD_JSON +import com.stripe.android.model.SourceFixtures.DOGE_COIN +import com.stripe.android.model.SourceFixtures.EXAMPLE_JSON_SOURCE_CUSTOM_TYPE import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertNotNull import kotlin.test.assertNull import kotlin.test.assertTrue -import org.json.JSONObject /** * Test class for [Source] model. @@ -13,7 +16,7 @@ import org.json.JSONObject class SourceTest { @Test fun fromJsonStringWithoutNulls_isNotNull() { - assertNotNull(Source.fromJson(EXAMPLE_JSON_SOURCE_WITHOUT_NULLS)) + assertNotNull(Source.fromJson(CUSTOMER_SOURCE_CARD_JSON)) } @Test @@ -59,162 +62,15 @@ class SourceTest { } @Test - fun fromJson_withSourceOrder() { + fun fromJson_withSourceOrderAndStatementDescriptor() { assertEquals( SourceOrderFixtures.SOURCE_ORDER, SourceFixtures.SOURCE_WITH_SOURCE_ORDER.sourceOrder ) - } - - internal companion object { - internal val EXAMPLE_JSON_SOURCE_WITHOUT_NULLS = JSONObject( - """ - { - "id": "src_19t3xKBZqEXluyI4uz2dxAfQ", - "object": "source", - "amount": 1000, - "client_secret": "src_client_secret_of43INi1HteJwXVe3djAUosN", - "code_verification": { - "attempts_remaining": 3, - "status": "pending" - }, - "created": 1488499654, - "currency": "usd", - "flow": "receiver", - "livemode": false, - "metadata": {}, - "owner": { - "verified_phone": "4158675309", - "address": { - "country": "US", - "city": "San Francisco", - "state": "CA", - "postal_code": "94107", - "line2": "#345", - "line1": "123 Market St" - }, - "phone": "4158675309", - "name": "Jenny Rosen", - "verified_name": "Jenny Rosen", - "verified_email": "jenny.rosen@example.com", - "verified_address": { - "country": "US", - "city": "San Francisco", - "state": "CA", - "postal_code": "94107", - "line2": "#345", - "line1": "123 Market St" - }, - "email": "jenny.rosen@example.com" - }, - "redirect": { - "return_url": "https://google.com", - "url": "examplecompany://redirect-link", - "status": "succeeded" - }, - "receiver": { - "address": "test_1MBhWS3uv4ynCfQXF3xQjJkzFPukr4K56N", - "amount_charged": 0, - "amount_received": 0, - "amount_returned": 0 - }, - "status": "pending", - "type": "card", - "usage": "single_use", - "card": { - "address_zip_check": "unchecked", - "tokenization_method": "apple_pay", - "country": "US", - "last4": "4242", - "funding": "credit", - "cvc_check": "unchecked", - "exp_month": 12, - "exp_year": 2050, - "address_line1_check": "unchecked", - "three_d_secure": "optional", - "dynamic_last4": "4242", - "brand": "Visa" - } - } - """.trimIndent() - ) - - private const val DOGE_COIN = "dogecoin" - private val EXAMPLE_JSON_SOURCE_CUSTOM_TYPE = JSONObject( - """ - { - "id": "src_19t3xKBZqEXluyI4uz2dxAfQ", - "object": "source", - "amount": 1000, - "client_secret": "src_client_secret_of43INi1HteJwXVe3djAUosN", - "code_verification": { - "attempts_remaining": 3, - "status": "pending" - }, - "created": 1488499654, - "currency": "usd", - "flow": "receiver", - "livemode": false, - "metadata": {}, - "owner": { - "verified_phone": "4158675309", - "address": { - "country": "US", - "city": "San Francisco", - "state": "CA", - "postal_code": "94107", - "line2": "#345", - "line1": "123 Market St" - }, - "phone": "4158675309", - "name": "Jenny Rosen", - "verified_name": "Jenny Rosen", - "verified_email": "jenny.rosen@example.com", - "verified_address": { - "country": "US", - "city": "San Francisco", - "state": "CA", - "postal_code": "94107", - "line2": "#345", - "line1": "123 Market St" - }, - "email": "jenny.rosen@example.com" - }, - "redirect": { - "return_url": "https://google.com", - "url": "examplecompany://redirect-link", - "status": "succeeded" - }, - "receiver": { - "address": "test_1MBhWS3uv4ynCfQXF3xQjJkzFPukr4K56N", - "amount_charged": 0, - "amount_received": 0, - "amount_returned": 0 - }, - "status": "pending", - "type": "dogecoin", - "usage": "single_use", - "dogecoin": { - "address": "test_1MBhWS3uv4ynCfQXF3xQjJkzFPukr4K56N", - "amount": 2371000, - "amount_charged": 0, - "amount_received": 0, - "amount_returned": 0, - "uri": "dogecoin:test_1MBhWS3uv4ynCfQXF3xQjJkzFPukr4K56N?amount=0.02371000" - } - } - """.trimIndent() - ) - - private val DELETED_CARD_JSON = JSONObject( - """ - { - "id": "card_1ELdAlCRMbs6FrXfNbmZEOb7", - "object": "card", - "deleted": true - } - """.trimIndent() + assertEquals( + "WIDGET FACTORY", + SourceFixtures.SOURCE_WITH_SOURCE_ORDER.statementDescriptor ) } }