diff --git a/.github/workflows/stripe_terminal_integration.yml b/.github/workflows/stripe_terminal_integration.yml index 786117b..06952ed 100644 --- a/.github/workflows/stripe_terminal_integration.yml +++ b/.github/workflows/stripe_terminal_integration.yml @@ -8,8 +8,6 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true - - jobs: integration: runs-on: ubuntu-latest @@ -23,7 +21,7 @@ jobs: - uses: actions/checkout@v3 - uses: subosito/flutter-action@v2 with: - flutter-version: '3.13.x' + flutter-version: '3.16.x' - name: Resolve dependencies run: flutter pub get @@ -47,9 +45,13 @@ jobs: steps: - uses: actions/checkout@v3 + - name: setup-cocoapods + uses: maxim-lobanov/setup-cocoapods@v1 + with: + podfile-path: stripe_terminal/example/ios/Podfile.lock - uses: subosito/flutter-action@v2 with: - flutter-version: '3.13.x' + flutter-version: '3.16.x' - name: Resolve dependencies run: flutter pub get --enforce-lockfile diff --git a/stripe_terminal/CHANGELOG.md b/stripe_terminal/CHANGELOG.md index 801748f..a9b18d5 100644 --- a/stripe_terminal/CHANGELOG.md +++ b/stripe_terminal/CHANGELOG.md @@ -1,3 +1,9 @@ +- chore(android): Replaced `compileSdkVersion` with `compileSdk` and bumped version to `34` +- chore(android): Bumped tools gradle version to `8.1.3` +- feat: Bumped [Android](https://github.com/stripe/stripe-terminal-android/blob/master/CHANGELOG.md#320---2023-11-15) + and [IOS](https://github.com/stripe/stripe-terminal-ios/blob/master/CHANGELOG.md#320-2023-11-17) sdks versions to `3.2.0` +- feat: Added to `PaymentIntent` class `charges`, `paymentMethod`, `amountDetails` properties + ## 3.1.2 - fix: Fixed incorrect Terminal instance access when unmounting the plugin from the engine diff --git a/stripe_terminal/android/build.gradle b/stripe_terminal/android/build.gradle index b972b9c..7dd6466 100644 --- a/stripe_terminal/android/build.gradle +++ b/stripe_terminal/android/build.gradle @@ -9,7 +9,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:8.0.2' + classpath 'com.android.tools.build:gradle:8.1.3' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } @@ -26,7 +26,7 @@ apply plugin: 'kotlin-android' android { namespace "mek.stripeterminal" - compileSdkVersion 33 + compileSdk 34 compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 @@ -66,6 +66,6 @@ android { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - api "com.stripe:stripeterminal-localmobile:3.1.0" - api "com.stripe:stripeterminal-core:3.1.0" + api "com.stripe:stripeterminal-localmobile:3.2.0" + api "com.stripe:stripeterminal-core:3.2.0" } \ No newline at end of file diff --git a/stripe_terminal/android/src/main/kotlin/mek/stripeterminal/api/TerminalApi.kt b/stripe_terminal/android/src/main/kotlin/mek/stripeterminal/api/TerminalApi.kt index 47a5236..6d3c59a 100644 --- a/stripe_terminal/android/src/main/kotlin/mek/stripeterminal/api/TerminalApi.kt +++ b/stripe_terminal/android/src/main/kotlin/mek/stripeterminal/api/TerminalApi.kt @@ -553,6 +553,16 @@ data class AddressApi( } } +data class AmountDetailsApi( + val tip: TipApi?, +) { + fun serialize(): List { + return listOf( + tip?.serialize(), + ) + } +} + enum class BatteryStatusApi { CRITICAL, LOW, NOMINAL; } @@ -565,6 +575,26 @@ enum class CardBrandApi { AMEX, DINERS_CLUB, DISCOVER, JCB, MASTER_CARD, UNION_PAY, VISA, INTERAC, EFTPOS_AU; } +data class CardDetailsApi( + val brand: CardBrandApi?, + val country: String?, + val expMonth: Long, + val expYear: Long, + val funding: CardFundingTypeApi?, + val last4: String?, +) { + fun serialize(): List { + return listOf( + brand?.ordinal, + country, + expMonth, + expYear, + funding?.ordinal, + last4, + ) + } +} + enum class CardFundingTypeApi { CREDIT, DEBIT, PREPAID; } @@ -679,6 +709,38 @@ data class CartLineItemApi( } } +data class ChargeApi( + val amount: Long, + val currency: String, + val status: ChargeStatusApi, + val paymentMethodDetails: PaymentMethodDetailsApi?, + val description: String, + val id: String, + val metadata: HashMap, + val statementDescriptorSuffix: String?, + val calculatedStatementDescriptor: String?, + val authorizationCode: String?, +) { + fun serialize(): List { + return listOf( + amount, + currency, + status.ordinal, + paymentMethodDetails?.serialize(), + description, + id, + hashMapOf(*metadata.map { (k, v) -> k to v }.toTypedArray()), + statementDescriptorSuffix, + calculatedStatementDescriptor, + authorizationCode, + ) + } +} + +enum class ChargeStatusApi { + SUCCEEDED, PENDING, FAILED; +} + enum class ConfirmationMethodApi { AUTOMATIC, MANUAL; } @@ -830,7 +892,10 @@ data class PaymentIntentApi( val captureMethod: CaptureMethodApi, val currency: String, val metadata: HashMap, + val charges: List, + val paymentMethod: PaymentMethodApi?, val paymentMethodId: String?, + val amountDetails: AmountDetailsApi?, val amountTip: Double?, val statementDescriptor: String?, val statementDescriptorSuffix: String?, @@ -860,7 +925,10 @@ data class PaymentIntentApi( captureMethod.ordinal, currency, hashMapOf(*metadata.map { (k, v) -> k to v }.toTypedArray()), + charges.map { it.serialize()} , + paymentMethod?.serialize(), paymentMethodId, + amountDetails?.serialize(), amountTip, statementDescriptor, statementDescriptorSuffix, @@ -936,6 +1004,26 @@ enum class PaymentIntentUsageApi { ON_SESSION, OFF_SESSION; } +data class PaymentMethodApi( + val id: String, + val card: CardDetailsApi?, + val cardPresent: CardPresentDetailsApi?, + val interacPresent: CardPresentDetailsApi?, + val customerId: String?, + val metadata: HashMap, +) { + fun serialize(): List { + return listOf( + id, + card?.serialize(), + cardPresent?.serialize(), + interacPresent?.serialize(), + customerId, + hashMapOf(*metadata.map { (k, v) -> k to v }.toTypedArray()), + ) + } +} + data class PaymentMethodDetailsApi( val cardPresent: CardPresentDetailsApi?, val interacPresent: CardPresentDetailsApi?, @@ -1192,6 +1280,16 @@ enum class TerminalExceptionCodeApi { UNKNOWN, READER_NOT_RECOVERED, PAYMENT_INTENT_NOT_RECOVERED, SETUP_INTENT_NOT_RECOVERED, CANCEL_FAILED, NOT_CONNECTED_TO_READER, ALREADY_CONNECTED_TO_READER, BLUETOOTH_DISABLED, BLUETOOTH_PERMISSION_DENIED, CONFIRM_INVALID_PAYMENT_INTENT, INVALID_CLIENT_SECRET, INVALID_READER_FOR_UPDATE, UNSUPPORTED_OPERATION, UNEXPECTED_OPERATION, UNSUPPORTED_SDK, FEATURE_NOT_AVAILABLE_WITH_CONNECTED_READER, USB_PERMISSION_DENIED, USB_DISCOVERY_TIMED_OUT, INVALID_PARAMETER, INVALID_REQUIRED_PARAMETER, INVALID_TIP_PARAMETER, LOCAL_MOBILE_UNSUPPORTED_DEVICE, LOCAL_MOBILE_UNSUPPORTED_OPERATING_SYSTEM_VERSION, LOCAL_MOBILE_DEVICE_TAMPERED, LOCAL_MOBILE_DEBUG_NOT_SUPPORTED, OFFLINE_MODE_UNSUPPORTED_OPERATING_SYSTEM_VERSION, CANCELED, LOCATION_SERVICES_DISABLED, BLUETOOTH_SCAN_TIMED_OUT, BLUETOOTH_LOW_ENERGY_UNSUPPORTED, READER_SOFTWARE_UPDATE_FAILED_BATTERY_LOW, READER_SOFTWARE_UPDATE_FAILED_INTERRUPTED, READER_SOFTWARE_UPDATE_FAILED_EXPIRED_UPDATE, BLUETOOTH_CONNECTION_FAILED_BATTERY_CRITICALLY_LOW, CARD_INSERT_NOT_READ, CARD_SWIPE_NOT_READ, CARD_READ_TIMED_OUT, CARD_REMOVED, CUSTOMER_CONSENT_REQUIRED, CARD_LEFT_IN_READER, FEATURE_NOT_ENABLED_ON_ACCOUNT, PASSCODE_NOT_ENABLED, COMMAND_NOT_ALLOWED_DURING_CALL, INVALID_AMOUNT, INVALID_CURRENCY, APPLE_BUILT_IN_READER_T_O_S_ACCEPTANCE_REQUIRESI_CLOUD_SIGN_IN, APPLE_BUILT_IN_READER_T_O_S_ACCEPTANCE_CANCELED, APPLE_BUILT_IN_READER_FAILED_TO_PREPARE, APPLE_BUILT_IN_READER_DEVICE_BANNED, APPLE_BUILT_IN_READER_T_O_S_NOT_YET_ACCEPTED, APPLE_BUILT_IN_READER_T_O_S_ACCEPTANCE_FAILED, APPLE_BUILT_IN_READER_MERCHANT_BLOCKED, APPLE_BUILT_IN_READER_INVALID_MERCHANT, READER_BUSY, INCOMPATIBLE_READER, READER_COMMUNICATION_ERROR, UNKNOWN_READER_IP_ADDRESS, INTERNET_CONNECT_TIME_OUT, CONNECT_FAILED_READER_IS_IN_USE, READER_NOT_ACCESSIBLE_IN_BACKGROUND, BLUETOOTH_ERROR, BLUETOOTH_CONNECT_TIMED_OUT, BLUETOOTH_DISCONNECTED, BLUETOOTH_PEER_REMOVED_PAIRING_INFORMATION, BLUETOOTH_ALREADY_PAIRED_WITH_ANOTHER_DEVICE, BLUETOOTH_RECONNECT_STARTED, USB_DISCONNECTED, USB_RECONNECT_STARTED, READER_CONNECTED_TO_ANOTHER_DEVICE, READER_SOFTWARE_UPDATE_FAILED, READER_SOFTWARE_UPDATE_FAILED_READER_ERROR, READER_SOFTWARE_UPDATE_FAILED_SERVER_ERROR, NFC_DISABLED, UNSUPPORTED_READER_VERSION, UNEXPECTED_SDK_ERROR, UNEXPECTED_READER_ERROR, ENCRYPTION_KEY_FAILURE, ENCRYPTION_KEY_STILL_INITIALIZING, DECLINED_BY_STRIPE_API, DECLINED_BY_READER, NOT_CONNECTED_TO_INTERNET, REQUEST_TIMED_OUT, STRIPE_API_CONNECTION_ERROR, STRIPE_API_ERROR, STRIPE_API_RESPONSE_DECODING_ERROR, INTERNAL_NETWORK_ERROR, CONNECTION_TOKEN_PROVIDER_ERROR, SESSION_EXPIRED, UNSUPPORTED_MOBILE_DEVICE_CONFIGURATION, COMMAND_NOT_ALLOWED, AMOUNT_EXCEEDS_MAX_OFFLINE_AMOUNT, OFFLINE_PAYMENTS_DATABASE_TOO_LARGE, READER_CONNECTION_NOT_AVAILABLE_OFFLINE, READER_CONNECTION_OFFLINE_LOCATION_MISMATCH, READER_CONNECTION_OFFLINE_NEEDS_UPDATE, LOCATION_CONNECTION_NOT_AVAILABLE_OFFLINE, NO_LAST_SEEN_ACCOUNT, INVALID_OFFLINE_CURRENCY, REFUND_FAILED, CARD_SWIPE_NOT_AVAILABLE, INTERAC_NOT_SUPPORTED_OFFLINE, ONLINE_PIN_NOT_SUPPORTED_OFFLINE, OFFLINE_AND_CARD_EXPIRED, OFFLINE_TRANSACTION_DECLINED, OFFLINE_COLLECT_AND_CONFIRM_MISMATCH, FORWARDING_TEST_MODE_PAYMENT_IN_LIVE_MODE, FORWARDING_LIVE_MODE_PAYMENT_IN_TEST_MODE, OFFLINE_PAYMENT_INTENT_NOT_FOUND, UPDATE_PAYMENT_INTENT_UNAVAILABLE_WHILE_OFFLINE, UPDATE_PAYMENT_INTENT_UNAVAILABLE_WHILE_OFFLINE_MODE_ENABLED, MISSING_EMV_DATA, CONNECTION_TOKEN_PROVIDER_ERROR_WHILE_FORWARDING, CONNECTION_TOKEN_PROVIDER_TIMED_OUT, ACCOUNT_ID_MISMATCH_WHILE_FORWARDING, OFFLINE_BEHAVIOR_FORCE_OFFLINE_WITH_FEATURE_DISABLED, NOT_CONNECTED_TO_INTERNET_AND_OFFLINE_BEHAVIOR_REQUIRE_ONLINE, TEST_CARD_IN_LIVE_MODE, COLLECT_INPUTS_APPLICATION_ERROR, COLLECT_INPUTS_TIMED_OUT, COLLECT_INPUTS_UNSUPPORTED; } +data class TipApi( + val amount: Long?, +) { + fun serialize(): List { + return listOf( + amount, + ) + } +} + data class TippingConfigurationApi( val eligibleAmount: Long, ) { diff --git a/stripe_terminal/android/src/main/kotlin/mek/stripeterminal/api/ToApiExtensions.kt b/stripe_terminal/android/src/main/kotlin/mek/stripeterminal/api/ToApiExtensions.kt index 59747f1..f429701 100644 --- a/stripe_terminal/android/src/main/kotlin/mek/stripeterminal/api/ToApiExtensions.kt +++ b/stripe_terminal/android/src/main/kotlin/mek/stripeterminal/api/ToApiExtensions.kt @@ -4,6 +4,7 @@ import mek.stripeterminal.toHashMap import com.stripe.stripeterminal.external.models.* import com.stripe.stripeterminal.external.models.TerminalException.TerminalErrorCode import mek.stripeterminal.createApiError +import mek.stripeterminal.mappings.toApi fun TerminalException.toPlatformError(): PlatformError { return toApi().toPlatformError() @@ -317,6 +318,9 @@ fun PaymentIntent.toApi(): PaymentIntentApi { }, currency = currency!!, metadata = metadata?.toHashMap() ?: hashMapOf(), + charges = getCharges().map { it.toApi() }, + paymentMethod = paymentMethod?.toApi(), + amountDetails = amountDetails?.toApi(), paymentMethodId = paymentMethodId, amountTip = amountTip?.toDouble(), statementDescriptor = statementDescriptor, diff --git a/stripe_terminal/android/src/main/kotlin/mek/stripeterminal/mappings/CardMappings.kt b/stripe_terminal/android/src/main/kotlin/mek/stripeterminal/mappings/CardMappings.kt new file mode 100644 index 0000000..662d123 --- /dev/null +++ b/stripe_terminal/android/src/main/kotlin/mek/stripeterminal/mappings/CardMappings.kt @@ -0,0 +1,17 @@ +package mek.stripeterminal.mappings + +import com.stripe.stripeterminal.external.models.CardDetails +import mek.stripeterminal.api.CardDetailsApi +import mek.stripeterminal.api.cardBrandToApi +import mek.stripeterminal.api.fundingToApi + +fun CardDetails.toApi(): CardDetailsApi { + return CardDetailsApi( + brand = cardBrandToApi(brand), + country = country, + expMonth = expMonth.toLong(), + expYear = expYear.toLong(), + funding = fundingToApi(funding), + last4 = last4, + ) +} diff --git a/stripe_terminal/android/src/main/kotlin/mek/stripeterminal/mappings/ChargeMappings.kt b/stripe_terminal/android/src/main/kotlin/mek/stripeterminal/mappings/ChargeMappings.kt new file mode 100644 index 0000000..5246733 --- /dev/null +++ b/stripe_terminal/android/src/main/kotlin/mek/stripeterminal/mappings/ChargeMappings.kt @@ -0,0 +1,27 @@ +package mek.stripeterminal.mappings + +import com.stripe.stripeterminal.external.models.Charge +import mek.stripeterminal.api.ChargeApi +import mek.stripeterminal.api.ChargeStatusApi +import mek.stripeterminal.api.toApi +import mek.stripeterminal.toHashMap + +fun Charge.toApi(): ChargeApi { + return ChargeApi( + amount = amount, + currency = currency!!, + status = when (status) { + "pending" -> ChargeStatusApi.PENDING + "failed" -> ChargeStatusApi.FAILED + "succeeded" -> ChargeStatusApi.SUCCEEDED + else -> throw Error("Unsupported $status") + }, + paymentMethodDetails = paymentMethodDetails?.toApi(), + description = description!!, + id = id, + metadata = metadata?.toHashMap() ?: hashMapOf(), + statementDescriptorSuffix = statementDescriptorSuffix, + calculatedStatementDescriptor = calculatedStatementDescriptor, + authorizationCode = authorizationCode, + ) +} diff --git a/stripe_terminal/android/src/main/kotlin/mek/stripeterminal/mappings/PaymentIntentMappings.kt b/stripe_terminal/android/src/main/kotlin/mek/stripeterminal/mappings/PaymentIntentMappings.kt new file mode 100644 index 0000000..eb17641 --- /dev/null +++ b/stripe_terminal/android/src/main/kotlin/mek/stripeterminal/mappings/PaymentIntentMappings.kt @@ -0,0 +1,10 @@ +package mek.stripeterminal.mappings + +import com.stripe.stripeterminal.external.models.AmountDetails +import mek.stripeterminal.api.AmountDetailsApi + +fun AmountDetails.toApi(): AmountDetailsApi { + return AmountDetailsApi( + tip = tip?.toApi(), + ) +} diff --git a/stripe_terminal/android/src/main/kotlin/mek/stripeterminal/mappings/PaymentMethod.kt b/stripe_terminal/android/src/main/kotlin/mek/stripeterminal/mappings/PaymentMethod.kt new file mode 100644 index 0000000..d8c0609 --- /dev/null +++ b/stripe_terminal/android/src/main/kotlin/mek/stripeterminal/mappings/PaymentMethod.kt @@ -0,0 +1,17 @@ +package mek.stripeterminal.mappings + +import com.stripe.stripeterminal.external.models.PaymentMethod +import mek.stripeterminal.api.PaymentMethodApi +import mek.stripeterminal.api.toApi +import mek.stripeterminal.toHashMap + +fun PaymentMethod.toApi(): PaymentMethodApi { + return PaymentMethodApi( + id = id, + card = cardDetails?.toApi(), + cardPresent = cardPresentDetails?.toApi(), + interacPresent = interacPresentDetails?.toApi(), + customerId = customer, + metadata = metadata?.toHashMap() ?: hashMapOf(), + ) +} diff --git a/stripe_terminal/android/src/main/kotlin/mek/stripeterminal/mappings/TipMappings.kt b/stripe_terminal/android/src/main/kotlin/mek/stripeterminal/mappings/TipMappings.kt new file mode 100644 index 0000000..2f9ac5d --- /dev/null +++ b/stripe_terminal/android/src/main/kotlin/mek/stripeterminal/mappings/TipMappings.kt @@ -0,0 +1,10 @@ +package mek.stripeterminal.mappings + +import com.stripe.stripeterminal.external.models.Tip +import mek.stripeterminal.api.TipApi + +fun Tip.toApi(): TipApi { + return TipApi( + amount = amount, + ) +} diff --git a/stripe_terminal/example/android/app/build.gradle b/stripe_terminal/example/android/app/build.gradle index 2a7597b..06569fc 100644 --- a/stripe_terminal/example/android/app/build.gradle +++ b/stripe_terminal/example/android/app/build.gradle @@ -27,7 +27,7 @@ apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { namespace "mek.stripeterminal.example" - compileSdkVersion flutter.compileSdkVersion + compileSdk 34 // flutter.compileSdkVersion ndkVersion flutter.ndkVersion compileOptions { diff --git a/stripe_terminal/example/android/build.gradle b/stripe_terminal/example/android/build.gradle index 5d4b56b..c3635bf 100644 --- a/stripe_terminal/example/android/build.gradle +++ b/stripe_terminal/example/android/build.gradle @@ -6,7 +6,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:8.0.2' + classpath 'com.android.tools.build:gradle:8.1.3' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } diff --git a/stripe_terminal/example/ios/Podfile.lock b/stripe_terminal/example/ios/Podfile.lock index 9086fda..fad01ff 100644 --- a/stripe_terminal/example/ios/Podfile.lock +++ b/stripe_terminal/example/ios/Podfile.lock @@ -1,11 +1,11 @@ PODS: - Flutter (1.0.0) - - mek_stripe_terminal (3.1.2): + - mek_stripe_terminal (3.2.0): - Flutter - - StripeTerminal (~> 3.1.0) + - StripeTerminal (~> 3.2.0) - permission_handler_apple (9.1.1): - Flutter - - StripeTerminal (3.1.0) + - StripeTerminal (3.2.0) DEPENDENCIES: - Flutter (from `Flutter`) @@ -26,9 +26,9 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 - mek_stripe_terminal: 0bed67f1e3d67bb50ab3d3457de82693cbfbdb20 + mek_stripe_terminal: 8055972d50bf0f261f0f82de4cbe64db3dd53edb permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6 - StripeTerminal: fa064cf68a7a3df7c2ee1b2e6d33c8866d1e6aef + StripeTerminal: cc78f3deca49d72ffa1285609ca2a125535ac7d1 PODFILE CHECKSUM: cf4dc61115723a2c178f9ac6bcd06534dfb5b047 diff --git a/stripe_terminal/example/pubspec.lock b/stripe_terminal/example/pubspec.lock index e56f4fd..a14e782 100644 --- a/stripe_terminal/example/pubspec.lock +++ b/stripe_terminal/example/pubspec.lock @@ -29,10 +29,10 @@ packages: dependency: transitive description: name: collection - sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted - version: "1.17.2" + version: "1.18.0" crypto: dependency: transitive description: @@ -140,15 +140,15 @@ packages: path: ".." relative: true source: path - version: "3.1.2" + version: "3.2.0" meta: dependency: transitive description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" one_for_all: dependency: "direct overridden" description: @@ -310,10 +310,10 @@ packages: dependency: transitive description: name: web - sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 url: "https://pub.dev" source: hosted - version: "0.1.4-beta" + version: "0.3.0" sdks: - dart: ">=3.1.0-185.0.dev <4.0.0" + dart: ">=3.2.0-194.0.dev <4.0.0" flutter: ">=3.10.0" diff --git a/stripe_terminal/ios/Classes/Api/TerminalApi.swift b/stripe_terminal/ios/Classes/Api/TerminalApi.swift index 89ceeaa..204a6cf 100644 --- a/stripe_terminal/ios/Classes/Api/TerminalApi.swift +++ b/stripe_terminal/ios/Classes/Api/TerminalApi.swift @@ -586,6 +586,16 @@ struct AddressApi { } } +struct AmountDetailsApi { + let tip: TipApi? + + func serialize() -> [Any?] { + return [ + tip?.serialize(), + ] + } +} + enum BatteryStatusApi: Int { case critical case low @@ -609,6 +619,26 @@ enum CardBrandApi: Int { case eftposAu } +struct CardDetailsApi { + let brand: CardBrandApi? + let country: String? + let expMonth: Int + let expYear: Int + let funding: CardFundingTypeApi? + let last4: String? + + func serialize() -> [Any?] { + return [ + brand?.rawValue, + country, + expMonth, + expYear, + funding?.rawValue, + last4, + ] + } +} + enum CardFundingTypeApi: Int { case credit case debit @@ -720,6 +750,40 @@ struct CartLineItemApi { } } +struct ChargeApi { + let amount: Int + let currency: String + let status: ChargeStatusApi + let paymentMethodDetails: PaymentMethodDetailsApi? + let description: String + let id: String + let metadata: [String: String] + let statementDescriptorSuffix: String? + let calculatedStatementDescriptor: String? + let authorizationCode: String? + + func serialize() -> [Any?] { + return [ + amount, + currency, + status.rawValue, + paymentMethodDetails?.serialize(), + description, + id, + metadata != nil ? Dictionary(uniqueKeysWithValues: metadata.map { k, v in (k, v) }) : nil, + statementDescriptorSuffix, + calculatedStatementDescriptor, + authorizationCode, + ] + } +} + +enum ChargeStatusApi: Int { + case succeeded + case pending + case failed +} + enum ConfirmationMethodApi: Int { case automatic case manual @@ -883,7 +947,10 @@ struct PaymentIntentApi { let captureMethod: CaptureMethodApi let currency: String let metadata: [String: String] + let charges: [ChargeApi] + let paymentMethod: PaymentMethodApi? let paymentMethodId: String? + let amountDetails: AmountDetailsApi? let amountTip: Double? let statementDescriptor: String? let statementDescriptorSuffix: String? @@ -913,7 +980,10 @@ struct PaymentIntentApi { captureMethod.rawValue, currency, metadata != nil ? Dictionary(uniqueKeysWithValues: metadata.map { k, v in (k, v) }) : nil, + charges.map { $0.serialize() }, + paymentMethod?.serialize(), paymentMethodId, + amountDetails?.serialize(), amountTip, statementDescriptor, statementDescriptorSuffix, @@ -994,6 +1064,26 @@ enum PaymentIntentUsageApi: Int { case offSession } +struct PaymentMethodApi { + let id: String + let card: CardDetailsApi? + let cardPresent: CardPresentDetailsApi? + let interacPresent: CardPresentDetailsApi? + let customerId: String? + let metadata: [String: String] + + func serialize() -> [Any?] { + return [ + id, + card?.serialize(), + cardPresent?.serialize(), + interacPresent?.serialize(), + customerId, + metadata != nil ? Dictionary(uniqueKeysWithValues: metadata.map { k, v in (k, v) }) : nil, + ] + } +} + struct PaymentMethodDetailsApi { let cardPresent: CardPresentDetailsApi? let interacPresent: CardPresentDetailsApi? @@ -1398,6 +1488,16 @@ enum TerminalExceptionCodeApi: Int { case collectInputsUnsupported } +struct TipApi { + let amount: Int? + + func serialize() -> [Any?] { + return [ + amount, + ] + } +} + struct TippingConfigurationApi { let eligibleAmount: Int diff --git a/stripe_terminal/ios/Classes/Api/ToApiExtensions.swift b/stripe_terminal/ios/Classes/Api/ToApiExtensions.swift index b14617c..c786c93 100644 --- a/stripe_terminal/ios/Classes/Api/ToApiExtensions.swift +++ b/stripe_terminal/ios/Classes/Api/ToApiExtensions.swift @@ -369,7 +369,10 @@ extension PaymentIntent { captureMethod: captureMethod.toApi(), currency: currency, metadata: metadata ?? [:], - paymentMethodId: paymentMethod?.stripeId, + charges: charges.map { $0.toApi() }, + paymentMethod: paymentMethod?.toApi(), + paymentMethodId: paymentMethodId, + amountDetails: amountDetails?.toApi(), amountTip: amountTip != nil ? Double(truncating: amountTip!) : nil, statementDescriptor: statementDescriptor, statementDescriptorSuffix: statementDescriptorSuffix, diff --git a/stripe_terminal/ios/Classes/Api/ToHostExtensions.swift b/stripe_terminal/ios/Classes/Api/ToHostExtensions.swift index ffb91ab..6ad91df 100644 --- a/stripe_terminal/ios/Classes/Api/ToHostExtensions.swift +++ b/stripe_terminal/ios/Classes/Api/ToHostExtensions.swift @@ -15,7 +15,7 @@ extension PaymentIntentParametersApi { .setStatementDescriptorSuffix(statementDescriptorSuffix) .setReceiptEmail(receiptEmail) .setCustomer(customerId) - .setApplicationFeeAmount(applicationFeeAmount?.toNSNumber()) + .setApplicationFeeAmount(applicationFeeAmount?.nsNumberValue) .setTransferDataDestination(transferDataDestination) .setTransferGroup(transferGroup) .setOnBehalfOf(onBehalfOf) diff --git a/stripe_terminal/ios/Classes/Extensions.swift b/stripe_terminal/ios/Classes/Extensions.swift index bcf0aef..3fa5ed4 100644 --- a/stripe_terminal/ios/Classes/Extensions.swift +++ b/stripe_terminal/ios/Classes/Extensions.swift @@ -19,7 +19,13 @@ extension Dictionary where Value: Equatable { } extension Int { - func toNSNumber() -> NSNumber { + var nsNumberValue: NSNumber { get { return NSNumber(value: self) - } + } } +} + +extension UInt { + var intValue: Int { get { + return Int(self) + } } } diff --git a/stripe_terminal/ios/Classes/Mappings/CardMappings.swift b/stripe_terminal/ios/Classes/Mappings/CardMappings.swift new file mode 100644 index 0000000..6d930c2 --- /dev/null +++ b/stripe_terminal/ios/Classes/Mappings/CardMappings.swift @@ -0,0 +1,15 @@ +import Foundation +import StripeTerminal + +extension CardDetails { + func toApi() -> CardDetailsApi { + return CardDetailsApi( + brand: brand.toApi(), + country: country, + expMonth: expMonth, + expYear: expYear, + funding: funding.toApi(), + last4: last4 + ) + } +} diff --git a/stripe_terminal/ios/Classes/Mappings/ChargeMappings.swift b/stripe_terminal/ios/Classes/Mappings/ChargeMappings.swift new file mode 100644 index 0000000..da5d45e --- /dev/null +++ b/stripe_terminal/ios/Classes/Mappings/ChargeMappings.swift @@ -0,0 +1,34 @@ +import Foundation +import StripeTerminal + +extension ChargeStatus { + func toApi() -> ChargeStatusApi { + switch (self) { + case ChargeStatus.pending: + return ChargeStatusApi.pending + case ChargeStatus.failed: + return ChargeStatusApi.failed + case ChargeStatus.succeeded: + return ChargeStatusApi.succeeded + @unknown default: + fatalError("Unkown charge status") + } + } +} + +extension Charge { + func toApi() -> ChargeApi { + return ChargeApi( + amount: amount.intValue, + currency: currency, + status: status.toApi(), + paymentMethodDetails: paymentMethodDetails?.toApi(), + description: description, + id: stripeId, + metadata: metadata, + statementDescriptorSuffix: statementDescriptorSuffix, + calculatedStatementDescriptor: calculatedStatementDescriptor, + authorizationCode: authorizationCode + ) + } +} diff --git a/stripe_terminal/ios/Classes/Mappings/PaymentIntentMappings.swift b/stripe_terminal/ios/Classes/Mappings/PaymentIntentMappings.swift new file mode 100644 index 0000000..7da5f3d --- /dev/null +++ b/stripe_terminal/ios/Classes/Mappings/PaymentIntentMappings.swift @@ -0,0 +1,10 @@ +import Foundation +import StripeTerminal + +extension SCPAmountDetails { + func toApi() -> AmountDetailsApi { + return AmountDetailsApi( + tip: tip?.toApi() + ) + } +} diff --git a/stripe_terminal/ios/Classes/Mappings/PaymentMethodMappings.swift b/stripe_terminal/ios/Classes/Mappings/PaymentMethodMappings.swift new file mode 100644 index 0000000..c778001 --- /dev/null +++ b/stripe_terminal/ios/Classes/Mappings/PaymentMethodMappings.swift @@ -0,0 +1,15 @@ +import Foundation +import StripeTerminal + +extension PaymentMethod { + func toApi() -> PaymentMethodApi { + return PaymentMethodApi( + id: stripeId, + card: card?.toApi(), + cardPresent: cardPresent?.toApi(), + interacPresent: interacPresent?.toApi(), + customerId: customer, + metadata: metadata + ) + } +} diff --git a/stripe_terminal/ios/Classes/Mappings/TipMappings.swift b/stripe_terminal/ios/Classes/Mappings/TipMappings.swift new file mode 100644 index 0000000..9c47ed3 --- /dev/null +++ b/stripe_terminal/ios/Classes/Mappings/TipMappings.swift @@ -0,0 +1,10 @@ +import Foundation +import StripeTerminal + +extension SCPTip { + func toApi() -> TipApi { + return TipApi( + amount: amount?.intValue + ) + } +} diff --git a/stripe_terminal/ios/mek_stripe_terminal.podspec b/stripe_terminal/ios/mek_stripe_terminal.podspec index 31ee101..11ff3db 100644 --- a/stripe_terminal/ios/mek_stripe_terminal.podspec +++ b/stripe_terminal/ios/mek_stripe_terminal.podspec @@ -25,5 +25,5 @@ Pod::Spec.new do |s| s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' } s.swift_version = '5.0' - s.dependency 'StripeTerminal', '~> 3.1.0' + s.dependency 'StripeTerminal', '~> 3.2.0' end diff --git a/stripe_terminal/lib/mek_stripe_terminal.dart b/stripe_terminal/lib/mek_stripe_terminal.dart index e61fa40..c0a69c7 100644 --- a/stripe_terminal/lib/mek_stripe_terminal.dart +++ b/stripe_terminal/lib/mek_stripe_terminal.dart @@ -5,15 +5,17 @@ library mek_stripe_terminal; export 'src/cancellable_future.dart'; export 'src/models/card.dart'; export 'src/models/cart.dart'; +export 'src/models/charge.dart'; export 'src/models/discovery_configuration.dart'; export 'src/models/location.dart'; export 'src/models/payment.dart'; export 'src/models/payment_intent.dart'; +export 'src/models/payment_method.dart'; export 'src/models/reader.dart'; export 'src/models/reader_software_update.dart'; export 'src/models/refund.dart'; export 'src/models/setup_intent.dart'; -export 'src/models/tipping.dart'; +export 'src/models/tip.dart'; export 'src/reader_delegates.dart'; export 'src/terminal.dart'; export 'src/terminal_exception.dart'; diff --git a/stripe_terminal/lib/src/models/card.dart b/stripe_terminal/lib/src/models/card.dart index 4e834df..b246e3c 100644 --- a/stripe_terminal/lib/src/models/card.dart +++ b/stripe_terminal/lib/src/models/card.dart @@ -20,6 +20,25 @@ enum CardBrand { enum CardFundingType { credit, debit, prepaid } +@DataClass() +class CardDetails with _$CardDetails { + final CardBrand? brand; + final String? country; + final int expMonth; + final int expYear; + final CardFundingType? funding; + final String? last4; + + const CardDetails({ + required this.brand, + required this.country, + required this.expMonth, + required this.expYear, + required this.funding, + required this.last4, + }); +} + @DataClass() class CardPresentDetails with _$CardPresentDetails { final CardBrand? brand; diff --git a/stripe_terminal/lib/src/models/card.g.dart b/stripe_terminal/lib/src/models/card.g.dart index ed35f96..af72ad3 100644 --- a/stripe_terminal/lib/src/models/card.g.dart +++ b/stripe_terminal/lib/src/models/card.g.dart @@ -6,6 +6,42 @@ part of 'card.dart'; // DataClassGenerator // ************************************************************************** +mixin _$CardDetails { + CardDetails get _self => this as CardDetails; + @override + bool operator ==(Object other) => + identical(this, other) || + other is CardDetails && + runtimeType == other.runtimeType && + _self.brand == other.brand && + _self.country == other.country && + _self.expMonth == other.expMonth && + _self.expYear == other.expYear && + _self.funding == other.funding && + _self.last4 == other.last4; + @override + int get hashCode { + var hashCode = 0; + hashCode = $hashCombine(hashCode, _self.brand.hashCode); + hashCode = $hashCombine(hashCode, _self.country.hashCode); + hashCode = $hashCombine(hashCode, _self.expMonth.hashCode); + hashCode = $hashCombine(hashCode, _self.expYear.hashCode); + hashCode = $hashCombine(hashCode, _self.funding.hashCode); + hashCode = $hashCombine(hashCode, _self.last4.hashCode); + return $hashFinish(hashCode); + } + + @override + String toString() => (ClassToString('CardDetails') + ..add('brand', _self.brand) + ..add('country', _self.country) + ..add('expMonth', _self.expMonth) + ..add('expYear', _self.expYear) + ..add('funding', _self.funding) + ..add('last4', _self.last4)) + .toString(); +} + mixin _$CardPresentDetails { CardPresentDetails get _self => this as CardPresentDetails; @override diff --git a/stripe_terminal/lib/src/models/charge.dart b/stripe_terminal/lib/src/models/charge.dart new file mode 100644 index 0000000..c1b3d9f --- /dev/null +++ b/stripe_terminal/lib/src/models/charge.dart @@ -0,0 +1,71 @@ +import 'package:mek_data_class/mek_data_class.dart'; +import 'package:mek_stripe_terminal/mek_stripe_terminal.dart'; +import 'package:meta/meta.dart'; + +part 'charge.g.dart'; + +/// The possible statuses for a charge +enum ChargeStatus { + /// The charge succeeded. + succeeded, + + /// The charge pending. + pending, + + /// The charge failed. + failed, +} + +/// An object representing a Stripe charge. +/// +/// See https://stripe.com/docs/api#charges +@DataClass() +class Charge with _$Charge { + /// The amount of the charge. + final int amount; + + /// The currency of the charge. + final String currency; + + /// The status of the charge. + final ChargeStatus status; + + /// The payment method details associated with the charge. + final PaymentMethodDetails? paymentMethodDetails; + + /// A string describing the charge, displayed in the Stripe dashboard and in email receipts. + final String description; + + /// The unique identifier for the charge. + final String id; + + /// Metadata associated with the charge. + /// + /// See https://stripe.com/docs/api#metadata + final Map metadata; + + /// Extra dynamic information about a Charge. This will appear concatenated with the + /// statementDescriptor on your customer’s credit card’s statement. + final String? statementDescriptorSuffix; + + /// The full statement descriptor that is displayed on your customer’s credit card’s statement, + /// after the static statementDescriptor and dynamic statementDescriptorSuffix portions are combined. + final String? calculatedStatementDescriptor; + + /// 6 digit authorization code for this charge. + final String? authorizationCode; + + @internal + const Charge({ + required this.amount, + required this.currency, + required this.status, + required this.description, + required this.paymentMethodDetails, + required this.id, + required this.metadata, + required this.statementDescriptorSuffix, + required this.calculatedStatementDescriptor, + required this.authorizationCode, + }); +} diff --git a/stripe_terminal/lib/src/models/charge.g.dart b/stripe_terminal/lib/src/models/charge.g.dart new file mode 100644 index 0000000..e825c51 --- /dev/null +++ b/stripe_terminal/lib/src/models/charge.g.dart @@ -0,0 +1,55 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'charge.dart'; + +// ************************************************************************** +// DataClassGenerator +// ************************************************************************** + +mixin _$Charge { + Charge get _self => this as Charge; + @override + bool operator ==(Object other) => + identical(this, other) || + other is Charge && + runtimeType == other.runtimeType && + _self.amount == other.amount && + _self.currency == other.currency && + _self.status == other.status && + _self.paymentMethodDetails == other.paymentMethodDetails && + _self.description == other.description && + _self.id == other.id && + $mapEquality.equals(_self.metadata, other.metadata) && + _self.statementDescriptorSuffix == other.statementDescriptorSuffix && + _self.calculatedStatementDescriptor == other.calculatedStatementDescriptor && + _self.authorizationCode == other.authorizationCode; + @override + int get hashCode { + var hashCode = 0; + hashCode = $hashCombine(hashCode, _self.amount.hashCode); + hashCode = $hashCombine(hashCode, _self.currency.hashCode); + hashCode = $hashCombine(hashCode, _self.status.hashCode); + hashCode = $hashCombine(hashCode, _self.paymentMethodDetails.hashCode); + hashCode = $hashCombine(hashCode, _self.description.hashCode); + hashCode = $hashCombine(hashCode, _self.id.hashCode); + hashCode = $hashCombine(hashCode, $mapEquality.hash(_self.metadata)); + hashCode = $hashCombine(hashCode, _self.statementDescriptorSuffix.hashCode); + hashCode = $hashCombine(hashCode, _self.calculatedStatementDescriptor.hashCode); + hashCode = $hashCombine(hashCode, _self.authorizationCode.hashCode); + return $hashFinish(hashCode); + } + + @override + String toString() => (ClassToString('Charge') + ..add('amount', _self.amount) + ..add('currency', _self.currency) + ..add('status', _self.status) + ..add('paymentMethodDetails', _self.paymentMethodDetails) + ..add('description', _self.description) + ..add('id', _self.id) + ..add('metadata', _self.metadata) + ..add('statementDescriptorSuffix', _self.statementDescriptorSuffix) + ..add('calculatedStatementDescriptor', _self.calculatedStatementDescriptor) + ..add('authorizationCode', _self.authorizationCode)) + .toString(); +} diff --git a/stripe_terminal/lib/src/models/payment_intent.dart b/stripe_terminal/lib/src/models/payment_intent.dart index c7bed23..bd1d59a 100644 --- a/stripe_terminal/lib/src/models/payment_intent.dart +++ b/stripe_terminal/lib/src/models/payment_intent.dart @@ -1,5 +1,8 @@ import 'package:mek_data_class/mek_data_class.dart'; -import 'package:mek_stripe_terminal/mek_stripe_terminal.dart'; +import 'package:mek_stripe_terminal/src/models/card.dart'; +import 'package:mek_stripe_terminal/src/models/charge.dart'; +import 'package:mek_stripe_terminal/src/models/payment_method.dart'; +import 'package:mek_stripe_terminal/src/models/tip.dart'; import 'package:meta/meta.dart'; part 'payment_intent.g.dart'; @@ -36,9 +39,19 @@ class PaymentIntent with _$PaymentIntent { /// Set of key-value pairs attached to the object. final Map metadata; - // TODO: charges, paymentMethod, amountDetails + + /// Charges that were created by this PaymentIntent, if any. + final List charges; + + /// The payment method to be used in this PaymentIntent. Only valid in the intent returned during collectPaymentMethod when using the updatePaymentIntent option in the SCPCollectConfiguration. + final PaymentMethod? paymentMethod; + + /// ID of the payment method used in this PaymentIntent. final String? paymentMethodId; + /// Details about items included in the amount after confirmation. + final AmountDetails? amountDetails; + /// Indicates how much the user intends to tip in addition to the amount by at confirmation time. /// This is only non-null in the [PaymentIntent] instance returned during collect when using /// updatePaymentIntent set to true in the CollectConfiguration. @@ -125,6 +138,9 @@ class PaymentIntent with _$PaymentIntent { required this.statementDescriptor, required this.statementDescriptorSuffix, this.metadata = const {}, + required this.charges, + required this.paymentMethod, + required this.amountDetails, required this.applicationId, required this.captureMethod, required this.cancellationReason, @@ -172,6 +188,19 @@ enum PaymentIntentStatus { succeeded, } +/// Contains details about items included in the [PaymentIntent] amount +class AmountDetails { + /// Details about the tip + final Tip? tip; + + @internal + const AmountDetails({ + required this.tip, + }); +} + +// PARAMETERS + @DataClass() class PaymentIntentParameters with _$PaymentIntentParameters { /// The amount of the payment, provided in the currency’s smallest unit. @@ -268,18 +297,6 @@ class PaymentIntentParameters with _$PaymentIntentParameters { }); } -/// An enum representing the type of payment method being handled. -enum PaymentMethodType { - /// A card present payment method. - cardPresent, - - /// A card payment method. - card, - - /// An Interac Present payment method. - interactPresent -} - /// Controls when the funds will be captured from the customer’s account. enum CaptureMethod { /// Stripe automatically captures funds when the customer authorizes the payment. diff --git a/stripe_terminal/lib/src/models/payment_intent.g.dart b/stripe_terminal/lib/src/models/payment_intent.g.dart index ddcacf0..1002046 100644 --- a/stripe_terminal/lib/src/models/payment_intent.g.dart +++ b/stripe_terminal/lib/src/models/payment_intent.g.dart @@ -20,7 +20,10 @@ mixin _$PaymentIntent { _self.captureMethod == other.captureMethod && _self.currency == other.currency && $mapEquality.equals(_self.metadata, other.metadata) && + $listEquality.equals(_self.charges, other.charges) && + _self.paymentMethod == other.paymentMethod && _self.paymentMethodId == other.paymentMethodId && + _self.amountDetails == other.amountDetails && _self.amountTip == other.amountTip && _self.statementDescriptor == other.statementDescriptor && _self.statementDescriptorSuffix == other.statementDescriptorSuffix && @@ -50,7 +53,10 @@ mixin _$PaymentIntent { hashCode = $hashCombine(hashCode, _self.captureMethod.hashCode); hashCode = $hashCombine(hashCode, _self.currency.hashCode); hashCode = $hashCombine(hashCode, $mapEquality.hash(_self.metadata)); + hashCode = $hashCombine(hashCode, $listEquality.hash(_self.charges)); + hashCode = $hashCombine(hashCode, _self.paymentMethod.hashCode); hashCode = $hashCombine(hashCode, _self.paymentMethodId.hashCode); + hashCode = $hashCombine(hashCode, _self.amountDetails.hashCode); hashCode = $hashCombine(hashCode, _self.amountTip.hashCode); hashCode = $hashCombine(hashCode, _self.statementDescriptor.hashCode); hashCode = $hashCombine(hashCode, _self.statementDescriptorSuffix.hashCode); @@ -82,7 +88,10 @@ mixin _$PaymentIntent { ..add('captureMethod', _self.captureMethod) ..add('currency', _self.currency) ..add('metadata', _self.metadata) + ..add('charges', _self.charges) + ..add('paymentMethod', _self.paymentMethod) ..add('paymentMethodId', _self.paymentMethodId) + ..add('amountDetails', _self.amountDetails) ..add('amountTip', _self.amountTip) ..add('statementDescriptor', _self.statementDescriptor) ..add('statementDescriptorSuffix', _self.statementDescriptorSuffix) diff --git a/stripe_terminal/lib/src/models/payment_method.dart b/stripe_terminal/lib/src/models/payment_method.dart new file mode 100644 index 0000000..9499222 --- /dev/null +++ b/stripe_terminal/lib/src/models/payment_method.dart @@ -0,0 +1,52 @@ +import 'package:mek_data_class/mek_data_class.dart'; +import 'package:mek_stripe_terminal/src/models/card.dart'; +import 'package:meta/meta.dart'; + +part 'payment_method.g.dart'; + +/// An enum representing the type of payment method being handled. +enum PaymentMethodType { + /// A card present payment method. + cardPresent, + + /// A card payment method. + card, + + /// An Interac Present payment method. + interactPresent +} + +/// PaymentMethod objects represent your customer’s payment instruments. They can be used with +/// PaymentIntents to collect payments, or saved to Customer objects to store instrument details +/// for future payments. +@DataClass() +class PaymentMethod with _$PaymentMethod { + /// The unique identifier for the PaymentMethod + final String id; + + /// A CardDetails object containing more details about the payment method + final CardDetails? card; + + /// Details about the card-present payment method + final CardPresentDetails? cardPresent; + + /// Details about the interac-present payment method + final CardPresentDetails? interacPresent; + + /// The Customer that this PaymentMethod is attached to, or nil. + final String? customerId; + + /// Set of key-value pairs that you can attach to an object. This can be useful for storing + /// additional information about the object in a structured format. + final Map metadata; + + @internal + const PaymentMethod({ + required this.id, + required this.card, + required this.cardPresent, + required this.interacPresent, + required this.customerId, + this.metadata = const {}, + }); +} diff --git a/stripe_terminal/lib/src/models/payment_method.g.dart b/stripe_terminal/lib/src/models/payment_method.g.dart new file mode 100644 index 0000000..55c8f2b --- /dev/null +++ b/stripe_terminal/lib/src/models/payment_method.g.dart @@ -0,0 +1,43 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'payment_method.dart'; + +// ************************************************************************** +// DataClassGenerator +// ************************************************************************** + +mixin _$PaymentMethod { + PaymentMethod get _self => this as PaymentMethod; + @override + bool operator ==(Object other) => + identical(this, other) || + other is PaymentMethod && + runtimeType == other.runtimeType && + _self.id == other.id && + _self.card == other.card && + _self.cardPresent == other.cardPresent && + _self.interacPresent == other.interacPresent && + _self.customerId == other.customerId && + $mapEquality.equals(_self.metadata, other.metadata); + @override + int get hashCode { + var hashCode = 0; + hashCode = $hashCombine(hashCode, _self.id.hashCode); + hashCode = $hashCombine(hashCode, _self.card.hashCode); + hashCode = $hashCombine(hashCode, _self.cardPresent.hashCode); + hashCode = $hashCombine(hashCode, _self.interacPresent.hashCode); + hashCode = $hashCombine(hashCode, _self.customerId.hashCode); + hashCode = $hashCombine(hashCode, $mapEquality.hash(_self.metadata)); + return $hashFinish(hashCode); + } + + @override + String toString() => (ClassToString('PaymentMethod') + ..add('id', _self.id) + ..add('card', _self.card) + ..add('cardPresent', _self.cardPresent) + ..add('interacPresent', _self.interacPresent) + ..add('customerId', _self.customerId) + ..add('metadata', _self.metadata)) + .toString(); +} diff --git a/stripe_terminal/lib/src/models/tip.dart b/stripe_terminal/lib/src/models/tip.dart new file mode 100644 index 0000000..c21e4db --- /dev/null +++ b/stripe_terminal/lib/src/models/tip.dart @@ -0,0 +1,36 @@ +import 'package:mek_data_class/mek_data_class.dart'; +import 'package:meta/meta.dart'; + +part 'tip.g.dart'; + +/// Contains details about tips +/// +/// For more information, see the official Stripe docs: [Collect on-reader tips](https://stripe.com/docs/terminal/features/collecting-tips/on-reader) +@DataClass() +class Tip with _$Tip { + /// Portion of the amount that corresponds to a tip + /// + /// The value will be null in the following scenarios: + /// - tipping is skipped by using the CollectConfiguration.skipTipping flag or by setting TippingConfiguration.eligibleAmount to 0 + /// - current reader location does not have a tipping config set + /// If “No tip” is selected on the reader, the value will be 0 + final int? amount; + + @internal + const Tip({ + required this.amount, + }); +} + +// PARAMETERS + +/// The [TippingConfiguration] contains configuration information relevant to collecting tips. +@DataClass() +class TippingConfiguration with _$TippingConfiguration { + /// The amount of the payment total eligible for tips. + final int eligibleAmount; + + const TippingConfiguration({ + required this.eligibleAmount, + }); +} diff --git a/stripe_terminal/lib/src/models/tipping.g.dart b/stripe_terminal/lib/src/models/tip.g.dart similarity index 63% rename from stripe_terminal/lib/src/models/tipping.g.dart rename to stripe_terminal/lib/src/models/tip.g.dart index 72452a3..8a1667f 100644 --- a/stripe_terminal/lib/src/models/tipping.g.dart +++ b/stripe_terminal/lib/src/models/tip.g.dart @@ -1,11 +1,28 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -part of 'tipping.dart'; +part of 'tip.dart'; // ************************************************************************** // DataClassGenerator // ************************************************************************** +mixin _$Tip { + Tip get _self => this as Tip; + @override + bool operator ==(Object other) => + identical(this, other) || + other is Tip && runtimeType == other.runtimeType && _self.amount == other.amount; + @override + int get hashCode { + var hashCode = 0; + hashCode = $hashCombine(hashCode, _self.amount.hashCode); + return $hashFinish(hashCode); + } + + @override + String toString() => (ClassToString('Tip')..add('amount', _self.amount)).toString(); +} + mixin _$TippingConfiguration { TippingConfiguration get _self => this as TippingConfiguration; @override diff --git a/stripe_terminal/lib/src/models/tipping.dart b/stripe_terminal/lib/src/models/tipping.dart deleted file mode 100644 index 6e39bc4..0000000 --- a/stripe_terminal/lib/src/models/tipping.dart +++ /dev/null @@ -1,14 +0,0 @@ -import 'package:mek_data_class/mek_data_class.dart'; - -part 'tipping.g.dart'; - -/// The [TippingConfiguration] contains configuration information relevant to collecting tips. -@DataClass() -class TippingConfiguration with _$TippingConfiguration { - /// The amount of the payment total eligible for tips. - final int eligibleAmount; - - const TippingConfiguration({ - required this.eligibleAmount, - }); -} diff --git a/stripe_terminal/lib/src/platform/terminal_platform.api.dart b/stripe_terminal/lib/src/platform/terminal_platform.api.dart index 2535cba..56c2b20 100644 --- a/stripe_terminal/lib/src/platform/terminal_platform.api.dart +++ b/stripe_terminal/lib/src/platform/terminal_platform.api.dart @@ -464,6 +464,15 @@ Address _$deserializeAddress(List serialized) => Address( line2: serialized[3] as String?, postalCode: serialized[4] as String?, state: serialized[5] as String?); +AmountDetails _$deserializeAmountDetails(List serialized) => + AmountDetails(tip: serialized[0] != null ? _$deserializeTip(serialized[0] as List) : null); +CardDetails _$deserializeCardDetails(List serialized) => CardDetails( + brand: serialized[0] != null ? CardBrand.values[serialized[0] as int] : null, + country: serialized[1] as String?, + expMonth: serialized[2] as int, + expYear: serialized[3] as int, + funding: serialized[4] != null ? CardFundingType.values[serialized[4] as int] : null, + last4: serialized[5] as String?); CardNetworks _$deserializeCardNetworks(List serialized) => CardNetworks( available: (serialized[0] as List).map((e) => CardBrand.values[e as int]).toList(), preferred: serialized[1] as String?); @@ -495,6 +504,18 @@ List _$serializeCart(Cart deserialized) => [ ]; List _$serializeCartLineItem(CartLineItem deserialized) => [deserialized.description, deserialized.quantity, deserialized.amount]; +Charge _$deserializeCharge(List serialized) => Charge( + amount: serialized[0] as int, + currency: serialized[1] as String, + status: ChargeStatus.values[serialized[2] as int], + paymentMethodDetails: + serialized[3] != null ? _$deserializePaymentMethodDetails(serialized[3] as List) : null, + description: serialized[4] as String, + id: serialized[5] as String, + metadata: (serialized[6] as Map).map((k, v) => MapEntry(k as String, v as String)), + statementDescriptorSuffix: serialized[7] as String?, + calculatedStatementDescriptor: serialized[8] as String?, + authorizationCode: serialized[9] as String?); List _$serializeDiscoveryConfiguration(DiscoveryConfiguration deserialized) => switch (deserialized) { BluetoothDiscoveryConfiguration() => _$serializeBluetoothDiscoveryConfiguration(deserialized), @@ -541,29 +562,33 @@ PaymentIntent _$deserializePaymentIntent(List serialized) => PaymentInt captureMethod: CaptureMethod.values[serialized[4] as int], currency: serialized[5] as String, metadata: (serialized[6] as Map).map((k, v) => MapEntry(k as String, v as String)), - paymentMethodId: serialized[7] as String?, - amountTip: serialized[8] as double?, - statementDescriptor: serialized[9] as String?, - statementDescriptorSuffix: serialized[10] as String?, - amountCapturable: serialized[11] as double?, - amountReceived: serialized[12] as double?, - applicationId: serialized[13] as String?, - applicationFeeAmount: serialized[14] as double?, - cancellationReason: serialized[15] as String?, + charges: (serialized[7] as List).map((e) => _$deserializeCharge(e as List)).toList(), + paymentMethod: serialized[8] != null ? _$deserializePaymentMethod(serialized[8] as List) : null, + paymentMethodId: serialized[9] as String?, + amountDetails: + serialized[10] != null ? _$deserializeAmountDetails(serialized[10] as List) : null, + amountTip: serialized[11] as double?, + statementDescriptor: serialized[12] as String?, + statementDescriptorSuffix: serialized[13] as String?, + amountCapturable: serialized[14] as double?, + amountReceived: serialized[15] as double?, + applicationId: serialized[16] as String?, + applicationFeeAmount: serialized[17] as double?, + cancellationReason: serialized[18] as String?, canceledAt: - serialized[16] != null ? DateTime.fromMillisecondsSinceEpoch(serialized[16] as int) : null, - clientSecret: serialized[17] as String?, + serialized[19] != null ? DateTime.fromMillisecondsSinceEpoch(serialized[19] as int) : null, + clientSecret: serialized[20] as String?, confirmationMethod: - serialized[18] != null ? ConfirmationMethod.values[serialized[18] as int] : null, - customerId: serialized[19] as String?, - description: serialized[20] as String?, - invoiceId: serialized[21] as String?, - onBehalfOf: serialized[22] as String?, - reviewId: serialized[23] as String?, - receiptEmail: serialized[24] as String?, + serialized[21] != null ? ConfirmationMethod.values[serialized[21] as int] : null, + customerId: serialized[22] as String?, + description: serialized[23] as String?, + invoiceId: serialized[24] as String?, + onBehalfOf: serialized[25] as String?, + reviewId: serialized[26] as String?, + receiptEmail: serialized[27] as String?, setupFutureUsage: - serialized[25] != null ? PaymentIntentUsage.values[serialized[25] as int] : null, - transferGroup: serialized[26] as String?); + serialized[28] != null ? PaymentIntentUsage.values[serialized[28] as int] : null, + transferGroup: serialized[29] as String?); List _$serializePaymentIntentParameters(PaymentIntentParameters deserialized) => [ deserialized.amount, deserialized.currency, @@ -584,6 +609,15 @@ List _$serializePaymentIntentParameters(PaymentIntentParameters deseria ? _$serializePaymentMethodOptionsParameters(deserialized.paymentMethodOptionsParameters!) : null ]; +PaymentMethod _$deserializePaymentMethod(List serialized) => PaymentMethod( + id: serialized[0] as String, + card: serialized[1] != null ? _$deserializeCardDetails(serialized[1] as List) : null, + cardPresent: + serialized[2] != null ? _$deserializeCardPresentDetails(serialized[2] as List) : null, + interacPresent: + serialized[3] != null ? _$deserializeCardPresentDetails(serialized[3] as List) : null, + customerId: serialized[4] as String?, + metadata: (serialized[5] as Map).map((k, v) => MapEntry(k as String, v as String))); PaymentMethodDetails _$deserializePaymentMethodDetails(List serialized) => PaymentMethodDetails( cardPresent: @@ -672,5 +706,6 @@ TerminalException _$deserializeTerminalException(List serialized) => Te stackTrace: serialized[2] as String?, paymentIntent: serialized[3] != null ? _$deserializePaymentIntent(serialized[3] as List) : null, apiError: serialized[4]); +Tip _$deserializeTip(List serialized) => Tip(amount: serialized[0] as int?); List _$serializeTippingConfiguration(TippingConfiguration deserialized) => [deserialized.eligibleAmount]; diff --git a/stripe_terminal/lib/src/platform/terminal_platform.dart b/stripe_terminal/lib/src/platform/terminal_platform.dart index 05d59bc..e6c5454 100644 --- a/stripe_terminal/lib/src/platform/terminal_platform.dart +++ b/stripe_terminal/lib/src/platform/terminal_platform.dart @@ -5,15 +5,17 @@ import 'dart:async'; import 'package:flutter/services.dart'; import 'package:mek_stripe_terminal/src/models/card.dart'; import 'package:mek_stripe_terminal/src/models/cart.dart'; +import 'package:mek_stripe_terminal/src/models/charge.dart'; import 'package:mek_stripe_terminal/src/models/discovery_configuration.dart'; import 'package:mek_stripe_terminal/src/models/location.dart'; import 'package:mek_stripe_terminal/src/models/payment.dart'; import 'package:mek_stripe_terminal/src/models/payment_intent.dart'; +import 'package:mek_stripe_terminal/src/models/payment_method.dart'; import 'package:mek_stripe_terminal/src/models/reader.dart'; import 'package:mek_stripe_terminal/src/models/reader_software_update.dart'; import 'package:mek_stripe_terminal/src/models/refund.dart'; import 'package:mek_stripe_terminal/src/models/setup_intent.dart'; -import 'package:mek_stripe_terminal/src/models/tipping.dart'; +import 'package:mek_stripe_terminal/src/models/tip.dart'; import 'package:mek_stripe_terminal/src/reader_delegates.dart'; import 'package:mek_stripe_terminal/src/terminal_exception.dart'; import 'package:one_for_all/one_for_all.dart'; diff --git a/stripe_terminal/lib/src/terminal.dart b/stripe_terminal/lib/src/terminal.dart index 45d2f08..a96aaff 100644 --- a/stripe_terminal/lib/src/terminal.dart +++ b/stripe_terminal/lib/src/terminal.dart @@ -11,7 +11,7 @@ import 'package:mek_stripe_terminal/src/models/payment_intent.dart'; import 'package:mek_stripe_terminal/src/models/reader.dart'; import 'package:mek_stripe_terminal/src/models/refund.dart'; import 'package:mek_stripe_terminal/src/models/setup_intent.dart'; -import 'package:mek_stripe_terminal/src/models/tipping.dart'; +import 'package:mek_stripe_terminal/src/models/tip.dart'; import 'package:mek_stripe_terminal/src/platform/terminal_platform.dart'; import 'package:mek_stripe_terminal/src/reader_delegates.dart'; import 'package:mek_stripe_terminal/src/terminal_exception.dart'; diff --git a/stripe_terminal/pubspec.yaml b/stripe_terminal/pubspec.yaml index 60c7ebe..7d435f9 100644 --- a/stripe_terminal/pubspec.yaml +++ b/stripe_terminal/pubspec.yaml @@ -1,6 +1,6 @@ name: mek_stripe_terminal description: A StripeTerminal plugin to discover readers, connect to them and process payments. -version: 3.1.2 +version: 3.2.0 repository: https://github.com/BreX900/mek-packages/tree/main/stripe_terminal homepage: https://github.com/BreX900/mek-packages/tree/main/stripe_terminal topics: