From e229659b083eeec4cd9e66f693e3484abfab926a Mon Sep 17 00:00:00 2001 From: BreX900 Date: Sun, 24 Sep 2023 22:37:06 +0200 Subject: [PATCH] fix(stripe_terminal.ios): Fixes incorrect checking `null` values from flutter - feat(stripe_terminal): added more parameters to `PaymentIntentParams` class --- .../one_for_all_generator_integration.yml | 34 ++++++ .github/workflows/one_for_all_integration.yml | 34 ++++++ .../workflows/stripe_terminal_integration.yml | 36 ++++++ .../src/codecs/plataforms/swift_codecs.dart | 8 +- stripe_terminal/CHANGELOG.md | 4 +- stripe_terminal/ROADMAP.md | 3 + .../stripeterminal/StripeTerminalPlugin.kt | 20 +--- .../stripeterminal/api/StripeTerminalApi.kt | 66 +++++++++++ .../stripeterminal/api/ToHostExtensions.kt | 62 +++++++++++ stripe_terminal/example/lib/main.dart | 103 ++++++++++-------- stripe_terminal/example/lib/models/k.dart | 3 + stripe_terminal/example/lib/stripe_api.dart | 3 +- stripe_terminal/example/pubspec.lock | 2 +- .../ios/Classes/Api/StripeTerminalApi.swift | 69 +++++++++++- .../ios/Classes/Api/ToHostExtensions.swift | 56 +++++++++- stripe_terminal/ios/Classes/Extensions.swift | 6 + .../ios/Classes/StripeTerminalPlugin.swift | 1 - stripe_terminal/lib/src/models/card.dart | 24 ++++ stripe_terminal/lib/src/models/card.g.dart | 32 ++++++ .../lib/src/models/payment_intent.dart | 38 ++++++- .../lib/src/models/payment_intent.g.dart | 61 ++++++++++- .../stripe_terminal_platform.api.dart | 25 ++++- stripe_terminal/pubspec.yaml | 2 +- 23 files changed, 613 insertions(+), 79 deletions(-) create mode 100644 .github/workflows/one_for_all_generator_integration.yml create mode 100644 .github/workflows/one_for_all_integration.yml create mode 100644 .github/workflows/stripe_terminal_integration.yml create mode 100644 stripe_terminal/example/lib/models/k.dart diff --git a/.github/workflows/one_for_all_generator_integration.yml b/.github/workflows/one_for_all_generator_integration.yml new file mode 100644 index 0000000..601421d --- /dev/null +++ b/.github/workflows/one_for_all_generator_integration.yml @@ -0,0 +1,34 @@ +name: Integration OneForAllGenerator + +on: + pull_request: + paths: [ 'one_for_all/**', 'one_for_all_generator/**' ] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +defaults: + run: + working-directory: one_for_all_generator + +jobs: + integration: + runs-on: ubuntu-latest + timeout-minutes: 5 + + steps: + - uses: actions/checkout@v3 + - uses: dart-lang/setup-dart@v1 + + - name: Resolve dependencies + run: dart pub get + timeout-minutes: 2 + + - name: Check code formatting + run: >- + dart format --line-length 100 --set-exit-if-changed --output none + $(find . ! -path "./.dart_tool/**" ! -path "./build/**" -name "*.dart" ! -name "*.g.dart") + + - name: Analyze code + run: dart analyze diff --git a/.github/workflows/one_for_all_integration.yml b/.github/workflows/one_for_all_integration.yml new file mode 100644 index 0000000..42d565d --- /dev/null +++ b/.github/workflows/one_for_all_integration.yml @@ -0,0 +1,34 @@ +name: Integration OneForAll + +on: + pull_request: + paths: [ 'one_for_all/**' ] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +defaults: + run: + working-directory: one_for_all + +jobs: + integration: + runs-on: ubuntu-latest + timeout-minutes: 5 + + steps: + - uses: actions/checkout@v3 + - uses: dart-lang/setup-dart@v1 + + - name: Resolve dependencies + run: dart pub get + timeout-minutes: 2 + + - name: Check code formatting + run: >- + dart format --line-length 100 --set-exit-if-changed --output none + $(find . ! -path "./.dart_tool/**" ! -path "./build/**" -name "*.dart" ! -name "*.g.dart") + + - name: Analyze code + run: dart analyze diff --git a/.github/workflows/stripe_terminal_integration.yml b/.github/workflows/stripe_terminal_integration.yml new file mode 100644 index 0000000..0fa9afe --- /dev/null +++ b/.github/workflows/stripe_terminal_integration.yml @@ -0,0 +1,36 @@ +name: Integration StripeTerminal + +on: + pull_request: + paths: [ 'stripe_terminal/**', 'one_for_all/**' ] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +defaults: + run: + working-directory: stripe_terminal + +jobs: + integration: + runs-on: ubuntu-latest + timeout-minutes: 5 + + steps: + - uses: actions/checkout@v3 + - uses: subosito/flutter-action@v2 + with: + flutter-version: '3.13.x' + + - name: Resolve dependencies + run: flutter pub get + timeout-minutes: 2 + + - name: Check code formatting + run: >- + dart format --line-length 100 --set-exit-if-changed --output none + $(find . ! -path "./.dart_tool/**" ! -path "./build/**" -name "*.dart" ! -name "*.g.dart") + + - name: Analyze code + run: flutter analyze --no-fatal-infos diff --git a/one_for_all_generator/lib/src/codecs/plataforms/swift_codecs.dart b/one_for_all_generator/lib/src/codecs/plataforms/swift_codecs.dart index 3a90ded..4ea3930 100644 --- a/one_for_all_generator/lib/src/codecs/plataforms/swift_codecs.dart +++ b/one_for_all_generator/lib/src/codecs/plataforms/swift_codecs.dart @@ -48,11 +48,11 @@ class SwiftApiCodes extends HostApiCodecs { final typesArgs = type.doubleTypeArgs; final deserializer = 'Dictionary(uniqueKeysWithValues: ($varAccess as! [AnyHashable?: Any?])' '.map { k, v in (${encodeDeserialization(typesArgs.$1, 'k')}, ${encodeDeserialization(typesArgs.$2, 'v')}) })'; - return type.isNullable ? '$varAccess != nil ? $deserializer : nil' : deserializer; + return type.isNullable ? '!($varAccess is NSNull) ? $deserializer : nil' : deserializer; } if (type.isDartCoreEnum || type.element is EnumElement) { final deserializer = '${encodeName(type.displayName)}(rawValue: $varAccess as! Int)!'; - return type.isNullable ? '$varAccess != nil ? $deserializer : nil' : deserializer; + return type.isNullable ? '!($varAccess is NSNull) ? $deserializer : nil' : deserializer; } final codec = findCodec(type); @@ -60,7 +60,7 @@ class SwiftApiCodes extends HostApiCodecs { if (!type.isNullable || codec.hasNullSafeDeserialization) { return codec.encodeDeserialization(this, type, varAccess); } else { - return '$varAccess != nil ? ${codec.encodeDeserialization(this, type, varAccess)} : nil'; + return '!($varAccess is NSNull) ? ${codec.encodeDeserialization(this, type, varAccess)} : nil'; } } @@ -70,7 +70,7 @@ class SwiftApiCodes extends HostApiCodecs { ? 'deserialize${encodeName(type.displayName)}' : '${encodeName(type.displayName)}.deserialize'; final deserializer = '$deserializerMethod($varAccess as! [Any?])'; - return type.isNullable ? '$varAccess != nil ? $deserializer : nil' : deserializer; + return type.isNullable ? '!($varAccess is NSNull) ? $deserializer : nil' : deserializer; } @override diff --git a/stripe_terminal/CHANGELOG.md b/stripe_terminal/CHANGELOG.md index de4402a..a599892 100644 --- a/stripe_terminal/CHANGELOG.md +++ b/stripe_terminal/CHANGELOG.md @@ -1,4 +1,6 @@ -## Next release +## 3.0.0-dev +- fix(ios): Fixes incorrect checking `null` values from flutter +- feat: added more parameters to `PaymentIntentParams` class - build(android): The `minSdkVersion` has been updated to 26. This means that the SDK will no longer support devices running Android 7.1.2 (Nougat) or earlier. Older devices can continue to use the 2.x versions of the SDK while on the maintenance schedule. - feat: Added to `Reader` class the `location` field. - fix(android): `Terminal.onUnexpectedReaderDisconnect` will be emit if a command cannot be sent to an internet reader. Previously, this callback was only invoked when a periodic status check failed. diff --git a/stripe_terminal/ROADMAP.md b/stripe_terminal/ROADMAP.md index 9f65197..c4eed8e 100644 --- a/stripe_terminal/ROADMAP.md +++ b/stripe_terminal/ROADMAP.md @@ -1,4 +1,7 @@ #### Ready +- Update [README.md](./README.md) + +#### Done - https://github.com/BreX900/mek-packages/issues/11 # Android diff --git a/stripe_terminal/android/src/main/kotlin/mek/stripeterminal/StripeTerminalPlugin.kt b/stripe_terminal/android/src/main/kotlin/mek/stripeterminal/StripeTerminalPlugin.kt index e475a4d..898a4c3 100644 --- a/stripe_terminal/android/src/main/kotlin/mek/stripeterminal/StripeTerminalPlugin.kt +++ b/stripe_terminal/android/src/main/kotlin/mek/stripeterminal/StripeTerminalPlugin.kt @@ -291,26 +291,14 @@ class StripeTerminalPlugin : FlutterPlugin, ActivityAware, StripeTerminalPlatfor parameters: PaymentIntentParametersApi ) { _terminal.createPaymentIntent( - PaymentIntentParameters.Builder( - amount = parameters.amount, - currency = parameters.currency, - captureMethod = when (parameters.captureMethod) { - CaptureMethodApi.MANUAL -> CaptureMethod.Manual - CaptureMethodApi.AUTOMATIC -> CaptureMethod.Automatic - }, - allowedPaymentMethodTypes = parameters.paymentMethodTypes.map { - when (it) { - PaymentMethodTypeApi.CARD_PRESENT -> PaymentMethodType.CARD_PRESENT - PaymentMethodTypeApi.CARD -> PaymentMethodType.CARD - PaymentMethodTypeApi.INTERACT_PRESENT -> PaymentMethodType.INTERAC_PRESENT - } - }, - ).build(), object : TerminalErrorHandler(result::error), PaymentIntentCallback { + params = parameters.toHost(), + callback = object : TerminalErrorHandler(result::error), PaymentIntentCallback { override fun onSuccess(paymentIntent: PaymentIntent) { _paymentIntents[paymentIntent.id!!] = paymentIntent result.success(paymentIntent.toApi()) } - }) + } + ) } override fun onRetrievePaymentIntent( diff --git a/stripe_terminal/android/src/main/kotlin/mek/stripeterminal/api/StripeTerminalApi.kt b/stripe_terminal/android/src/main/kotlin/mek/stripeterminal/api/StripeTerminalApi.kt index 82df7e5..3b181ca 100644 --- a/stripe_terminal/android/src/main/kotlin/mek/stripeterminal/api/StripeTerminalApi.kt +++ b/stripe_terminal/android/src/main/kotlin/mek/stripeterminal/api/StripeTerminalApi.kt @@ -582,6 +582,10 @@ data class CardNetworksApi( } } +enum class CardPresentCaptureMethodApi { + MANUAL_PREFERRED; +} + data class CardPresentDetailsApi( val brand: CardBrandApi?, val country: String?, @@ -614,6 +618,30 @@ data class CardPresentDetailsApi( } } +data class CardPresentParametersApi( + val captureMethod: CardPresentCaptureMethodApi?, + val requestExtendedAuthorization: Boolean?, + val requestIncrementalAuthorizationSupport: Boolean?, + val requestedPriority: CardPresentRoutingApi?, +) { + companion object { + fun deserialize( + serialized: List, + ): CardPresentParametersApi { + return CardPresentParametersApi( + captureMethod = (serialized[0] as Int?)?.let { CardPresentCaptureMethodApi.values()[it] }, + requestExtendedAuthorization = serialized[1] as Boolean?, + requestIncrementalAuthorizationSupport = serialized[2] as Boolean?, + requestedPriority = (serialized[3] as Int?)?.let { CardPresentRoutingApi.values()[it] }, + ) + } + } +} + +enum class CardPresentRoutingApi { + DOMESTIC, INTERNATIONAL; +} + data class CartApi( val currency: String, val tax: Long, @@ -858,6 +886,18 @@ data class PaymentIntentParametersApi( val currency: String, val captureMethod: CaptureMethodApi, val paymentMethodTypes: List, + val metadata: HashMap, + val description: String?, + val statementDescriptor: String?, + val statementDescriptorSuffix: String?, + val receiptEmail: String?, + val customerId: String?, + val applicationFeeAmount: Long?, + val transferDataDestination: String?, + val transferGroup: String?, + val onBehalfOf: String?, + val setupFutureUsage: String?, + val paymentMethodOptionsParameters: PaymentMethodOptionsParametersApi?, ) { companion object { fun deserialize( @@ -868,6 +908,18 @@ data class PaymentIntentParametersApi( currency = serialized[1] as String, captureMethod = (serialized[2] as Int).let { CaptureMethodApi.values()[it] }, paymentMethodTypes = (serialized[3] as List<*>).map { (it as Int).let { PaymentMethodTypeApi.values()[it] } }, + metadata = hashMapOf(*(serialized[4] as HashMap<*, *>).map { (k, v) -> k as String to v as String }.toTypedArray()), + description = serialized[5] as String?, + statementDescriptor = serialized[6] as String?, + statementDescriptorSuffix = serialized[7] as String?, + receiptEmail = serialized[8] as String?, + customerId = serialized[9] as String?, + applicationFeeAmount = (serialized[10] as? Number)?.toLong(), + transferDataDestination = serialized[11] as String?, + transferGroup = serialized[12] as String?, + onBehalfOf = serialized[13] as String?, + setupFutureUsage = serialized[14] as String?, + paymentMethodOptionsParameters = (serialized[15] as List?)?.let { PaymentMethodOptionsParametersApi.deserialize(it) }, ) } } @@ -889,6 +941,20 @@ data class PaymentMethodDetailsApi( } } +data class PaymentMethodOptionsParametersApi( + val cardPresentParameters: CardPresentParametersApi, +) { + companion object { + fun deserialize( + serialized: List, + ): PaymentMethodOptionsParametersApi { + return PaymentMethodOptionsParametersApi( + cardPresentParameters = (serialized[0] as List).let { CardPresentParametersApi.deserialize(it) }, + ) + } + } +} + enum class PaymentMethodTypeApi { CARD_PRESENT, CARD, INTERACT_PRESENT; } diff --git a/stripe_terminal/android/src/main/kotlin/mek/stripeterminal/api/ToHostExtensions.kt b/stripe_terminal/android/src/main/kotlin/mek/stripeterminal/api/ToHostExtensions.kt index e371800..d737a07 100644 --- a/stripe_terminal/android/src/main/kotlin/mek/stripeterminal/api/ToHostExtensions.kt +++ b/stripe_terminal/android/src/main/kotlin/mek/stripeterminal/api/ToHostExtensions.kt @@ -9,15 +9,18 @@ fun DiscoveryConfigurationApi.toHost(): DiscoveryConfiguration? { isSimulated = isSimulated, timeout = timeout?.let { microsecondsToSeconds(it) } ?: 0, ) + is BluetoothProximityDiscoveryConfigurationApi -> null is HandoffDiscoveryConfigurationApi -> DiscoveryConfiguration.HandoffDiscoveryConfiguration() is InternetDiscoveryConfigurationApi -> DiscoveryConfiguration.InternetDiscoveryConfiguration( isSimulated = isSimulated, location = locationId, ) + is LocalMobileDiscoveryConfigurationApi -> DiscoveryConfiguration.LocalMobileDiscoveryConfiguration( isSimulated = isSimulated, ) + is UsbDiscoveryConfigurationApi -> DiscoveryConfiguration.UsbDiscoveryConfiguration( isSimulated = isSimulated, timeout = timeout?.let { microsecondsToSeconds(it) } ?: 0, @@ -61,6 +64,65 @@ fun CartLineItemApi.toHost(): CartLineItem { ).build() } +fun PaymentIntentParametersApi.toHost(): PaymentIntentParameters { + val b = PaymentIntentParameters.Builder( + amount = amount, + currency = currency, + captureMethod = when (captureMethod) { + CaptureMethodApi.MANUAL -> CaptureMethod.Manual + CaptureMethodApi.AUTOMATIC -> CaptureMethod.Automatic + }, + allowedPaymentMethodTypes = paymentMethodTypes.map { + when (it) { + PaymentMethodTypeApi.CARD_PRESENT -> PaymentMethodType.CARD_PRESENT + PaymentMethodTypeApi.CARD -> PaymentMethodType.CARD + PaymentMethodTypeApi.INTERACT_PRESENT -> PaymentMethodType.INTERAC_PRESENT + } + }, + ) + b.setMetadata(metadata) + description?.let(b::setDescription) + statementDescriptor?.let(b::setStatementDescriptor) + statementDescriptorSuffix?.let(b::setStatementDescriptorSuffix) + receiptEmail?.let(b::setReceiptEmail) + customerId?.let(b::setCustomer) + applicationFeeAmount?.let(b::setApplicationFeeAmount) + transferDataDestination?.let(b::setTransferDataDestination) + transferGroup?.let(b::setTransferGroup) + onBehalfOf?.let(b::setOnBehalfOf) + setupFutureUsage?.let(b::setSetupFutureUsage) + paymentMethodOptionsParameters?.let { b.setPaymentMethodOptionsParameters(it.toHost()) } + return b.build() +} + +fun PaymentMethodOptionsParametersApi.toHost(): PaymentMethodOptionsParameters { + return PaymentMethodOptionsParameters.Builder() + .setCardPresentParameters(cardPresentParameters.toHost()) + .build() +} + +fun CardPresentParametersApi.toHost(): CardPresentParameters { + val b = CardPresentParameters.Builder() + captureMethod?.let { b.setCaptureMethod(it.toHost()) } + requestExtendedAuthorization?.let { b.setRequestExtendedAuthorization(it) } + requestIncrementalAuthorizationSupport?.let { b.setRequestIncrementalAuthorizationSupport(it) } + requestedPriority?.let { b.setRouting(CardPresentRoutingOptionParameters(it.toHost())) } + return b.build() +} + +fun CardPresentCaptureMethodApi.toHost(): CardPresentCaptureMethod { + return when (this) { + CardPresentCaptureMethodApi.MANUAL_PREFERRED -> CardPresentCaptureMethod.ManualPreferred + } +} + +fun CardPresentRoutingApi.toHost(): RoutingPriority { + return when (this) { + CardPresentRoutingApi.DOMESTIC -> RoutingPriority.DOMESTIC + CardPresentRoutingApi.INTERNATIONAL -> RoutingPriority.INTERNATIONAL + } +} + fun SetupIntentUsageApi.toHost(): String { return when (this) { SetupIntentUsageApi.ON_SESSION -> "on_session" diff --git a/stripe_terminal/example/lib/main.dart b/stripe_terminal/example/lib/main.dart index 5f2ebc4..2a4ee1c 100644 --- a/stripe_terminal/example/lib/main.dart +++ b/stripe_terminal/example/lib/main.dart @@ -4,6 +4,7 @@ import 'dart:async'; import 'dart:io'; import 'package:example/models/discovery_method.dart'; +import 'package:example/models/k.dart'; import 'package:example/stripe_api.dart'; import 'package:flutter/material.dart'; import 'package:mek_stripe_terminal/mek_stripe_terminal.dart'; @@ -42,7 +43,8 @@ class _MyAppState extends State { StreamSubscription? _onUnexpectedReaderDisconnectSub; Reader? _reader; - String? _paymentIntentClientSecret; + StreamSubscription? _onPaymentStatusChangeSub; + PaymentStatus _paymentStatus = PaymentStatus.notReady; PaymentIntent? _paymentIntent; CancelableFuture? _collectingPaymentMethod; @@ -51,6 +53,7 @@ class _MyAppState extends State { unawaited(_onConnectionStatusChangeSub?.cancel()); unawaited(_discoverReaderSub?.cancel()); unawaited(_onUnexpectedReaderDisconnectSub?.cancel()); + unawaited(_onPaymentStatusChangeSub?.cancel()); unawaited(_collectingPaymentMethod?.cancel()); super.dispose(); } @@ -79,14 +82,18 @@ class _MyAppState extends State { fetchToken: _fetchConnectionToken, ); setState(() => _terminal = stripeTerminal); - _onConnectionStatusChangeSub = stripeTerminal.onConnectionStatusChange.listen((event) { - print('Connection Status Changed: ${event.name}'); - setState(() => _connectionStatus = event); + _onConnectionStatusChangeSub = stripeTerminal.onConnectionStatusChange.listen((status) { + print('Connection Status Changed: ${status.name}'); + setState(() => _connectionStatus = status); }); - _onUnexpectedReaderDisconnectSub = stripeTerminal.onUnexpectedReaderDisconnect.listen((event) { - print('Reader Unexpected Disconnected: ${event.label}'); + _onUnexpectedReaderDisconnectSub = stripeTerminal.onUnexpectedReaderDisconnect.listen((reader) { + print('Reader Unexpected Disconnected: ${reader.label}'); setState(() => _reader = null); }); + _onPaymentStatusChangeSub = stripeTerminal.onPaymentStatusChange.listen((status) { + print('Payment Status Changed: ${status.name}'); + setState(() => _paymentStatus = status); + }); } void _fetchLocations(StripeTerminal terminal) async { @@ -119,7 +126,7 @@ class _MyAppState extends State { _showSnackBar('Connection status: ${status.name}'); } - Future _connectReader(StripeTerminal terminal, Reader reader) async { + Future _tryConnectReader(StripeTerminal terminal, Reader reader) async { String? getLocationId() { final locationId = _selectedLocation?.id ?? reader.locationId; if (locationId == null) _showSnackBar('Missing location'); @@ -152,21 +159,20 @@ class _MyAppState extends State { } } - void _toggleReader(StripeTerminal terminal, Reader reader) async { - if (_reader != null) { - await terminal.disconnectReader(); - _showSnackBar('Terminal ${_reader!.label ?? _reader!.serialNumber} disconnected'); - setState(() => _reader = null); - return; - } - - final connectedReader = await _connectReader(terminal, reader); + void _connectReader(StripeTerminal terminal, Reader reader) async { + final connectedReader = await _tryConnectReader(terminal, reader); if (connectedReader == null) return; _showSnackBar( 'Connected to a device: ${connectedReader.label ?? connectedReader.serialNumber}'); setState(() => _reader = connectedReader); } + void _disconnectReader(StripeTerminal terminal) async { + await terminal.disconnectReader(); + _showSnackBar('Terminal ${_reader!.label ?? _reader!.serialNumber} disconnected'); + setState(() => _reader = null); + } + void _startDiscoverReaders(StripeTerminal terminal) { setState(() => _readers = const []); @@ -205,16 +211,19 @@ class _MyAppState extends State { setState(() => _discoverReaderSub = null); } - void _createPaymentIntent() async { - final paymentIntentClientSecret = await _api.createPaymentIntent(); - setState(() { - _paymentIntentClientSecret = paymentIntentClientSecret; - _paymentIntent = null; - }); + void _createPaymentIntent(StripeTerminal terminal) async { + final paymentIntent = await terminal.createPaymentIntent(PaymentIntentParameters( + amount: 200, + currency: K.currency, + captureMethod: CaptureMethod.automatic, + paymentMethodTypes: [PaymentMethodType.cardPresent], + )); + setState(() => _paymentIntent = paymentIntent); _showSnackBar('Payment intent created!'); } - void _retrievePaymentIntent(StripeTerminal terminal, String paymentIntentClientSecret) async { + void _createFromApiAndRetrievePaymentIntentFromSdk(StripeTerminal terminal) async { + final paymentIntentClientSecret = await _api.createPaymentIntent(); final paymentIntent = await terminal.retrievePaymentIntent(paymentIntentClientSecret); setState(() => _paymentIntent = paymentIntent); _showSnackBar('Payment intent retrieved!'); @@ -231,13 +240,16 @@ class _MyAppState extends State { try { final paymentIntentWithPaymentMethod = await collectingPaymentMethod; - setState(() => _paymentIntent = paymentIntentWithPaymentMethod); + setState(() { + _paymentIntent = paymentIntentWithPaymentMethod; + _collectingPaymentMethod = null; + }); _showSnackBar('Payment method collected!'); } on TerminalException catch (exception) { + setState(() => _collectingPaymentMethod = null); switch (exception.rawCode) { // TODO: map error codes from swift/android and unify them for dart case '2020' || 'cancelled': - setState(() => _collectingPaymentMethod = null); _showSnackBar('Collecting Payment method is cancelled!'); default: rethrow; @@ -265,7 +277,6 @@ class _MyAppState extends State { @override Widget build(BuildContext context) { final terminal = _terminal; - final paymentIntentClientSecret = _paymentIntentClientSecret; final paymentIntent = _paymentIntent; final collectingPaymentMethod = _collectingPaymentMethod; @@ -315,7 +326,14 @@ class _MyAppState extends State { ); }).toList(), ), - if (_discoverReaderSub == null) + if (_connectionStatus != ConnectionStatus.notConnected) + TextButton( + onPressed: terminal != null && _connectionStatus == ConnectionStatus.connected + ? () => _disconnectReader(terminal) + : null, + child: const Text('Disconnect Reader'), + ) + else if (_discoverReaderSub == null) TextButton( onPressed: terminal != null ? () => _startDiscoverReaders(terminal) : null, child: const Text('Scan Devices'), @@ -332,7 +350,9 @@ class _MyAppState extends State { enabled: terminal != null && _connectionStatus != ConnectionStatus.connecting && (_reader == null || _reader!.serialNumber == e.serialNumber), - onTap: terminal != null ? () => _toggleReader(terminal, e) : null, + onTap: terminal != null && _connectionStatus == ConnectionStatus.notConnected + ? () => _connectReader(terminal, e) + : null, title: Text(e.serialNumber), subtitle: Text('${e.deviceType?.name ?? 'Unknown'} ${e.locationId ?? 'NoLocation'}'), trailing: Text('${(e.batteryLevel * 100).toInt()}'), @@ -340,15 +360,18 @@ class _MyAppState extends State { }), ]; final paymentTab = [ + ListTile( + selected: true, + title: Text('Payment Status: ${_paymentStatus.name}'), + ), TextButton( - onPressed: _createPaymentIntent, - child: const Text('Create PaymentIntent'), + onPressed: terminal != null ? () => _createPaymentIntent(terminal) : null, + child: const Text('Create PaymentIntent via Skd'), ), TextButton( - onPressed: terminal != null && paymentIntentClientSecret != null - ? () => _retrievePaymentIntent(terminal, paymentIntentClientSecret) - : null, - child: const Text('Retrieve Payment Intent'), + onPressed: + terminal != null ? () => _createFromApiAndRetrievePaymentIntentFromSdk(terminal) : null, + child: const Text('Create PaymentIntent via Api and Retrieve it via Sdk'), ), if (collectingPaymentMethod == null) TextButton( @@ -380,20 +403,10 @@ class _MyAppState extends State { ) ]; final cardTab = [ - // TextButton( - // child: const Text('Read Reusable Card Detail'), - // onPressed: () async { - // stripeTerminal.readReusableCardDetail().then((StripePaymentMethod paymentMethod) { - // _showSnackbar( - // 'A card was read: ${paymentMethod.cardDetails}', - // ); - // }); - // }, - // ), TextButton( onPressed: terminal != null ? () async => await terminal.setReaderDisplay(const Cart( - currency: 'USD', + currency: K.currency, tax: 130, total: 1000, lineItems: [ diff --git a/stripe_terminal/example/lib/models/k.dart b/stripe_terminal/example/lib/models/k.dart new file mode 100644 index 0000000..79c49ba --- /dev/null +++ b/stripe_terminal/example/lib/models/k.dart @@ -0,0 +1,3 @@ +abstract final class K { + static const String currency = 'gbp'; +} diff --git a/stripe_terminal/example/lib/stripe_api.dart b/stripe_terminal/example/lib/stripe_api.dart index b5c11b1..5af48b9 100644 --- a/stripe_terminal/example/lib/stripe_api.dart +++ b/stripe_terminal/example/lib/stripe_api.dart @@ -2,6 +2,7 @@ import 'dart:convert'; +import 'package:example/models/k.dart'; import 'package:stripe/stripe.dart'; class StripeApi { @@ -45,7 +46,7 @@ class StripeApi { Future createPaymentIntent() async { final paymentIntent = await _stripe.client.post('payment_intents', data: { - 'currency': 'gbp', + 'currency': K.currency, 'payment_method_types': ['card_present'], 'capture_method': 'manual', 'amount': 1000, diff --git a/stripe_terminal/example/pubspec.lock b/stripe_terminal/example/pubspec.lock index 97e8ebf..de210bb 100644 --- a/stripe_terminal/example/pubspec.lock +++ b/stripe_terminal/example/pubspec.lock @@ -140,7 +140,7 @@ packages: path: ".." relative: true source: path - version: "2.1.4" + version: "3.0.0-dev" meta: dependency: transitive description: diff --git a/stripe_terminal/ios/Classes/Api/StripeTerminalApi.swift b/stripe_terminal/ios/Classes/Api/StripeTerminalApi.swift index d675269..22f8552 100644 --- a/stripe_terminal/ios/Classes/Api/StripeTerminalApi.swift +++ b/stripe_terminal/ios/Classes/Api/StripeTerminalApi.swift @@ -383,7 +383,7 @@ func setStripeTerminalPlatformApiHandler( } case "createSetupIntent": runAsync { - let res = try await hostApi.onCreateSetupIntent(args[0] as? String, args[1] != nil ? Dictionary(uniqueKeysWithValues: (args[1] as! [AnyHashable?: Any?]).map { k, v in (k as! String, v as! String) }) : nil, args[2] as? String, args[3] as? String, args[4] != nil ? SetupIntentUsageApi(rawValue: args[4] as! Int)! : nil) + let res = try await hostApi.onCreateSetupIntent(args[0] as? String, !(args[1] is NSNull) ? Dictionary(uniqueKeysWithValues: (args[1] as! [AnyHashable?: Any?]).map { k, v in (k as! String, v as! String) }) : nil, args[2] as? String, args[3] as? String, !(args[4] is NSNull) ? SetupIntentUsageApi(rawValue: args[4] as! Int)! : nil) return res.serialize() } case "retrieveSetupIntent": @@ -411,7 +411,7 @@ func setStripeTerminalPlatformApiHandler( } case "startCollectRefundPaymentMethod": let res = Result(result) { nil } - try hostApi.onStartCollectRefundPaymentMethod(res, args[0] as! Int, args[1] as! String, args[2] as! Int, args[3] as! String, args[4] != nil ? Dictionary(uniqueKeysWithValues: (args[4] as! [AnyHashable?: Any?]).map { k, v in (k as! String, v as! String) }) : nil, args[5] as? Bool, args[6] as? Bool, args[7] as? Bool) + try hostApi.onStartCollectRefundPaymentMethod(res, args[0] as! Int, args[1] as! String, args[2] as! Int, args[3] as! String, !(args[4] is NSNull) ? Dictionary(uniqueKeysWithValues: (args[4] as! [AnyHashable?: Any?]).map { k, v in (k as! String, v as! String) }) : nil, args[5] as? Bool, args[6] as? Bool, args[7] as? Bool) case "stopCollectRefundPaymentMethod": runAsync { try await hostApi.onStopCollectRefundPaymentMethod(args[0] as! Int) @@ -626,6 +626,10 @@ struct CardNetworksApi { } } +enum CardPresentCaptureMethodApi: Int { + case manualPreferred +} + struct CardPresentDetailsApi { let brand: CardBrandApi? let country: String? @@ -658,6 +662,29 @@ struct CardPresentDetailsApi { } } +struct CardPresentParametersApi { + let captureMethod: CardPresentCaptureMethodApi? + let requestExtendedAuthorization: Bool? + let requestIncrementalAuthorizationSupport: Bool? + let requestedPriority: CardPresentRoutingApi? + + static func deserialize( + _ serialized: [Any?] + ) -> CardPresentParametersApi { + return CardPresentParametersApi( + captureMethod: !(serialized[0] is NSNull) ? CardPresentCaptureMethodApi(rawValue: serialized[0] as! Int)! : nil, + requestExtendedAuthorization: serialized[1] as? Bool, + requestIncrementalAuthorizationSupport: serialized[2] as? Bool, + requestedPriority: !(serialized[3] is NSNull) ? CardPresentRoutingApi(rawValue: serialized[3] as! Int)! : nil + ) + } +} + +enum CardPresentRoutingApi: Int { + case domestic + case international +} + struct CartApi { let currency: String let tax: Int @@ -909,6 +936,18 @@ struct PaymentIntentParametersApi { let currency: String let captureMethod: CaptureMethodApi let paymentMethodTypes: [PaymentMethodTypeApi] + let metadata: [String: String] + let description: String? + let statementDescriptor: String? + let statementDescriptorSuffix: String? + let receiptEmail: String? + let customerId: String? + let applicationFeeAmount: Int? + let transferDataDestination: String? + let transferGroup: String? + let onBehalfOf: String? + let setupFutureUsage: String? + let paymentMethodOptionsParameters: PaymentMethodOptionsParametersApi? static func deserialize( _ serialized: [Any?] @@ -917,7 +956,19 @@ struct PaymentIntentParametersApi { amount: serialized[0] as! Int, currency: serialized[1] as! String, captureMethod: CaptureMethodApi(rawValue: serialized[2] as! Int)!, - paymentMethodTypes: (serialized[3] as! [Any?]).map { PaymentMethodTypeApi(rawValue: $0 as! Int)! } + paymentMethodTypes: (serialized[3] as! [Any?]).map { PaymentMethodTypeApi(rawValue: $0 as! Int)! }, + metadata: Dictionary(uniqueKeysWithValues: (serialized[4] as! [AnyHashable?: Any?]).map { k, v in (k as! String, v as! String) }), + description: serialized[5] as? String, + statementDescriptor: serialized[6] as? String, + statementDescriptorSuffix: serialized[7] as? String, + receiptEmail: serialized[8] as? String, + customerId: serialized[9] as? String, + applicationFeeAmount: serialized[10] as? Int, + transferDataDestination: serialized[11] as? String, + transferGroup: serialized[12] as? String, + onBehalfOf: serialized[13] as? String, + setupFutureUsage: serialized[14] as? String, + paymentMethodOptionsParameters: !(serialized[15] is NSNull) ? PaymentMethodOptionsParametersApi.deserialize(serialized[15] as! [Any?]) : nil ) } } @@ -943,6 +994,18 @@ struct PaymentMethodDetailsApi { } } +struct PaymentMethodOptionsParametersApi { + let cardPresentParameters: CardPresentParametersApi + + static func deserialize( + _ serialized: [Any?] + ) -> PaymentMethodOptionsParametersApi { + return PaymentMethodOptionsParametersApi( + cardPresentParameters: CardPresentParametersApi.deserialize(serialized[0] as! [Any?]) + ) + } +} + enum PaymentMethodTypeApi: Int { case cardPresent case card diff --git a/stripe_terminal/ios/Classes/Api/ToHostExtensions.swift b/stripe_terminal/ios/Classes/Api/ToHostExtensions.swift index 75fa479..4e9cf63 100644 --- a/stripe_terminal/ios/Classes/Api/ToHostExtensions.swift +++ b/stripe_terminal/ios/Classes/Api/ToHostExtensions.swift @@ -3,16 +3,68 @@ import StripeTerminal extension PaymentIntentParametersApi { func toHost() throws -> PaymentIntentParameters { - return try PaymentIntentParametersBuilder( + let b = PaymentIntentParametersBuilder( amount: UInt(amount), currency: currency ) .setPaymentMethodTypes(paymentMethodTypes.map { $0.toHost() }) .setCaptureMethod(captureMethod.toHost()) + .setMetadata(metadata) + .setStripeDescription(description) + .setStatementDescriptor(statementDescriptor) + .setStatementDescriptorSuffix(statementDescriptorSuffix) + .setReceiptEmail(receiptEmail) + .setCustomer(customerId) + .setApplicationFeeAmount(applicationFeeAmount?.toNSNumber()) + .setTransferDataDestination(transferDataDestination) + .setTransferGroup(transferGroup) + .setOnBehalfOf(onBehalfOf) + .setSetupFutureUsage(setupFutureUsage) + if let it = paymentMethodOptionsParameters { b.setPaymentMethodOptionsParameters(try it.toHost()) } + return try b.build() + } +} + +extension PaymentMethodOptionsParametersApi { + func toHost() throws -> PaymentMethodOptionsParameters { + return try PaymentMethodOptionsParametersBuilder( + cardPresentParameters: try cardPresentParameters.toHost() + ) .build() } } +extension CardPresentParametersApi { + func toHost() throws -> CardPresentParameters { + let b = CardPresentParametersBuilder() + if let it = captureMethod { b.setCaptureMethod(it.toHost()) } + if let it = requestedPriority { b.setRequestedPriority(it.toHost()) } + if let it = requestExtendedAuthorization { b.setRequestExtendedAuthorization(it) } + if let it = requestIncrementalAuthorizationSupport { b.setRequestIncrementalAuthorizationSupport(it) } + return try b.build() + } +} + +extension CardPresentCaptureMethodApi { + func toHost() -> CardPresentCaptureMethod { + switch self { + case .manualPreferred: + return .manualPreferred + } + } +} + +extension CardPresentRoutingApi { + func toHost() -> CardPresentRouting { + switch self { + case .domestic: + return .domestic + case .international: + return .international + } + } +} + extension PaymentMethodTypeApi { func toHost() -> String { switch (self) { @@ -28,7 +80,7 @@ extension PaymentMethodTypeApi { extension CaptureMethodApi { func toHost() -> CaptureMethod { - switch (self) { + switch self { case .automatic: return .automatic case .manual: diff --git a/stripe_terminal/ios/Classes/Extensions.swift b/stripe_terminal/ios/Classes/Extensions.swift index 57ce05a..bcf0aef 100644 --- a/stripe_terminal/ios/Classes/Extensions.swift +++ b/stripe_terminal/ios/Classes/Extensions.swift @@ -17,3 +17,9 @@ extension Dictionary where Value: Equatable { return self.first(where: { k, v in v == value})?.key } } + +extension Int { + func toNSNumber() -> NSNumber { + return NSNumber(value: self) + } +} diff --git a/stripe_terminal/ios/Classes/StripeTerminalPlugin.swift b/stripe_terminal/ios/Classes/StripeTerminalPlugin.swift index 14c12ae..97c0205 100644 --- a/stripe_terminal/ios/Classes/StripeTerminalPlugin.swift +++ b/stripe_terminal/ios/Classes/StripeTerminalPlugin.swift @@ -198,7 +198,6 @@ public class StripeTerminalPlugin: NSObject, FlutterPlugin, StripeTerminalPlatfo func onCreatePaymentIntent(_ parameters: PaymentIntentParametersApi) async throws -> PaymentIntentApi { do { - let paymentIntent = try await Terminal.shared.createPaymentIntent(parameters.toHost()) _paymentIntents[paymentIntent.stripeId!] = paymentIntent return paymentIntent.toApi() diff --git a/stripe_terminal/lib/src/models/card.dart b/stripe_terminal/lib/src/models/card.dart index a0a58a2..12d7e4f 100644 --- a/stripe_terminal/lib/src/models/card.dart +++ b/stripe_terminal/lib/src/models/card.dart @@ -90,3 +90,27 @@ class ReceiptDetails with _$ReceiptDetails { required this.terminalVerificationResults, }); } + +enum CardPresentCaptureMethod { + manualPreferred, +} + +@DataClass() +class CardPresentParameters with _$CardPresentParameters { + final CardPresentCaptureMethod? captureMethod; + final bool? requestExtendedAuthorization; + final bool? requestIncrementalAuthorizationSupport; + final CardPresentRouting? requestedPriority; + + const CardPresentParameters({ + this.captureMethod, + this.requestExtendedAuthorization, + this.requestIncrementalAuthorizationSupport, + this.requestedPriority, + }); +} + +enum CardPresentRouting { + domestic, + international, +} diff --git a/stripe_terminal/lib/src/models/card.g.dart b/stripe_terminal/lib/src/models/card.g.dart index b7ca7bd..ed35f96 100644 --- a/stripe_terminal/lib/src/models/card.g.dart +++ b/stripe_terminal/lib/src/models/card.g.dart @@ -125,3 +125,35 @@ mixin _$ReceiptDetails { ..add('terminalVerificationResults', _self.terminalVerificationResults)) .toString(); } + +mixin _$CardPresentParameters { + CardPresentParameters get _self => this as CardPresentParameters; + @override + bool operator ==(Object other) => + identical(this, other) || + other is CardPresentParameters && + runtimeType == other.runtimeType && + _self.captureMethod == other.captureMethod && + _self.requestExtendedAuthorization == other.requestExtendedAuthorization && + _self.requestIncrementalAuthorizationSupport == + other.requestIncrementalAuthorizationSupport && + _self.requestedPriority == other.requestedPriority; + @override + int get hashCode { + var hashCode = 0; + hashCode = $hashCombine(hashCode, _self.captureMethod.hashCode); + hashCode = $hashCombine(hashCode, _self.requestExtendedAuthorization.hashCode); + hashCode = $hashCombine(hashCode, _self.requestIncrementalAuthorizationSupport.hashCode); + hashCode = $hashCombine(hashCode, _self.requestedPriority.hashCode); + return $hashFinish(hashCode); + } + + @override + String toString() => (ClassToString('CardPresentParameters') + ..add('captureMethod', _self.captureMethod) + ..add('requestExtendedAuthorization', _self.requestExtendedAuthorization) + ..add( + 'requestIncrementalAuthorizationSupport', _self.requestIncrementalAuthorizationSupport) + ..add('requestedPriority', _self.requestedPriority)) + .toString(); +} diff --git a/stripe_terminal/lib/src/models/payment_intent.dart b/stripe_terminal/lib/src/models/payment_intent.dart index f250c1c..bf4bb4b 100644 --- a/stripe_terminal/lib/src/models/payment_intent.dart +++ b/stripe_terminal/lib/src/models/payment_intent.dart @@ -1,4 +1,5 @@ import 'package:mek_data_class/mek_data_class.dart'; +import 'package:mek_stripe_terminal/mek_stripe_terminal.dart'; import 'package:meta/meta.dart'; part 'payment_intent.g.dart'; @@ -86,14 +87,49 @@ class PaymentIntentParameters with _$PaymentIntentParameters { final CaptureMethod captureMethod; final List paymentMethodTypes; - const PaymentIntentParameters({ + final Map metadata; + final String? description; + final String? statementDescriptor; + final String? statementDescriptorSuffix; + final String? receiptEmail; + final String? customerId; + final int? applicationFeeAmount; + final String? transferDataDestination; + final String? transferGroup; + final String? onBehalfOf; + final String? setupFutureUsage; + + final PaymentMethodOptionsParameters? paymentMethodOptionsParameters; + + PaymentIntentParameters({ required this.amount, required this.currency, required this.captureMethod, required this.paymentMethodTypes, + this.metadata = const {}, + this.description, + this.statementDescriptor, + this.statementDescriptorSuffix, + this.receiptEmail, + this.customerId, + this.applicationFeeAmount, + this.transferDataDestination, + this.transferGroup, + this.onBehalfOf, + this.setupFutureUsage, + this.paymentMethodOptionsParameters, }); } enum PaymentMethodType { cardPresent, card, interactPresent } enum CaptureMethod { automatic, manual } + +@DataClass() +class PaymentMethodOptionsParameters with _$PaymentMethodOptionsParameters { + final CardPresentParameters cardPresentParameters; + + const PaymentMethodOptionsParameters({ + required this.cardPresentParameters, + }); +} diff --git a/stripe_terminal/lib/src/models/payment_intent.g.dart b/stripe_terminal/lib/src/models/payment_intent.g.dart index 0e12b6c..af58731 100644 --- a/stripe_terminal/lib/src/models/payment_intent.g.dart +++ b/stripe_terminal/lib/src/models/payment_intent.g.dart @@ -115,7 +115,19 @@ mixin _$PaymentIntentParameters { _self.amount == other.amount && _self.currency == other.currency && _self.captureMethod == other.captureMethod && - $listEquality.equals(_self.paymentMethodTypes, other.paymentMethodTypes); + $listEquality.equals(_self.paymentMethodTypes, other.paymentMethodTypes) && + $mapEquality.equals(_self.metadata, other.metadata) && + _self.description == other.description && + _self.statementDescriptor == other.statementDescriptor && + _self.statementDescriptorSuffix == other.statementDescriptorSuffix && + _self.receiptEmail == other.receiptEmail && + _self.customerId == other.customerId && + _self.applicationFeeAmount == other.applicationFeeAmount && + _self.transferDataDestination == other.transferDataDestination && + _self.transferGroup == other.transferGroup && + _self.onBehalfOf == other.onBehalfOf && + _self.setupFutureUsage == other.setupFutureUsage && + _self.paymentMethodOptionsParameters == other.paymentMethodOptionsParameters; @override int get hashCode { var hashCode = 0; @@ -123,6 +135,18 @@ mixin _$PaymentIntentParameters { hashCode = $hashCombine(hashCode, _self.currency.hashCode); hashCode = $hashCombine(hashCode, _self.captureMethod.hashCode); hashCode = $hashCombine(hashCode, $listEquality.hash(_self.paymentMethodTypes)); + hashCode = $hashCombine(hashCode, $mapEquality.hash(_self.metadata)); + hashCode = $hashCombine(hashCode, _self.description.hashCode); + hashCode = $hashCombine(hashCode, _self.statementDescriptor.hashCode); + hashCode = $hashCombine(hashCode, _self.statementDescriptorSuffix.hashCode); + hashCode = $hashCombine(hashCode, _self.receiptEmail.hashCode); + hashCode = $hashCombine(hashCode, _self.customerId.hashCode); + hashCode = $hashCombine(hashCode, _self.applicationFeeAmount.hashCode); + hashCode = $hashCombine(hashCode, _self.transferDataDestination.hashCode); + hashCode = $hashCombine(hashCode, _self.transferGroup.hashCode); + hashCode = $hashCombine(hashCode, _self.onBehalfOf.hashCode); + hashCode = $hashCombine(hashCode, _self.setupFutureUsage.hashCode); + hashCode = $hashCombine(hashCode, _self.paymentMethodOptionsParameters.hashCode); return $hashFinish(hashCode); } @@ -131,6 +155,39 @@ mixin _$PaymentIntentParameters { ..add('amount', _self.amount) ..add('currency', _self.currency) ..add('captureMethod', _self.captureMethod) - ..add('paymentMethodTypes', _self.paymentMethodTypes)) + ..add('paymentMethodTypes', _self.paymentMethodTypes) + ..add('metadata', _self.metadata) + ..add('description', _self.description) + ..add('statementDescriptor', _self.statementDescriptor) + ..add('statementDescriptorSuffix', _self.statementDescriptorSuffix) + ..add('receiptEmail', _self.receiptEmail) + ..add('customerId', _self.customerId) + ..add('applicationFeeAmount', _self.applicationFeeAmount) + ..add('transferDataDestination', _self.transferDataDestination) + ..add('transferGroup', _self.transferGroup) + ..add('onBehalfOf', _self.onBehalfOf) + ..add('setupFutureUsage', _self.setupFutureUsage) + ..add('paymentMethodOptionsParameters', _self.paymentMethodOptionsParameters)) + .toString(); +} + +mixin _$PaymentMethodOptionsParameters { + PaymentMethodOptionsParameters get _self => this as PaymentMethodOptionsParameters; + @override + bool operator ==(Object other) => + identical(this, other) || + other is PaymentMethodOptionsParameters && + runtimeType == other.runtimeType && + _self.cardPresentParameters == other.cardPresentParameters; + @override + int get hashCode { + var hashCode = 0; + hashCode = $hashCombine(hashCode, _self.cardPresentParameters.hashCode); + return $hashFinish(hashCode); + } + + @override + String toString() => (ClassToString('PaymentMethodOptionsParameters') + ..add('cardPresentParameters', _self.cardPresentParameters)) .toString(); } diff --git a/stripe_terminal/lib/src/platform/stripe_terminal_platform.api.dart b/stripe_terminal/lib/src/platform/stripe_terminal_platform.api.dart index 455fb59..1aab30f 100644 --- a/stripe_terminal/lib/src/platform/stripe_terminal_platform.api.dart +++ b/stripe_terminal/lib/src/platform/stripe_terminal_platform.api.dart @@ -467,6 +467,12 @@ CardPresentDetails _$deserializeCardPresentDetails(List serialized) => serialized[9] != null ? IncrementalAuthorizationStatus.values[serialized[9] as int] : null, networks: serialized[10] != null ? _$deserializeCardNetworks(serialized[10] as List) : null, receipt: serialized[11] != null ? _$deserializeReceiptDetails(serialized[11] as List) : null); +List _$serializeCardPresentParameters(CardPresentParameters deserialized) => [ + deserialized.captureMethod?.index, + deserialized.requestExtendedAuthorization, + deserialized.requestIncrementalAuthorizationSupport, + deserialized.requestedPriority?.index + ]; List _$serializeCart(Cart deserialized) => [ deserialized.currency, deserialized.tax, @@ -546,7 +552,21 @@ List _$serializePaymentIntentParameters(PaymentIntentParameters deseria deserialized.amount, deserialized.currency, deserialized.captureMethod.index, - deserialized.paymentMethodTypes.map((e) => e.index).toList() + deserialized.paymentMethodTypes.map((e) => e.index).toList(), + deserialized.metadata.map((k, v) => MapEntry(k, v)), + deserialized.description, + deserialized.statementDescriptor, + deserialized.statementDescriptorSuffix, + deserialized.receiptEmail, + deserialized.customerId, + deserialized.applicationFeeAmount, + deserialized.transferDataDestination, + deserialized.transferGroup, + deserialized.onBehalfOf, + deserialized.setupFutureUsage, + deserialized.paymentMethodOptionsParameters != null + ? _$serializePaymentMethodOptionsParameters(deserialized.paymentMethodOptionsParameters!) + : null ]; PaymentMethodDetails _$deserializePaymentMethodDetails(List serialized) => PaymentMethodDetails( @@ -554,6 +574,9 @@ PaymentMethodDetails _$deserializePaymentMethodDetails(List serialized) serialized[0] != null ? _$deserializeCardPresentDetails(serialized[0] as List) : null, interacPresent: serialized[1] != null ? _$deserializeCardPresentDetails(serialized[1] as List) : null); +List _$serializePaymentMethodOptionsParameters( + PaymentMethodOptionsParameters deserialized) => + [_$serializeCardPresentParameters(deserialized.cardPresentParameters)]; Reader _$deserializeReader(List serialized) => Reader( locationStatus: serialized[0] != null ? LocationStatus.values[serialized[0] as int] : null, deviceType: serialized[1] != null ? DeviceType.values[serialized[1] as int] : null, diff --git a/stripe_terminal/pubspec.yaml b/stripe_terminal/pubspec.yaml index 85c1631..d011fdb 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: 2.1.4 +version: 3.0.0-dev repository: https://github.com/BreX900/mek-packages/tree/main/stripe_terminal topics: - stripe-terminal