diff --git a/packages/stripe_platform_interface/lib/src/method_channel_stripe.dart b/packages/stripe_platform_interface/lib/src/method_channel_stripe.dart index 12cdef5af..67b61e427 100644 --- a/packages/stripe_platform_interface/lib/src/method_channel_stripe.dart +++ b/packages/stripe_platform_interface/lib/src/method_channel_stripe.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'package:flutter/services.dart'; +import 'package:stripe_platform_interface/src/models/create_token_data.dart'; import 'models/app_info.dart'; import 'models/apple_pay.dart'; @@ -199,6 +200,21 @@ class MethodChannelStripe extends StripePlatform { Future confirmPaymentSheetPayment() async { await _methodChannel.invokeMethod('confirmPaymentSheetPayment'); } + + @override + Future createToken(CreateTokenParams params) async { + try { + final result = await _methodChannel.invokeMapMethod( + 'createToken', {'params': params.toJson()}); + + return TokenData.fromJson(result.unfoldToNonNull()); + } on Exception catch (e) { + throw StripeError( + code: CreateTokenError.unknown, + message: 'Create token failed with exception: $e', + ); + } + } } class MethodChannelStripeFactory { diff --git a/packages/stripe_platform_interface/lib/src/models/card_field_input.dart b/packages/stripe_platform_interface/lib/src/models/card_field_input.dart index d30abbaf2..ed9f4cb7b 100644 --- a/packages/stripe_platform_interface/lib/src/models/card_field_input.dart +++ b/packages/stripe_platform_interface/lib/src/models/card_field_input.dart @@ -161,15 +161,19 @@ class CardFieldFocusName with _$CardFieldFocusName { /// Enum representing the different fiels on the card field. enum CardFieldName { @JsonValue('CardNumber') + /// Card number field. cardNumber, @JsonValue('Cvc') + /// Cvc field. cvc, @JsonValue('ExpiryDate') + /// Expiry date field. expiryDate, @JsonValue('PostalCode') + /// Postal code field. postalCode, } diff --git a/packages/stripe_platform_interface/lib/src/models/create_token_data.dart b/packages/stripe_platform_interface/lib/src/models/create_token_data.dart new file mode 100644 index 000000000..70c13f624 --- /dev/null +++ b/packages/stripe_platform_interface/lib/src/models/create_token_data.dart @@ -0,0 +1,158 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +import 'address.dart'; + +part 'create_token_data.freezed.dart'; +part 'create_token_data.g.dart'; +//ignore_for_file: constant_identifier_names + +@freezed + +/// parameters that are used to create a token. +/// +/// At this moment only card tokens are supported. +class CreateTokenParams with _$CreateTokenParams { + const factory CreateTokenParams({ + /// Type of token. + @Default(TokenType.Card) TokenType type, + + /// Additional address details + Address? address, + }) = _CreateTokenParams; + + factory CreateTokenParams.fromJson(Map json) => + _$CreateTokenParamsFromJson(json); +} + +@freezed + +/// Data that provides information about the token +class TokenData with _$TokenData { + const factory TokenData({ + /// Unique identifier of the token + required String tokenId, + + /// Timestamp when token was created + @JsonKey(name: 'created') required String createdDateTime, + + /// Type of the token + required TokenType type, + + /// Whether or not the object exists in livemode + required bool livemode, + + /// Bank account data + BankAccount? bankAccount, + + /// Card data + CardData? card, + }) = _TokenData; + + factory TokenData.fromJson(Map json) => + _$TokenDataFromJson(json); +} + +@freezed + +/// Card data associated with the token +class CardData with _$CardData { + @JsonSerializable(explicitToJson: true) + const factory CardData({ + /// The brand associated to the card e.g. (visa, amex). + required String brand, + + /// Two letter iso code. + String? country, + + /// The three letter ISO 4217 code for the currency. + String? currency, + + /// four digit number representing the year of expiry of the card. + int? expYear, + + /// two digit number representing the month of expire of the card. + int? expMonth, + + /// Fullname of the cardholder + String? name, + + /// card funding type e.g. (credit, debit). + String? funding, + + /// last four digits of the card. + String? last4, + + /// Address of the cardholder + Address? address, + }) = _CardData; + + factory CardData.fromJson(Map json) => + _$CardDataFromJson(json); +} + +@freezed + +/// Bank account data related to the token +class BankAccount with _$BankAccount { + const factory BankAccount({ + /// Entity that is holder of the account. + required BankAccountHolderType accountHolderType, + + /// Status of the bank account. + required BankAccountStatus status, + + /// Name of the bank where the account is registered. + String? bankName, + + /// Full name of the account holder + String? accountHolderName, + + /// 2 letter code of the country where the account is located + String? country, + + /// The three letter ISO 4217 code for the currency. + String? currency, + + /// The routing number of the bank account (e.g. needer for US accounts). + String? routingNumber, + }) = _BankAccount; + + factory BankAccount.fromJson(Map json) => + _$BankAccountFromJson(json); +} + +/// Entity that is holder of the account +enum BankAccountHolderType { + /// Company. + Company, + + /// Individual. + Individual, + + /// Entity cannot be determined. + Unknown, +} + +/// Verfication status of the bankaccount. +enum BankAccountStatus { + /// Validation has some errors + Errored, + + /// Seen as a new bankaccount + New, + + /// Bankaccount is validated + Validated, + + /// Failed to verify bankaccount + VerificationFailed, + + /// Bankaccount is verified + Verified, + + /// Status cannot be determined + Unknown +} + +/// Type of token +enum TokenType { Card } diff --git a/packages/stripe_platform_interface/lib/src/models/create_token_data.freezed.dart b/packages/stripe_platform_interface/lib/src/models/create_token_data.freezed.dart new file mode 100644 index 000000000..fed8d2836 --- /dev/null +++ b/packages/stripe_platform_interface/lib/src/models/create_token_data.freezed.dart @@ -0,0 +1,1317 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides + +part of 'create_token_data.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more informations: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); + +CreateTokenParams _$CreateTokenParamsFromJson(Map json) { + return _CreateTokenParams.fromJson(json); +} + +/// @nodoc +class _$CreateTokenParamsTearOff { + const _$CreateTokenParamsTearOff(); + + _CreateTokenParams call({TokenType type = TokenType.Card, Address? address}) { + return _CreateTokenParams( + type: type, + address: address, + ); + } + + CreateTokenParams fromJson(Map json) { + return CreateTokenParams.fromJson(json); + } +} + +/// @nodoc +const $CreateTokenParams = _$CreateTokenParamsTearOff(); + +/// @nodoc +mixin _$CreateTokenParams { + /// Type of token. + TokenType get type => throw _privateConstructorUsedError; + + /// Additional address details + Address? get address => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $CreateTokenParamsCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $CreateTokenParamsCopyWith<$Res> { + factory $CreateTokenParamsCopyWith( + CreateTokenParams value, $Res Function(CreateTokenParams) then) = + _$CreateTokenParamsCopyWithImpl<$Res>; + $Res call({TokenType type, Address? address}); + + $AddressCopyWith<$Res>? get address; +} + +/// @nodoc +class _$CreateTokenParamsCopyWithImpl<$Res> + implements $CreateTokenParamsCopyWith<$Res> { + _$CreateTokenParamsCopyWithImpl(this._value, this._then); + + final CreateTokenParams _value; + // ignore: unused_field + final $Res Function(CreateTokenParams) _then; + + @override + $Res call({ + Object? type = freezed, + Object? address = freezed, + }) { + return _then(_value.copyWith( + type: type == freezed + ? _value.type + : type // ignore: cast_nullable_to_non_nullable + as TokenType, + address: address == freezed + ? _value.address + : address // ignore: cast_nullable_to_non_nullable + as Address?, + )); + } + + @override + $AddressCopyWith<$Res>? get address { + if (_value.address == null) { + return null; + } + + return $AddressCopyWith<$Res>(_value.address!, (value) { + return _then(_value.copyWith(address: value)); + }); + } +} + +/// @nodoc +abstract class _$CreateTokenParamsCopyWith<$Res> + implements $CreateTokenParamsCopyWith<$Res> { + factory _$CreateTokenParamsCopyWith( + _CreateTokenParams value, $Res Function(_CreateTokenParams) then) = + __$CreateTokenParamsCopyWithImpl<$Res>; + @override + $Res call({TokenType type, Address? address}); + + @override + $AddressCopyWith<$Res>? get address; +} + +/// @nodoc +class __$CreateTokenParamsCopyWithImpl<$Res> + extends _$CreateTokenParamsCopyWithImpl<$Res> + implements _$CreateTokenParamsCopyWith<$Res> { + __$CreateTokenParamsCopyWithImpl( + _CreateTokenParams _value, $Res Function(_CreateTokenParams) _then) + : super(_value, (v) => _then(v as _CreateTokenParams)); + + @override + _CreateTokenParams get _value => super._value as _CreateTokenParams; + + @override + $Res call({ + Object? type = freezed, + Object? address = freezed, + }) { + return _then(_CreateTokenParams( + type: type == freezed + ? _value.type + : type // ignore: cast_nullable_to_non_nullable + as TokenType, + address: address == freezed + ? _value.address + : address // ignore: cast_nullable_to_non_nullable + as Address?, + )); + } +} + +@JsonSerializable() + +/// @nodoc +class _$_CreateTokenParams implements _CreateTokenParams { + const _$_CreateTokenParams({this.type = TokenType.Card, this.address}); + + factory _$_CreateTokenParams.fromJson(Map json) => + _$_$_CreateTokenParamsFromJson(json); + + @JsonKey(defaultValue: TokenType.Card) + @override + + /// Type of token. + final TokenType type; + @override + + /// Additional address details + final Address? address; + + @override + String toString() { + return 'CreateTokenParams(type: $type, address: $address)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other is _CreateTokenParams && + (identical(other.type, type) || + const DeepCollectionEquality().equals(other.type, type)) && + (identical(other.address, address) || + const DeepCollectionEquality().equals(other.address, address))); + } + + @override + int get hashCode => + runtimeType.hashCode ^ + const DeepCollectionEquality().hash(type) ^ + const DeepCollectionEquality().hash(address); + + @JsonKey(ignore: true) + @override + _$CreateTokenParamsCopyWith<_CreateTokenParams> get copyWith => + __$CreateTokenParamsCopyWithImpl<_CreateTokenParams>(this, _$identity); + + @override + Map toJson() { + return _$_$_CreateTokenParamsToJson(this); + } +} + +abstract class _CreateTokenParams implements CreateTokenParams { + const factory _CreateTokenParams({TokenType type, Address? address}) = + _$_CreateTokenParams; + + factory _CreateTokenParams.fromJson(Map json) = + _$_CreateTokenParams.fromJson; + + @override + + /// Type of token. + TokenType get type => throw _privateConstructorUsedError; + @override + + /// Additional address details + Address? get address => throw _privateConstructorUsedError; + @override + @JsonKey(ignore: true) + _$CreateTokenParamsCopyWith<_CreateTokenParams> get copyWith => + throw _privateConstructorUsedError; +} + +TokenData _$TokenDataFromJson(Map json) { + return _TokenData.fromJson(json); +} + +/// @nodoc +class _$TokenDataTearOff { + const _$TokenDataTearOff(); + + _TokenData call( + {required String tokenId, + @JsonKey(name: 'created') required String createdDateTime, + required TokenType type, + required bool livemode, + BankAccount? bankAccount, + CardData? card}) { + return _TokenData( + tokenId: tokenId, + createdDateTime: createdDateTime, + type: type, + livemode: livemode, + bankAccount: bankAccount, + card: card, + ); + } + + TokenData fromJson(Map json) { + return TokenData.fromJson(json); + } +} + +/// @nodoc +const $TokenData = _$TokenDataTearOff(); + +/// @nodoc +mixin _$TokenData { + /// Unique identifier of the token + String get tokenId => throw _privateConstructorUsedError; + + /// Timestamp when token was created + @JsonKey(name: 'created') + String get createdDateTime => throw _privateConstructorUsedError; + + /// Type of the token + TokenType get type => throw _privateConstructorUsedError; + + /// Whether or not the object exists in livemode + bool get livemode => throw _privateConstructorUsedError; + + /// Bank account data + BankAccount? get bankAccount => throw _privateConstructorUsedError; + + /// Card data + CardData? get card => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $TokenDataCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $TokenDataCopyWith<$Res> { + factory $TokenDataCopyWith(TokenData value, $Res Function(TokenData) then) = + _$TokenDataCopyWithImpl<$Res>; + $Res call( + {String tokenId, + @JsonKey(name: 'created') String createdDateTime, + TokenType type, + bool livemode, + BankAccount? bankAccount, + CardData? card}); + + $BankAccountCopyWith<$Res>? get bankAccount; + $CardDataCopyWith<$Res>? get card; +} + +/// @nodoc +class _$TokenDataCopyWithImpl<$Res> implements $TokenDataCopyWith<$Res> { + _$TokenDataCopyWithImpl(this._value, this._then); + + final TokenData _value; + // ignore: unused_field + final $Res Function(TokenData) _then; + + @override + $Res call({ + Object? tokenId = freezed, + Object? createdDateTime = freezed, + Object? type = freezed, + Object? livemode = freezed, + Object? bankAccount = freezed, + Object? card = freezed, + }) { + return _then(_value.copyWith( + tokenId: tokenId == freezed + ? _value.tokenId + : tokenId // ignore: cast_nullable_to_non_nullable + as String, + createdDateTime: createdDateTime == freezed + ? _value.createdDateTime + : createdDateTime // ignore: cast_nullable_to_non_nullable + as String, + type: type == freezed + ? _value.type + : type // ignore: cast_nullable_to_non_nullable + as TokenType, + livemode: livemode == freezed + ? _value.livemode + : livemode // ignore: cast_nullable_to_non_nullable + as bool, + bankAccount: bankAccount == freezed + ? _value.bankAccount + : bankAccount // ignore: cast_nullable_to_non_nullable + as BankAccount?, + card: card == freezed + ? _value.card + : card // ignore: cast_nullable_to_non_nullable + as CardData?, + )); + } + + @override + $BankAccountCopyWith<$Res>? get bankAccount { + if (_value.bankAccount == null) { + return null; + } + + return $BankAccountCopyWith<$Res>(_value.bankAccount!, (value) { + return _then(_value.copyWith(bankAccount: value)); + }); + } + + @override + $CardDataCopyWith<$Res>? get card { + if (_value.card == null) { + return null; + } + + return $CardDataCopyWith<$Res>(_value.card!, (value) { + return _then(_value.copyWith(card: value)); + }); + } +} + +/// @nodoc +abstract class _$TokenDataCopyWith<$Res> implements $TokenDataCopyWith<$Res> { + factory _$TokenDataCopyWith( + _TokenData value, $Res Function(_TokenData) then) = + __$TokenDataCopyWithImpl<$Res>; + @override + $Res call( + {String tokenId, + @JsonKey(name: 'created') String createdDateTime, + TokenType type, + bool livemode, + BankAccount? bankAccount, + CardData? card}); + + @override + $BankAccountCopyWith<$Res>? get bankAccount; + @override + $CardDataCopyWith<$Res>? get card; +} + +/// @nodoc +class __$TokenDataCopyWithImpl<$Res> extends _$TokenDataCopyWithImpl<$Res> + implements _$TokenDataCopyWith<$Res> { + __$TokenDataCopyWithImpl(_TokenData _value, $Res Function(_TokenData) _then) + : super(_value, (v) => _then(v as _TokenData)); + + @override + _TokenData get _value => super._value as _TokenData; + + @override + $Res call({ + Object? tokenId = freezed, + Object? createdDateTime = freezed, + Object? type = freezed, + Object? livemode = freezed, + Object? bankAccount = freezed, + Object? card = freezed, + }) { + return _then(_TokenData( + tokenId: tokenId == freezed + ? _value.tokenId + : tokenId // ignore: cast_nullable_to_non_nullable + as String, + createdDateTime: createdDateTime == freezed + ? _value.createdDateTime + : createdDateTime // ignore: cast_nullable_to_non_nullable + as String, + type: type == freezed + ? _value.type + : type // ignore: cast_nullable_to_non_nullable + as TokenType, + livemode: livemode == freezed + ? _value.livemode + : livemode // ignore: cast_nullable_to_non_nullable + as bool, + bankAccount: bankAccount == freezed + ? _value.bankAccount + : bankAccount // ignore: cast_nullable_to_non_nullable + as BankAccount?, + card: card == freezed + ? _value.card + : card // ignore: cast_nullable_to_non_nullable + as CardData?, + )); + } +} + +@JsonSerializable() + +/// @nodoc +class _$_TokenData implements _TokenData { + const _$_TokenData( + {required this.tokenId, + @JsonKey(name: 'created') required this.createdDateTime, + required this.type, + required this.livemode, + this.bankAccount, + this.card}); + + factory _$_TokenData.fromJson(Map json) => + _$_$_TokenDataFromJson(json); + + @override + + /// Unique identifier of the token + final String tokenId; + @override + + /// Timestamp when token was created + @JsonKey(name: 'created') + final String createdDateTime; + @override + + /// Type of the token + final TokenType type; + @override + + /// Whether or not the object exists in livemode + final bool livemode; + @override + + /// Bank account data + final BankAccount? bankAccount; + @override + + /// Card data + final CardData? card; + + @override + String toString() { + return 'TokenData(tokenId: $tokenId, createdDateTime: $createdDateTime, type: $type, livemode: $livemode, bankAccount: $bankAccount, card: $card)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other is _TokenData && + (identical(other.tokenId, tokenId) || + const DeepCollectionEquality() + .equals(other.tokenId, tokenId)) && + (identical(other.createdDateTime, createdDateTime) || + const DeepCollectionEquality() + .equals(other.createdDateTime, createdDateTime)) && + (identical(other.type, type) || + const DeepCollectionEquality().equals(other.type, type)) && + (identical(other.livemode, livemode) || + const DeepCollectionEquality() + .equals(other.livemode, livemode)) && + (identical(other.bankAccount, bankAccount) || + const DeepCollectionEquality() + .equals(other.bankAccount, bankAccount)) && + (identical(other.card, card) || + const DeepCollectionEquality().equals(other.card, card))); + } + + @override + int get hashCode => + runtimeType.hashCode ^ + const DeepCollectionEquality().hash(tokenId) ^ + const DeepCollectionEquality().hash(createdDateTime) ^ + const DeepCollectionEquality().hash(type) ^ + const DeepCollectionEquality().hash(livemode) ^ + const DeepCollectionEquality().hash(bankAccount) ^ + const DeepCollectionEquality().hash(card); + + @JsonKey(ignore: true) + @override + _$TokenDataCopyWith<_TokenData> get copyWith => + __$TokenDataCopyWithImpl<_TokenData>(this, _$identity); + + @override + Map toJson() { + return _$_$_TokenDataToJson(this); + } +} + +abstract class _TokenData implements TokenData { + const factory _TokenData( + {required String tokenId, + @JsonKey(name: 'created') required String createdDateTime, + required TokenType type, + required bool livemode, + BankAccount? bankAccount, + CardData? card}) = _$_TokenData; + + factory _TokenData.fromJson(Map json) = + _$_TokenData.fromJson; + + @override + + /// Unique identifier of the token + String get tokenId => throw _privateConstructorUsedError; + @override + + /// Timestamp when token was created + @JsonKey(name: 'created') + String get createdDateTime => throw _privateConstructorUsedError; + @override + + /// Type of the token + TokenType get type => throw _privateConstructorUsedError; + @override + + /// Whether or not the object exists in livemode + bool get livemode => throw _privateConstructorUsedError; + @override + + /// Bank account data + BankAccount? get bankAccount => throw _privateConstructorUsedError; + @override + + /// Card data + CardData? get card => throw _privateConstructorUsedError; + @override + @JsonKey(ignore: true) + _$TokenDataCopyWith<_TokenData> get copyWith => + throw _privateConstructorUsedError; +} + +CardData _$CardDataFromJson(Map json) { + return _CardData.fromJson(json); +} + +/// @nodoc +class _$CardDataTearOff { + const _$CardDataTearOff(); + + _CardData call( + {required String brand, + String? country, + String? currency, + int? expYear, + int? expMonth, + String? name, + String? funding, + String? last4, + Address? address}) { + return _CardData( + brand: brand, + country: country, + currency: currency, + expYear: expYear, + expMonth: expMonth, + name: name, + funding: funding, + last4: last4, + address: address, + ); + } + + CardData fromJson(Map json) { + return CardData.fromJson(json); + } +} + +/// @nodoc +const $CardData = _$CardDataTearOff(); + +/// @nodoc +mixin _$CardData { + /// The brand associated to the card e.g. (visa, amex). + String get brand => throw _privateConstructorUsedError; + + /// Two letter iso code. + String? get country => throw _privateConstructorUsedError; + + /// The three letter ISO 4217 code for the currency. + String? get currency => throw _privateConstructorUsedError; + + /// four digit number representing the year of expiry of the card. + int? get expYear => throw _privateConstructorUsedError; + + /// two digit number representing the month of expire of the card. + int? get expMonth => throw _privateConstructorUsedError; + + /// Fullname of the cardholder + String? get name => throw _privateConstructorUsedError; + + /// card funding type e.g. (credit, debit). + String? get funding => throw _privateConstructorUsedError; + + /// last four digits of the card. + String? get last4 => throw _privateConstructorUsedError; + + /// Address of the cardholder + Address? get address => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $CardDataCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $CardDataCopyWith<$Res> { + factory $CardDataCopyWith(CardData value, $Res Function(CardData) then) = + _$CardDataCopyWithImpl<$Res>; + $Res call( + {String brand, + String? country, + String? currency, + int? expYear, + int? expMonth, + String? name, + String? funding, + String? last4, + Address? address}); + + $AddressCopyWith<$Res>? get address; +} + +/// @nodoc +class _$CardDataCopyWithImpl<$Res> implements $CardDataCopyWith<$Res> { + _$CardDataCopyWithImpl(this._value, this._then); + + final CardData _value; + // ignore: unused_field + final $Res Function(CardData) _then; + + @override + $Res call({ + Object? brand = freezed, + Object? country = freezed, + Object? currency = freezed, + Object? expYear = freezed, + Object? expMonth = freezed, + Object? name = freezed, + Object? funding = freezed, + Object? last4 = freezed, + Object? address = freezed, + }) { + return _then(_value.copyWith( + brand: brand == freezed + ? _value.brand + : brand // ignore: cast_nullable_to_non_nullable + as String, + country: country == freezed + ? _value.country + : country // ignore: cast_nullable_to_non_nullable + as String?, + currency: currency == freezed + ? _value.currency + : currency // ignore: cast_nullable_to_non_nullable + as String?, + expYear: expYear == freezed + ? _value.expYear + : expYear // ignore: cast_nullable_to_non_nullable + as int?, + expMonth: expMonth == freezed + ? _value.expMonth + : expMonth // ignore: cast_nullable_to_non_nullable + as int?, + name: name == freezed + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String?, + funding: funding == freezed + ? _value.funding + : funding // ignore: cast_nullable_to_non_nullable + as String?, + last4: last4 == freezed + ? _value.last4 + : last4 // ignore: cast_nullable_to_non_nullable + as String?, + address: address == freezed + ? _value.address + : address // ignore: cast_nullable_to_non_nullable + as Address?, + )); + } + + @override + $AddressCopyWith<$Res>? get address { + if (_value.address == null) { + return null; + } + + return $AddressCopyWith<$Res>(_value.address!, (value) { + return _then(_value.copyWith(address: value)); + }); + } +} + +/// @nodoc +abstract class _$CardDataCopyWith<$Res> implements $CardDataCopyWith<$Res> { + factory _$CardDataCopyWith(_CardData value, $Res Function(_CardData) then) = + __$CardDataCopyWithImpl<$Res>; + @override + $Res call( + {String brand, + String? country, + String? currency, + int? expYear, + int? expMonth, + String? name, + String? funding, + String? last4, + Address? address}); + + @override + $AddressCopyWith<$Res>? get address; +} + +/// @nodoc +class __$CardDataCopyWithImpl<$Res> extends _$CardDataCopyWithImpl<$Res> + implements _$CardDataCopyWith<$Res> { + __$CardDataCopyWithImpl(_CardData _value, $Res Function(_CardData) _then) + : super(_value, (v) => _then(v as _CardData)); + + @override + _CardData get _value => super._value as _CardData; + + @override + $Res call({ + Object? brand = freezed, + Object? country = freezed, + Object? currency = freezed, + Object? expYear = freezed, + Object? expMonth = freezed, + Object? name = freezed, + Object? funding = freezed, + Object? last4 = freezed, + Object? address = freezed, + }) { + return _then(_CardData( + brand: brand == freezed + ? _value.brand + : brand // ignore: cast_nullable_to_non_nullable + as String, + country: country == freezed + ? _value.country + : country // ignore: cast_nullable_to_non_nullable + as String?, + currency: currency == freezed + ? _value.currency + : currency // ignore: cast_nullable_to_non_nullable + as String?, + expYear: expYear == freezed + ? _value.expYear + : expYear // ignore: cast_nullable_to_non_nullable + as int?, + expMonth: expMonth == freezed + ? _value.expMonth + : expMonth // ignore: cast_nullable_to_non_nullable + as int?, + name: name == freezed + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String?, + funding: funding == freezed + ? _value.funding + : funding // ignore: cast_nullable_to_non_nullable + as String?, + last4: last4 == freezed + ? _value.last4 + : last4 // ignore: cast_nullable_to_non_nullable + as String?, + address: address == freezed + ? _value.address + : address // ignore: cast_nullable_to_non_nullable + as Address?, + )); + } +} + +@JsonSerializable(explicitToJson: true) + +/// @nodoc +class _$_CardData implements _CardData { + const _$_CardData( + {required this.brand, + this.country, + this.currency, + this.expYear, + this.expMonth, + this.name, + this.funding, + this.last4, + this.address}); + + factory _$_CardData.fromJson(Map json) => + _$_$_CardDataFromJson(json); + + @override + + /// The brand associated to the card e.g. (visa, amex). + final String brand; + @override + + /// Two letter iso code. + final String? country; + @override + + /// The three letter ISO 4217 code for the currency. + final String? currency; + @override + + /// four digit number representing the year of expiry of the card. + final int? expYear; + @override + + /// two digit number representing the month of expire of the card. + final int? expMonth; + @override + + /// Fullname of the cardholder + final String? name; + @override + + /// card funding type e.g. (credit, debit). + final String? funding; + @override + + /// last four digits of the card. + final String? last4; + @override + + /// Address of the cardholder + final Address? address; + + @override + String toString() { + return 'CardData(brand: $brand, country: $country, currency: $currency, expYear: $expYear, expMonth: $expMonth, name: $name, funding: $funding, last4: $last4, address: $address)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other is _CardData && + (identical(other.brand, brand) || + const DeepCollectionEquality().equals(other.brand, brand)) && + (identical(other.country, country) || + const DeepCollectionEquality() + .equals(other.country, country)) && + (identical(other.currency, currency) || + const DeepCollectionEquality() + .equals(other.currency, currency)) && + (identical(other.expYear, expYear) || + const DeepCollectionEquality() + .equals(other.expYear, expYear)) && + (identical(other.expMonth, expMonth) || + const DeepCollectionEquality() + .equals(other.expMonth, expMonth)) && + (identical(other.name, name) || + const DeepCollectionEquality().equals(other.name, name)) && + (identical(other.funding, funding) || + const DeepCollectionEquality() + .equals(other.funding, funding)) && + (identical(other.last4, last4) || + const DeepCollectionEquality().equals(other.last4, last4)) && + (identical(other.address, address) || + const DeepCollectionEquality().equals(other.address, address))); + } + + @override + int get hashCode => + runtimeType.hashCode ^ + const DeepCollectionEquality().hash(brand) ^ + const DeepCollectionEquality().hash(country) ^ + const DeepCollectionEquality().hash(currency) ^ + const DeepCollectionEquality().hash(expYear) ^ + const DeepCollectionEquality().hash(expMonth) ^ + const DeepCollectionEquality().hash(name) ^ + const DeepCollectionEquality().hash(funding) ^ + const DeepCollectionEquality().hash(last4) ^ + const DeepCollectionEquality().hash(address); + + @JsonKey(ignore: true) + @override + _$CardDataCopyWith<_CardData> get copyWith => + __$CardDataCopyWithImpl<_CardData>(this, _$identity); + + @override + Map toJson() { + return _$_$_CardDataToJson(this); + } +} + +abstract class _CardData implements CardData { + const factory _CardData( + {required String brand, + String? country, + String? currency, + int? expYear, + int? expMonth, + String? name, + String? funding, + String? last4, + Address? address}) = _$_CardData; + + factory _CardData.fromJson(Map json) = _$_CardData.fromJson; + + @override + + /// The brand associated to the card e.g. (visa, amex). + String get brand => throw _privateConstructorUsedError; + @override + + /// Two letter iso code. + String? get country => throw _privateConstructorUsedError; + @override + + /// The three letter ISO 4217 code for the currency. + String? get currency => throw _privateConstructorUsedError; + @override + + /// four digit number representing the year of expiry of the card. + int? get expYear => throw _privateConstructorUsedError; + @override + + /// two digit number representing the month of expire of the card. + int? get expMonth => throw _privateConstructorUsedError; + @override + + /// Fullname of the cardholder + String? get name => throw _privateConstructorUsedError; + @override + + /// card funding type e.g. (credit, debit). + String? get funding => throw _privateConstructorUsedError; + @override + + /// last four digits of the card. + String? get last4 => throw _privateConstructorUsedError; + @override + + /// Address of the cardholder + Address? get address => throw _privateConstructorUsedError; + @override + @JsonKey(ignore: true) + _$CardDataCopyWith<_CardData> get copyWith => + throw _privateConstructorUsedError; +} + +BankAccount _$BankAccountFromJson(Map json) { + return _BankAccount.fromJson(json); +} + +/// @nodoc +class _$BankAccountTearOff { + const _$BankAccountTearOff(); + + _BankAccount call( + {required BankAccountHolderType accountHolderType, + required BankAccountStatus status, + String? bankName, + String? accountHolderName, + String? country, + String? currency, + String? routingNumber}) { + return _BankAccount( + accountHolderType: accountHolderType, + status: status, + bankName: bankName, + accountHolderName: accountHolderName, + country: country, + currency: currency, + routingNumber: routingNumber, + ); + } + + BankAccount fromJson(Map json) { + return BankAccount.fromJson(json); + } +} + +/// @nodoc +const $BankAccount = _$BankAccountTearOff(); + +/// @nodoc +mixin _$BankAccount { + /// Entity that is holder of the account. + BankAccountHolderType get accountHolderType => + throw _privateConstructorUsedError; + + /// Status of the bank account. + BankAccountStatus get status => throw _privateConstructorUsedError; + + /// Name of the bank where the account is registered. + String? get bankName => throw _privateConstructorUsedError; + + /// Full name of the account holder + String? get accountHolderName => throw _privateConstructorUsedError; + + /// 2 letter code of the country where the account is located + String? get country => throw _privateConstructorUsedError; + + /// The three letter ISO 4217 code for the currency. + String? get currency => throw _privateConstructorUsedError; + + /// The routing number of the bank account (e.g. needer for US accounts). + String? get routingNumber => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $BankAccountCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $BankAccountCopyWith<$Res> { + factory $BankAccountCopyWith( + BankAccount value, $Res Function(BankAccount) then) = + _$BankAccountCopyWithImpl<$Res>; + $Res call( + {BankAccountHolderType accountHolderType, + BankAccountStatus status, + String? bankName, + String? accountHolderName, + String? country, + String? currency, + String? routingNumber}); +} + +/// @nodoc +class _$BankAccountCopyWithImpl<$Res> implements $BankAccountCopyWith<$Res> { + _$BankAccountCopyWithImpl(this._value, this._then); + + final BankAccount _value; + // ignore: unused_field + final $Res Function(BankAccount) _then; + + @override + $Res call({ + Object? accountHolderType = freezed, + Object? status = freezed, + Object? bankName = freezed, + Object? accountHolderName = freezed, + Object? country = freezed, + Object? currency = freezed, + Object? routingNumber = freezed, + }) { + return _then(_value.copyWith( + accountHolderType: accountHolderType == freezed + ? _value.accountHolderType + : accountHolderType // ignore: cast_nullable_to_non_nullable + as BankAccountHolderType, + status: status == freezed + ? _value.status + : status // ignore: cast_nullable_to_non_nullable + as BankAccountStatus, + bankName: bankName == freezed + ? _value.bankName + : bankName // ignore: cast_nullable_to_non_nullable + as String?, + accountHolderName: accountHolderName == freezed + ? _value.accountHolderName + : accountHolderName // ignore: cast_nullable_to_non_nullable + as String?, + country: country == freezed + ? _value.country + : country // ignore: cast_nullable_to_non_nullable + as String?, + currency: currency == freezed + ? _value.currency + : currency // ignore: cast_nullable_to_non_nullable + as String?, + routingNumber: routingNumber == freezed + ? _value.routingNumber + : routingNumber // ignore: cast_nullable_to_non_nullable + as String?, + )); + } +} + +/// @nodoc +abstract class _$BankAccountCopyWith<$Res> + implements $BankAccountCopyWith<$Res> { + factory _$BankAccountCopyWith( + _BankAccount value, $Res Function(_BankAccount) then) = + __$BankAccountCopyWithImpl<$Res>; + @override + $Res call( + {BankAccountHolderType accountHolderType, + BankAccountStatus status, + String? bankName, + String? accountHolderName, + String? country, + String? currency, + String? routingNumber}); +} + +/// @nodoc +class __$BankAccountCopyWithImpl<$Res> extends _$BankAccountCopyWithImpl<$Res> + implements _$BankAccountCopyWith<$Res> { + __$BankAccountCopyWithImpl( + _BankAccount _value, $Res Function(_BankAccount) _then) + : super(_value, (v) => _then(v as _BankAccount)); + + @override + _BankAccount get _value => super._value as _BankAccount; + + @override + $Res call({ + Object? accountHolderType = freezed, + Object? status = freezed, + Object? bankName = freezed, + Object? accountHolderName = freezed, + Object? country = freezed, + Object? currency = freezed, + Object? routingNumber = freezed, + }) { + return _then(_BankAccount( + accountHolderType: accountHolderType == freezed + ? _value.accountHolderType + : accountHolderType // ignore: cast_nullable_to_non_nullable + as BankAccountHolderType, + status: status == freezed + ? _value.status + : status // ignore: cast_nullable_to_non_nullable + as BankAccountStatus, + bankName: bankName == freezed + ? _value.bankName + : bankName // ignore: cast_nullable_to_non_nullable + as String?, + accountHolderName: accountHolderName == freezed + ? _value.accountHolderName + : accountHolderName // ignore: cast_nullable_to_non_nullable + as String?, + country: country == freezed + ? _value.country + : country // ignore: cast_nullable_to_non_nullable + as String?, + currency: currency == freezed + ? _value.currency + : currency // ignore: cast_nullable_to_non_nullable + as String?, + routingNumber: routingNumber == freezed + ? _value.routingNumber + : routingNumber // ignore: cast_nullable_to_non_nullable + as String?, + )); + } +} + +@JsonSerializable() + +/// @nodoc +class _$_BankAccount implements _BankAccount { + const _$_BankAccount( + {required this.accountHolderType, + required this.status, + this.bankName, + this.accountHolderName, + this.country, + this.currency, + this.routingNumber}); + + factory _$_BankAccount.fromJson(Map json) => + _$_$_BankAccountFromJson(json); + + @override + + /// Entity that is holder of the account. + final BankAccountHolderType accountHolderType; + @override + + /// Status of the bank account. + final BankAccountStatus status; + @override + + /// Name of the bank where the account is registered. + final String? bankName; + @override + + /// Full name of the account holder + final String? accountHolderName; + @override + + /// 2 letter code of the country where the account is located + final String? country; + @override + + /// The three letter ISO 4217 code for the currency. + final String? currency; + @override + + /// The routing number of the bank account (e.g. needer for US accounts). + final String? routingNumber; + + @override + String toString() { + return 'BankAccount(accountHolderType: $accountHolderType, status: $status, bankName: $bankName, accountHolderName: $accountHolderName, country: $country, currency: $currency, routingNumber: $routingNumber)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other is _BankAccount && + (identical(other.accountHolderType, accountHolderType) || + const DeepCollectionEquality() + .equals(other.accountHolderType, accountHolderType)) && + (identical(other.status, status) || + const DeepCollectionEquality().equals(other.status, status)) && + (identical(other.bankName, bankName) || + const DeepCollectionEquality() + .equals(other.bankName, bankName)) && + (identical(other.accountHolderName, accountHolderName) || + const DeepCollectionEquality() + .equals(other.accountHolderName, accountHolderName)) && + (identical(other.country, country) || + const DeepCollectionEquality() + .equals(other.country, country)) && + (identical(other.currency, currency) || + const DeepCollectionEquality() + .equals(other.currency, currency)) && + (identical(other.routingNumber, routingNumber) || + const DeepCollectionEquality() + .equals(other.routingNumber, routingNumber))); + } + + @override + int get hashCode => + runtimeType.hashCode ^ + const DeepCollectionEquality().hash(accountHolderType) ^ + const DeepCollectionEquality().hash(status) ^ + const DeepCollectionEquality().hash(bankName) ^ + const DeepCollectionEquality().hash(accountHolderName) ^ + const DeepCollectionEquality().hash(country) ^ + const DeepCollectionEquality().hash(currency) ^ + const DeepCollectionEquality().hash(routingNumber); + + @JsonKey(ignore: true) + @override + _$BankAccountCopyWith<_BankAccount> get copyWith => + __$BankAccountCopyWithImpl<_BankAccount>(this, _$identity); + + @override + Map toJson() { + return _$_$_BankAccountToJson(this); + } +} + +abstract class _BankAccount implements BankAccount { + const factory _BankAccount( + {required BankAccountHolderType accountHolderType, + required BankAccountStatus status, + String? bankName, + String? accountHolderName, + String? country, + String? currency, + String? routingNumber}) = _$_BankAccount; + + factory _BankAccount.fromJson(Map json) = + _$_BankAccount.fromJson; + + @override + + /// Entity that is holder of the account. + BankAccountHolderType get accountHolderType => + throw _privateConstructorUsedError; + @override + + /// Status of the bank account. + BankAccountStatus get status => throw _privateConstructorUsedError; + @override + + /// Name of the bank where the account is registered. + String? get bankName => throw _privateConstructorUsedError; + @override + + /// Full name of the account holder + String? get accountHolderName => throw _privateConstructorUsedError; + @override + + /// 2 letter code of the country where the account is located + String? get country => throw _privateConstructorUsedError; + @override + + /// The three letter ISO 4217 code for the currency. + String? get currency => throw _privateConstructorUsedError; + @override + + /// The routing number of the bank account (e.g. needer for US accounts). + String? get routingNumber => throw _privateConstructorUsedError; + @override + @JsonKey(ignore: true) + _$BankAccountCopyWith<_BankAccount> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/packages/stripe_platform_interface/lib/src/models/create_token_data.g.dart b/packages/stripe_platform_interface/lib/src/models/create_token_data.g.dart new file mode 100644 index 000000000..f7d9ca7af --- /dev/null +++ b/packages/stripe_platform_interface/lib/src/models/create_token_data.g.dart @@ -0,0 +1,159 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'create_token_data.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$_CreateTokenParams _$_$_CreateTokenParamsFromJson(Map json) { + return _$_CreateTokenParams( + type: _$enumDecodeNullable(_$TokenTypeEnumMap, json['type']) ?? + TokenType.Card, + address: json['address'] == null + ? null + : Address.fromJson(json['address'] as Map), + ); +} + +Map _$_$_CreateTokenParamsToJson( + _$_CreateTokenParams instance) => + { + 'type': _$TokenTypeEnumMap[instance.type], + 'address': instance.address, + }; + +K _$enumDecode( + Map enumValues, + Object? source, { + K? unknownValue, +}) { + if (source == null) { + throw ArgumentError( + 'A value must be provided. Supported values: ' + '${enumValues.values.join(', ')}', + ); + } + + return enumValues.entries.singleWhere( + (e) => e.value == source, + orElse: () { + if (unknownValue == null) { + throw ArgumentError( + '`$source` is not one of the supported values: ' + '${enumValues.values.join(', ')}', + ); + } + return MapEntry(unknownValue, enumValues.values.first); + }, + ).key; +} + +K? _$enumDecodeNullable( + Map enumValues, + dynamic source, { + K? unknownValue, +}) { + if (source == null) { + return null; + } + return _$enumDecode(enumValues, source, unknownValue: unknownValue); +} + +const _$TokenTypeEnumMap = { + TokenType.Card: 'Card', +}; + +_$_TokenData _$_$_TokenDataFromJson(Map json) { + return _$_TokenData( + tokenId: json['tokenId'] as String, + createdDateTime: json['created'] as String, + type: _$enumDecode(_$TokenTypeEnumMap, json['type']), + livemode: json['livemode'] as bool, + bankAccount: json['bankAccount'] == null + ? null + : BankAccount.fromJson(json['bankAccount'] as Map), + card: json['card'] == null + ? null + : CardData.fromJson(json['card'] as Map), + ); +} + +Map _$_$_TokenDataToJson(_$_TokenData instance) => + { + 'tokenId': instance.tokenId, + 'created': instance.createdDateTime, + 'type': _$TokenTypeEnumMap[instance.type], + 'livemode': instance.livemode, + 'bankAccount': instance.bankAccount, + 'card': instance.card, + }; + +_$_CardData _$_$_CardDataFromJson(Map json) { + return _$_CardData( + brand: json['brand'] as String, + country: json['country'] as String?, + currency: json['currency'] as String?, + expYear: json['expYear'] as int?, + expMonth: json['expMonth'] as int?, + name: json['name'] as String?, + funding: json['funding'] as String?, + last4: json['last4'] as String?, + address: json['address'] == null + ? null + : Address.fromJson(json['address'] as Map), + ); +} + +Map _$_$_CardDataToJson(_$_CardData instance) => + { + 'brand': instance.brand, + 'country': instance.country, + 'currency': instance.currency, + 'expYear': instance.expYear, + 'expMonth': instance.expMonth, + 'name': instance.name, + 'funding': instance.funding, + 'last4': instance.last4, + 'address': instance.address?.toJson(), + }; + +_$_BankAccount _$_$_BankAccountFromJson(Map json) { + return _$_BankAccount( + accountHolderType: + _$enumDecode(_$BankAccountHolderTypeEnumMap, json['accountHolderType']), + status: _$enumDecode(_$BankAccountStatusEnumMap, json['status']), + bankName: json['bankName'] as String?, + accountHolderName: json['accountHolderName'] as String?, + country: json['country'] as String?, + currency: json['currency'] as String?, + routingNumber: json['routingNumber'] as String?, + ); +} + +Map _$_$_BankAccountToJson(_$_BankAccount instance) => + { + 'accountHolderType': + _$BankAccountHolderTypeEnumMap[instance.accountHolderType], + 'status': _$BankAccountStatusEnumMap[instance.status], + 'bankName': instance.bankName, + 'accountHolderName': instance.accountHolderName, + 'country': instance.country, + 'currency': instance.currency, + 'routingNumber': instance.routingNumber, + }; + +const _$BankAccountHolderTypeEnumMap = { + BankAccountHolderType.Company: 'Company', + BankAccountHolderType.Individual: 'Individual', + BankAccountHolderType.Unknown: 'Unknown', +}; + +const _$BankAccountStatusEnumMap = { + BankAccountStatus.Errored: 'Errored', + BankAccountStatus.New: 'New', + BankAccountStatus.Validated: 'Validated', + BankAccountStatus.VerificationFailed: 'VerificationFailed', + BankAccountStatus.Verified: 'Verified', + BankAccountStatus.Unknown: 'Unknown', +}; diff --git a/packages/stripe_platform_interface/lib/src/models/errors.dart b/packages/stripe_platform_interface/lib/src/models/errors.dart index 743c7a1af..b3cbf4f43 100644 --- a/packages/stripe_platform_interface/lib/src/models/errors.dart +++ b/packages/stripe_platform_interface/lib/src/models/errors.dart @@ -6,6 +6,8 @@ part 'errors.g.dart'; // ignore_for_file: constant_identifier_names enum PaymentIntentError { unknown } +enum CreateTokenError { unknown } + @freezed /// Wrapper class that represents an error with the Stripe platform. diff --git a/packages/stripe_platform_interface/lib/src/stripe_platform_interface.dart b/packages/stripe_platform_interface/lib/src/stripe_platform_interface.dart index cdabd6064..6bfd96a17 100644 --- a/packages/stripe_platform_interface/lib/src/stripe_platform_interface.dart +++ b/packages/stripe_platform_interface/lib/src/stripe_platform_interface.dart @@ -2,6 +2,7 @@ import 'package:plugin_platform_interface/plugin_platform_interface.dart'; import 'method_channel_stripe.dart'; import 'models/apple_pay.dart'; +import 'models/create_token_data.dart'; import 'models/payment_intents.dart'; import 'models/payment_methods.dart'; import 'models/payment_sheet.dart'; @@ -57,6 +58,11 @@ abstract class StripePlatform extends PlatformInterface { Future presentApplePay(ApplePayPresentParams params); Future confirmApplePayPayment(String clientSecret); + + /// Creates a token for card details. + /// + /// Note this method is legacy and it is advised to use [PaymentIntent]. + Future createToken(CreateTokenParams params); Future confirmSetupIntent( String setupIntentClientSecret, PaymentMethodParams data, [Map options = const {}]); diff --git a/packages/stripe_platform_interface/lib/stripe_platform_interface.dart b/packages/stripe_platform_interface/lib/stripe_platform_interface.dart index bb902b700..8d8c842d9 100644 --- a/packages/stripe_platform_interface/lib/stripe_platform_interface.dart +++ b/packages/stripe_platform_interface/lib/stripe_platform_interface.dart @@ -4,6 +4,7 @@ export 'src/models/address.dart'; export 'src/models/app_info.dart'; export 'src/models/apple_pay.dart'; export 'src/models/card_field_input.dart'; +export 'src/models/create_token_data.dart'; export 'src/models/errors.dart'; export 'src/models/payment_intents.dart'; export 'src/models/payment_methods.dart'; diff --git a/packages/stripe_platform_interface/test/method_channel_stripe_test.dart b/packages/stripe_platform_interface/test/method_channel_stripe_test.dart index 7aebe2f5f..041df8853 100644 --- a/packages/stripe_platform_interface/test/method_channel_stripe_test.dart +++ b/packages/stripe_platform_interface/test/method_channel_stripe_test.dart @@ -401,5 +401,53 @@ void main() { expect(completer.isCompleted, true); }); }); + + group('create token', () { + late CreateTokenParams params; + late TokenData result; + + setUp(() { + params = const CreateTokenParams(); + }); + group('When create token succeeds', () { + setUp(() async { + sut = MethodChannelStripe( + platformIsIos: false, + methodChannel: MethodChannelMock( + channelName: methodChannelName, + method: 'createToken', + result: TokenDataTestInstance.create('tokenId').jsonMap()) + .methodChannel, + ); + + result = await sut.createToken(params); + }); + + test('It returns correct data', () { + expect(result, TokenDataTestInstance.create('tokenId')); + }); + }); + + group('When create token fails', () { + setUp(() async { + sut = MethodChannelStripe( + platformIsIos: false, + methodChannel: MethodChannelMock( + channelName: methodChannelName, + method: 'createToken', + result: Exception('whoops')) + .methodChannel, + ); + }); + + test('It returns correct data', () async { + expect( + () async => await sut.createToken(params), + throwsA( + const TypeMatcher>(), + )); + }); + }); + }); }); } diff --git a/packages/stripe_platform_interface/test/test_data.dart b/packages/stripe_platform_interface/test/test_data.dart index c866dc9ad..1d8b6dfe7 100644 --- a/packages/stripe_platform_interface/test/test_data.dart +++ b/packages/stripe_platform_interface/test/test_data.dart @@ -1,4 +1,5 @@ import 'package:flutter/foundation.dart'; +import 'package:stripe_platform_interface/src/models/create_token_data.dart'; import 'package:stripe_platform_interface/src/models/payment_intents.dart'; import 'package:stripe_platform_interface/src/models/payment_methods.dart'; import 'package:stripe_platform_interface/src/models/setup_intent.dart'; @@ -120,3 +121,28 @@ extension SetupIntentTestInstance on SetupIntent { 'lastSetupError': lastSetupError, }; } + +extension TokenDataTestInstance on TokenData { + static TokenData create(String id) => TokenData( + tokenId: id, + createdDateTime: 'createdDateTime', + type: TokenType.Card, + livemode: false, + card: const CardData(brand: 'Visa'), + ); + + Map jsonMap() => { + 'tokenId': tokenId, + 'livemode': livemode, + 'type': describeEnum(type), + 'created': createdDateTime, + 'card': { + 'brand': card?.brand, + 'country': card?.country, + 'expYear': card?.expYear, + 'expMonth': card?.expMonth, + 'funding': card?.funding, + 'last4': card?.last4, + }, + }; +}