From 6b72dfee66beea2373a36dcaa83c19a5a8b59b69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D1=81=D0=BA=D0=B0=D0=BD=D0=B4=D0=B0=D1=80=20=D0=A0?= =?UTF-8?q?=2E=20=D0=A8=D0=B0=D0=B1=D0=B0=D0=B5=D0=B2?= Date: Thu, 8 Sep 2022 11:32:35 +0300 Subject: [PATCH] 1.0.3: Fixed iOS confirmation flow. Refactored `TokenizationResult`, now it's have SuccessTokenizationResult, ErrorTokenizationResult and CanceledTokenizationResult versions. --- .vscode/launch.json | 13 +++ CHANGELOG.md | 11 +++ .../flutter/TokenizationResultExtensions.kt | 1 + .../flutter/YookassaPaymentsFlutterPlugin.kt | 9 +- example/ios/Podfile | 1 + example/lib/success_tokenization_screen.dart | 65 +++++++------- example/lib/tokenization_screen.dart | 43 ++++++---- example/pubspec.lock | 25 ++++-- .../SwiftYookassaPaymentsFlutterPlugin.swift | 86 +++++++++---------- ios/yookassa_payments_flutter.podspec | 2 +- lib/models/payment_method_types.dart | 41 ++++++--- lib/models/tokenization_result.dart | 79 +++++++++++------ lib/yookassa_payments_flutter.dart | 30 ++++--- pubspec.lock | 23 +++-- pubspec.yaml | 2 +- 15 files changed, 267 insertions(+), 164 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 7830690..3e7ea02 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -22,6 +22,19 @@ "--flavor", "dev" ] + }, + { + "name": "demo-debug-prod", + "cwd": "demo", + "request": "launch", + "type": "dart", + "flutterMode": "debug", + "args": [ + "-t", + "lib/main_prod.dart", + "--flavor", + "prod" + ] } ] } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 4466f7e..e507de6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ +# 1.0.3 + +* Fixed iOS confirmation flow. Refactored `TokenizationResult`, now it's have SuccessTokenizationResult, ErrorTokenizationResult and CanceledTokenizationResult versions. +Not to get token from TokenizationResult you need to check it's type: +``` +var result = await YookassaPaymentsFlutter.tokenization(tokenizationModuleInputData); +if (result is SuccessTokenizationResult) { + result.token +} +``` + # 1.0.2 * Made applePayID and moneyAuthClientId fields optional. diff --git a/android/src/main/kotlin/ru/yoomoney/sdk/kassa/payments/flutter/TokenizationResultExtensions.kt b/android/src/main/kotlin/ru/yoomoney/sdk/kassa/payments/flutter/TokenizationResultExtensions.kt index 9c34b94..03e4052 100644 --- a/android/src/main/kotlin/ru/yoomoney/sdk/kassa/payments/flutter/TokenizationResultExtensions.kt +++ b/android/src/main/kotlin/ru/yoomoney/sdk/kassa/payments/flutter/TokenizationResultExtensions.kt @@ -6,6 +6,7 @@ import ru.yoomoney.sdk.kassa.payments.checkoutParameters.PaymentMethodType fun TokenizationResult.toJson(): String { val json = JSONObject() + json.put("status", "success") json.put("paymentToken", paymentToken) json.put("paymentMethodType", when(paymentMethodType) { PaymentMethodType.YOO_MONEY -> "yoo_money" diff --git a/android/src/main/kotlin/ru/yoomoney/sdk/kassa/payments/flutter/YookassaPaymentsFlutterPlugin.kt b/android/src/main/kotlin/ru/yoomoney/sdk/kassa/payments/flutter/YookassaPaymentsFlutterPlugin.kt index 2a7e35e..8f0ff7f 100644 --- a/android/src/main/kotlin/ru/yoomoney/sdk/kassa/payments/flutter/YookassaPaymentsFlutterPlugin.kt +++ b/android/src/main/kotlin/ru/yoomoney/sdk/kassa/payments/flutter/YookassaPaymentsFlutterPlugin.kt @@ -36,6 +36,9 @@ import ru.yoomoney.sdk.kassa.payments.checkoutParameters.TestParameters import ru.yoomoney.sdk.kassa.payments.TokenizationResult import ru.yoomoney.sdk.kassa.payments.checkoutParameters.UiParameters +private const val CANCELED_RESULT = "{\"status\":\"canceled\"}" +private const val ERROR_RESULT = "{\"status\":\"error\"}" + class YookassaPaymentsFlutterPlugin: FlutterPlugin, MethodCallHandler, ActivityAware, PluginRegistry.ActivityResultListener { private lateinit var flutterResult: Result @@ -123,9 +126,13 @@ class YookassaPaymentsFlutterPlugin: FlutterPlugin, MethodCallHandler, ActivityA override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean { if (requestCode == REQUEST_CODE_TOKENIZE) { - if (resultCode == Activity.RESULT_OK && data != null) { + if (resultCode == Activity.RESULT_CANCELED) { + flutterResult.success(CANCELED_RESULT) + } else if (resultCode == Activity.RESULT_OK && data != null) { val result: TokenizationResult = Checkout.createTokenizationResult(data); flutterResult.success(result.toJson()) + } else { + flutterResult.success(ERROR_RESULT) } } else if (requestCode == REQUEST_CODE_CONFIRMATION) { flutterResult.success(resultCode) diff --git a/example/ios/Podfile b/example/ios/Podfile index ca04734..df52c58 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -42,6 +42,7 @@ post_install do |installer| target.build_configurations.each do |config| config.build_settings["ONLY_ACTIVE_ARCH"] = "YES" + config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.0' end end end diff --git a/example/lib/success_tokenization_screen.dart b/example/lib/success_tokenization_screen.dart index c08b63a..b7160f4 100644 --- a/example/lib/success_tokenization_screen.dart +++ b/example/lib/success_tokenization_screen.dart @@ -1,26 +1,29 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:yookassa_payments_flutter/input_data/saved_card_module_input_data.dart'; -import 'package:yookassa_payments_flutter/models/tokenization_result.dart'; import 'package:yookassa_payments_flutter/yookassa_payments_flutter.dart'; class SuccessTokenizationScreen extends StatefulWidget { - const SuccessTokenizationScreen({Key? key, required this.result, this.tokenizationData, this.repeatData}) : super(key: key); + const SuccessTokenizationScreen( + {Key? key, required this.result, this.tokenizationData, this.repeatData}) + : super(key: key); - final TokenizationResult result; + final SuccessTokenizationResult result; final TokenizationModuleInputData? tokenizationData; final SavedBankCardModuleInputData? repeatData; @override - State createState() => SuccessTokenizationScreenState(result, tokenizationData, repeatData); + State createState() => + SuccessTokenizationScreenState(result, tokenizationData, repeatData); } class SuccessTokenizationScreenState extends State { - final TokenizationResult result; + final SuccessTokenizationResult result; final TokenizationModuleInputData? tokenizationData; final SavedBankCardModuleInputData? repeatData; - SuccessTokenizationScreenState(this.result, this.tokenizationData, this.repeatData); + SuccessTokenizationScreenState( + this.result, this.tokenizationData, this.repeatData); late TextEditingController controller; @@ -47,39 +50,41 @@ class SuccessTokenizationScreenState extends State { padding: const EdgeInsets.all(20.0), child: TextField( controller: controller, - decoration: const InputDecoration( - hintText: "3ds / App2App ссылка" - ), + decoration: + const InputDecoration(hintText: "3ds / App2App ссылка"), ), ), ElevatedButton( onPressed: () async { - await YookassaPaymentsFlutter.confirmation(controller.text, result.paymentMethodType); - showDialog(context: context, builder: (context) => const AlertDialog( - content: Text("Confirmation process is done"), - )); + await YookassaPaymentsFlutter.confirmation( + controller.text, result.paymentMethodType); + showDialog( + context: context, + builder: (context) => const AlertDialog( + content: Text("Confirmation process is done"), + )); }, - child: const Text("Подтвердить") - ), + child: const Text("Подтвердить")), TextButton( onPressed: () async { - showDialog(context: context, builder: (context) => AlertDialog( - content: Text(result.token), - actions: [ - TextButton( - onPressed: () { - Clipboard.setData(ClipboardData(text: result.token)); - Navigator.of(context).pop(); - }, - child: const Text('Скопировать'), - ), - ] - )); + showDialog( + context: context, + builder: (context) => AlertDialog( + content: Text(result.token), + actions: [ + TextButton( + onPressed: () { + Clipboard.setData( + ClipboardData(text: result.token)); + Navigator.of(context).pop(); + }, + child: const Text('Скопировать'), + ), + ])); }, - child: const Text("Показать токен") - ) + child: const Text("Показать токен")) ], ), ); } -} \ No newline at end of file +} diff --git a/example/lib/tokenization_screen.dart b/example/lib/tokenization_screen.dart index 9d55497..a5fd011 100644 --- a/example/lib/tokenization_screen.dart +++ b/example/lib/tokenization_screen.dart @@ -1,8 +1,9 @@ import 'package:flutter/material.dart'; import 'package:yookassa_payments_flutter/yookassa_payments_flutter.dart'; import 'package:yookassa_payments_flutter_example/success_tokenization_screen.dart'; +import 'package:yookassa_payments_flutter/models/tokenization_result.dart'; -class TokenizationScreen extends StatefulWidget{ +class TokenizationScreen extends StatefulWidget { const TokenizationScreen({Key? key}) : super(key: key); @override @@ -37,8 +38,7 @@ class TokenizationScreenState extends State { onPressed: () async { startTokenization(); }, - child: const Text("Оплатить") - ) + child: const Text("Оплатить")) ], ), ); @@ -46,7 +46,8 @@ class TokenizationScreenState extends State { void startTokenization() async { var clientApplicationKey = "<Ключ для клиентских приложений>"; - var amount = Amount(value: double.parse(controller.text), currency: Currency.rub); + var amount = + Amount(value: double.parse(controller.text), currency: Currency.rub); var moneyAuthClientId = ""; var shopId = "<Идентификатор магазина в ЮKassa>"; var applicationScheme = "<Схема вашего приложения для deeplink>" "://"; @@ -61,16 +62,26 @@ class TokenizationScreenState extends State { shopId: shopId, customerId: "<Уникальный идентификатор покупателя>", applicationScheme: applicationScheme, - tokenizationSettings: const TokenizationSettings( - PaymentMethodTypes([ - PaymentMethod.bankCard, - PaymentMethod.yooMoney, - PaymentMethod.sberbank - ]) - ), - testModeSettings: null - ); - var result = await YookassaPaymentsFlutter.tokenization(tokenizationModuleInputData); - Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) => SuccessTokenizationScreen(result: result, tokenizationData: tokenizationModuleInputData))); + tokenizationSettings: const TokenizationSettings(PaymentMethodTypes([ + PaymentMethod.bankCard, + PaymentMethod.yooMoney, + PaymentMethod.sberbank + ])), + testModeSettings: null); + var result = + await YookassaPaymentsFlutter.tokenization(tokenizationModuleInputData); + if (result is SuccessTokenizationResult) { + Navigator.push( + context, + MaterialPageRoute( + builder: (BuildContext context) => SuccessTokenizationScreen( + result: result, + tokenizationData: tokenizationModuleInputData))); + } else if (result is ErrorTokenizationResult) { + showDialog( + context: context, + builder: (context) => AlertDialog(content: Text(result.error))); + return; + } } -} \ No newline at end of file +} diff --git a/example/pubspec.lock b/example/pubspec.lock index 09397f3..4dc2fde 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -42,7 +42,7 @@ packages: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.16.0" + version: "1.15.0" cupertino_icons: dependency: "direct main" description: @@ -56,7 +56,7 @@ packages: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.3.0" + version: "1.2.0" flutter: dependency: "direct main" description: flutter @@ -94,7 +94,7 @@ packages: name: material_color_utilities url: "https://pub.dartlang.org" source: hosted - version: "0.1.4" + version: "0.1.3" meta: dependency: transitive description: @@ -108,7 +108,7 @@ packages: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.8.1" + version: "1.8.0" sky_engine: dependency: transitive description: flutter @@ -120,7 +120,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.2" + version: "1.8.1" stack_trace: dependency: transitive description: @@ -155,21 +155,28 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.4.9" + version: "0.4.8" + typed_data: + dependency: transitive + description: + name: typed_data + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.0" vector_math: dependency: transitive description: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.2" + version: "2.1.1" yookassa_payments_flutter: dependency: "direct main" description: path: ".." relative: true source: path - version: "1.0.0" + version: "1.0.2" sdks: - dart: ">=2.17.0-0 <3.0.0" + dart: ">=2.14.0 <3.0.0" flutter: ">=2.10.5" diff --git a/ios/Classes/SwiftYookassaPaymentsFlutterPlugin.swift b/ios/Classes/SwiftYookassaPaymentsFlutterPlugin.swift index 6886356..708129e 100644 --- a/ios/Classes/SwiftYookassaPaymentsFlutterPlugin.swift +++ b/ios/Classes/SwiftYookassaPaymentsFlutterPlugin.swift @@ -9,6 +9,7 @@ var flutterController: FlutterViewController? var yoomoneyController: UIViewController? public class SwiftYookassaPaymentsFlutterPlugin: NSObject, FlutterPlugin { + public static func register(with registrar: FlutterPluginRegistrar) { let channel = FlutterMethodChannel(name: "ru.yoomoney.yookassa_payments_flutter/yoomoney", binaryMessenger: registrar.messenger()) let instance = SwiftYookassaPaymentsFlutterPlugin() @@ -18,26 +19,31 @@ public class SwiftYookassaPaymentsFlutterPlugin: NSObject, FlutterPlugin { public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { flutterResult = result + // Tokenezation Flow + if (call.method == YooMoneyService.tokenization.rawValue) { - guard let data = call.arguments as? [String:AnyObject], - let jsonData = try? JSONSerialization.data(withJSONObject: data, options: .prettyPrinted), - let tokenizationModuleInputData = try? JSONDecoder().decode(TokenizationModuleInputData.self, from: jsonData) - else { - result(YooMoneyErrors.tokenizationData.rawValue) - return - } + guard let data = call.arguments as? [String:AnyObject], + let jsonData = try? JSONSerialization.data(withJSONObject: data, options: .prettyPrinted), + let tokenizationModuleInputData = try? JSONDecoder().decode(TokenizationModuleInputData.self, from: jsonData) + else { + result(YooMoneyErrors.tokenizationData.rawValue) + return + } + + let controller = UIApplication.shared.delegate?.window??.rootViewController as? FlutterViewController + let inputData: TokenizationFlow = .tokenization(tokenizationModuleInputData) - let inputData: TokenizationFlow = .tokenization(tokenizationModuleInputData) + if let flutterVC = controller { + let tokenezationViewController = TokenizationAssembly.makeModule(inputData: inputData, moduleOutput: flutterVC) + yoomoneyController = tokenezationViewController; + flutterController = flutterVC; - let controller = UIApplication.shared.delegate?.window??.rootViewController as! FlutterViewController - - let vc = TokenizationAssembly.makeModule(inputData: inputData, moduleOutput: controller) - controller.present(vc, animated: true, completion: nil) - - flutterController = controller - yoomoneyController = vc + flutterVC.present(tokenezationViewController, animated: true, completion: nil) + } } + // Confirmation Flow + if (call.method == YooMoneyService.confirmation.rawValue) { guard let data = call.arguments as? [String:AnyObject], let jsonData = try? JSONSerialization.data(withJSONObject: data, options: .prettyPrinted), @@ -79,6 +85,8 @@ public class SwiftYookassaPaymentsFlutterPlugin: NSObject, FlutterPlugin { ) } + // BankCardRepeat Flow + if (call.method == YooMoneyService.repeatPayment.rawValue) { guard let data = call.arguments as? [String:AnyObject], let jsonData = try? JSONSerialization.data(withJSONObject: data, options: .prettyPrinted), @@ -94,6 +102,7 @@ public class SwiftYookassaPaymentsFlutterPlugin: NSObject, FlutterPlugin { if let controller = flutterController { let vc = TokenizationAssembly.makeModule(inputData: inputData, moduleOutput: controller) + yoomoneyController = vc tokenizationModuleInput = vc controller.present(vc, animated: true, completion: nil) } @@ -102,21 +111,6 @@ public class SwiftYookassaPaymentsFlutterPlugin: NSObject, FlutterPlugin { } extension FlutterViewController: TokenizationModuleOutput { - public func didSuccessfullyPassedCardSec(on module: TokenizationModuleInput) { - DispatchQueue.main.async { [weak self] in - guard let self = self else { return } - let alertController = UIAlertController( - title: "3D-Sec", - message: "Successfully passed 3d-sec", - preferredStyle: .alert - ) - - let action = UIAlertAction(title: "OK", style: .default) - alertController.addAction(action) - self.dismiss(animated: true) - self.present(alertController, animated: true) - } - } public func tokenizationModule( _ module: TokenizationModuleInput, @@ -126,7 +120,7 @@ extension FlutterViewController: TokenizationModuleOutput { tokenizationModuleInput = module if let result = flutterResult { - result("{\"paymentToken\": \"\(token.paymentToken)\", \"paymentMethodType\": \"\(paymentMethodType.rawValue)\"}") + result("{\"status\":\"success\", \"paymentToken\": \"\(token.paymentToken)\", \"paymentMethodType\": \"\(paymentMethodType.rawValue)\"}") DispatchQueue.main.async { if let controller = yoomoneyController { controller.dismiss(animated: true) @@ -144,24 +138,22 @@ extension FlutterViewController: TokenizationModuleOutput { controller.dismiss(animated: true) } } + guard let result = flutterResult else { return } + if let error = error { + result("{\"status\":\"error\", \"error\": \"\(error.localizedDescription)\"}") + } else { + result("{\"status\":\"canceled\"}") + } } - public func didSuccessfullyConfirmation( - paymentMethodType: PaymentMethodType - ) { + public func didFinishConfirmation(paymentMethodType: PaymentMethodType) { + guard let result = flutterResult else { return } DispatchQueue.main.async { [weak self] in - guard let self = self else { return } - let alertController = UIAlertController( - title: "Confirmation", - message: "Successfully confirmation", - preferredStyle: .alert - ) - - let action = UIAlertAction(title: "OK", style: .default) - alertController.addAction(action) - self.dismiss(animated: true) - self.present(alertController, animated: true) + if let controller = yoomoneyController { + controller.dismiss(animated: true) + } } + result("{\"paymentMethodType\": \"\(paymentMethodType.rawValue)\"}") } } @@ -292,8 +284,8 @@ extension TokenizationModuleInputData: Decodable { extension BankCardRepeatModuleInputData: Decodable { enum CodingKeys: String, CodingKey { case clientApplicationKey = "clientApplicationKey" - case shopName = "shopName" - case purchaseDescription = "purchaseDescription" + case shopName = "title" + case purchaseDescription = "subtitle" case amount = "amount" case savePaymentMethod = "savePaymentMethod" case paymentMethodId = "paymentMethodId" diff --git a/ios/yookassa_payments_flutter.podspec b/ios/yookassa_payments_flutter.podspec index d6bcc62..e397bc6 100644 --- a/ios/yookassa_payments_flutter.podspec +++ b/ios/yookassa_payments_flutter.podspec @@ -11,7 +11,7 @@ Flutter SDK from yoomoney s.source = { :path => '.' } s.source_files = 'Classes/**/*' s.dependency 'Flutter' - s.dependency 'YooKassaPayments', '6.8.0' + s.dependency 'YooKassaPayments', '6.9.0' s.platform = :ios, '10.0' diff --git a/lib/models/payment_method_types.dart b/lib/models/payment_method_types.dart index c7424e6..f1e0350 100644 --- a/lib/models/payment_method_types.dart +++ b/lib/models/payment_method_types.dart @@ -6,11 +6,16 @@ class PaymentMethodTypes { return paymentMethodTypes.map((e) => e.toString()).toList(); } - static const PaymentMethodTypes bankCard = PaymentMethodTypes([PaymentMethod.bankCard]); - static const PaymentMethodTypes yooMoney = PaymentMethodTypes([PaymentMethod.yooMoney]); - static const PaymentMethodTypes sberbank = PaymentMethodTypes([PaymentMethod.sberbank]); - static const PaymentMethodTypes applePay = PaymentMethodTypes([PaymentMethod.applePay]); - static const PaymentMethodTypes googlePay = PaymentMethodTypes([PaymentMethod.googlePay]); + static const PaymentMethodTypes bankCard = + PaymentMethodTypes([PaymentMethod.bankCard]); + static const PaymentMethodTypes yooMoney = + PaymentMethodTypes([PaymentMethod.yooMoney]); + static const PaymentMethodTypes sberbank = + PaymentMethodTypes([PaymentMethod.sberbank]); + static const PaymentMethodTypes applePay = + PaymentMethodTypes([PaymentMethod.applePay]); + static const PaymentMethodTypes googlePay = + PaymentMethodTypes([PaymentMethod.googlePay]); static const PaymentMethodTypes all = PaymentMethodTypes([ PaymentMethod.bankCard, PaymentMethod.yooMoney, @@ -20,10 +25,22 @@ class PaymentMethodTypes { ]); } -enum PaymentMethod { - bankCard, - yooMoney, - applePay, - googlePay, - sberbank -} \ No newline at end of file +enum PaymentMethod { bankCard, yooMoney, applePay, googlePay, sberbank } + +extension PaymentMethodExtension on PaymentMethod { + static PaymentMethod fromStringValue(String rawValue) { + switch (rawValue) { + case 'bank_card': + return PaymentMethod.bankCard; + case 'yoo_money': + return PaymentMethod.yooMoney; + case 'sberbank': + return PaymentMethod.sberbank; + case 'apple_pay': + return PaymentMethod.applePay; + case 'google_pay': + return PaymentMethod.googlePay; + } + return PaymentMethod.bankCard; + } +} diff --git a/lib/models/tokenization_result.dart b/lib/models/tokenization_result.dart index 7c76f31..38411fa 100644 --- a/lib/models/tokenization_result.dart +++ b/lib/models/tokenization_result.dart @@ -1,35 +1,62 @@ import 'package:yookassa_payments_flutter/models/payment_method_types.dart'; class TokenizationResult { - String token; - PaymentMethod? paymentMethodType; + TokenizationResult._(); - TokenizationResult(this.token, this.paymentMethodType); + factory TokenizationResult.success( + String token, PaymentMethod? paymentMethodType) = + SuccessTokenizationResult; + factory TokenizationResult.canceled() = CanceledTokenizationResult; + factory TokenizationResult.error(String error) = ErrorTokenizationResult; factory TokenizationResult.fromJson(Map json) { - var token = json['paymentToken']; - - PaymentMethod? paymentMethodType; - switch(json['paymentMethodType']){ - case "sberbank": - paymentMethodType = PaymentMethod.sberbank; - break; - case "bank_card": - paymentMethodType = PaymentMethod.bankCard; - break; - case "yoo_money": - paymentMethodType = PaymentMethod.yooMoney; - break; - case "apple_pay": - paymentMethodType = PaymentMethod.applePay; - break; - case "google_pay": - paymentMethodType = PaymentMethod.googlePay; - break; + final status = json['status']; + switch (status) { + case 'success': + { + final token = json['paymentToken']; + PaymentMethod? paymentMethodType = + _paymentMethodFromString(json['paymentMethodType']); + return TokenizationResult.success(token, paymentMethodType); + } + case 'canceled': + return TokenizationResult.canceled(); default: - break; + return TokenizationResult.error(json['error'] ?? 'Unknown error'); } - - return TokenizationResult(token, paymentMethodType); } -} \ No newline at end of file +} + +class SuccessTokenizationResult extends TokenizationResult { + final String token; + final PaymentMethod? paymentMethodType; + + SuccessTokenizationResult(this.token, this.paymentMethodType) : super._(); +} + +class CanceledTokenizationResult extends TokenizationResult { + CanceledTokenizationResult() : super._(); +} + +class ErrorTokenizationResult extends TokenizationResult { + final String error; + + ErrorTokenizationResult(this.error) : super._(); +} + +PaymentMethod? _paymentMethodFromString(String type) { + switch (type) { + case "sberbank": + return PaymentMethod.sberbank; + case "bank_card": + return PaymentMethod.bankCard; + case "yoo_money": + return PaymentMethod.yooMoney; + case "apple_pay": + return PaymentMethod.applePay; + case "google_pay": + return PaymentMethod.googlePay; + default: + return null; + } +} diff --git a/lib/yookassa_payments_flutter.dart b/lib/yookassa_payments_flutter.dart index 82b7ff7..9dc34aa 100644 --- a/lib/yookassa_payments_flutter.dart +++ b/lib/yookassa_payments_flutter.dart @@ -6,6 +6,7 @@ export 'models/tokenization_settings.dart'; export 'models/customization_settings.dart'; export 'models/google_pay_parameters.dart'; export 'models/test_mode_settings.dart'; +export 'models/tokenization_result.dart'; export 'input_data/tokenization_module_input_data.dart'; import 'input_data/saved_card_module_input_data.dart'; @@ -14,28 +15,31 @@ import 'package:flutter/services.dart'; import 'package:yookassa_payments_flutter/models/tokenization_result.dart'; import 'input_data/tokenization_module_input_data.dart'; import 'models/payment_method_types.dart'; +import 'models/tokenization_result.dart'; class YookassaPaymentsFlutter { - static const MethodChannel _channel = MethodChannel('ru.yoomoney.yookassa_payments_flutter/yoomoney'); + static const MethodChannel _channel = + MethodChannel('ru.yoomoney.yookassa_payments_flutter/yoomoney'); - static Future tokenization(TokenizationModuleInputData data) async { + static Future tokenization( + TokenizationModuleInputData data) async { var inputData = data.toJson(); return await _channel - .invokeMethod('tokenization', inputData).then((value) => TokenizationResult.fromJson(json.decode(value))); + .invokeMethod('tokenization', inputData) + .then((value) => TokenizationResult.fromJson(json.decode(value))); } - static Future confirmation(String url, PaymentMethod? paymentMethod) async { - await _channel - .invokeMethod('confirmation', - { - 'url': url, - 'paymentMethod': paymentMethod?.name - } - ); + static Future confirmation( + String url, PaymentMethod? paymentMethod) async { + var inputData = {'url': url, 'paymentMethod': paymentMethod?.name}; + return await _channel.invokeMethod('confirmation', inputData); } - static Future bankCardRepeat(SavedBankCardModuleInputData data) async { - return await _channel.invokeMethod('repeat', data.toJson()).then((value) => TokenizationResult.fromJson(json.decode(value))); + static Future bankCardRepeat( + SavedBankCardModuleInputData data) async { + return await _channel + .invokeMethod('repeat', data.toJson()) + .then((value) => TokenizationResult.fromJson(json.decode(value))); } } diff --git a/pubspec.lock b/pubspec.lock index 96201dd..22c4351 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -42,14 +42,14 @@ packages: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.16.0" + version: "1.15.0" fake_async: dependency: transitive description: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.3.0" + version: "1.2.0" flutter: dependency: "direct main" description: flutter @@ -87,7 +87,7 @@ packages: name: material_color_utilities url: "https://pub.dartlang.org" source: hosted - version: "0.1.4" + version: "0.1.3" meta: dependency: transitive description: @@ -101,7 +101,7 @@ packages: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.8.1" + version: "1.8.0" sky_engine: dependency: transitive description: flutter @@ -113,7 +113,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.2" + version: "1.8.1" stack_trace: dependency: transitive description: @@ -148,14 +148,21 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.4.9" + version: "0.4.8" + typed_data: + dependency: transitive + description: + name: typed_data + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.0" vector_math: dependency: transitive description: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.2" + version: "2.1.1" sdks: - dart: ">=2.17.0-0 <3.0.0" + dart: ">=2.14.0 <3.0.0" flutter: ">=2.10.5" diff --git a/pubspec.yaml b/pubspec.yaml index ee49157..78f696d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: yookassa_payments_flutter description: This Flutter SDK allows processing payments using a payment token. It works as an addition to the YooMoney API. -version: 1.0.2 +version: 1.0.3 homepage: https://git.yoomoney.ru/projects/SDK/repos/yookassa-payments-flutter-sdk/browse repository: https://git.yoomoney.ru/projects/SDK/repos/yookassa-payments-flutter-sdk/browse