From 1b9a8af2c55a68d1f2dae3fb5eb36f7df64fa893 Mon Sep 17 00:00:00 2001 From: "Serik.Uvaissov" Date: Sun, 23 Aug 2020 14:05:56 +0600 Subject: [PATCH] ui and back worked --- .../aman/kassa/plugins/BankNfcPlugins.java | 2 +- lib/core/locator.dart | 3 + lib/core/route_names.dart | 1 + lib/core/router.dart | 6 + lib/core/services/BankService.dart | 114 ++++++++ lib/redux/actions/bank_actions.dart | 19 ++ lib/redux/reducers/bank_reducer.dart | 7 + lib/redux/state/bank_state.dart | 41 +++ lib/redux/store.dart | 35 ++- lib/views/bank_setting/bank_setting_view.dart | 114 ++++++++ lib/views/home/components/popup_menu.dart | 47 +++- lib/views/home/home_view.dart | 4 +- lib/views/payment_nfc/payment_nfc_view.dart | 257 ++++++++++++++++-- .../payment_nfc/widgets/action_view.dart | 49 ++++ lib/views/payment_nfc/widgets/phone_view.dart | 34 ++- pubspec.lock | 79 ++---- 16 files changed, 717 insertions(+), 95 deletions(-) create mode 100644 lib/core/services/BankService.dart create mode 100644 lib/redux/actions/bank_actions.dart create mode 100644 lib/redux/reducers/bank_reducer.dart create mode 100644 lib/redux/state/bank_state.dart create mode 100644 lib/views/bank_setting/bank_setting_view.dart create mode 100644 lib/views/payment_nfc/widgets/action_view.dart diff --git a/android/app/src/main/java/kz/com/aman/kassa/plugins/BankNfcPlugins.java b/android/app/src/main/java/kz/com/aman/kassa/plugins/BankNfcPlugins.java index b02ea69..ce7b66c 100644 --- a/android/app/src/main/java/kz/com/aman/kassa/plugins/BankNfcPlugins.java +++ b/android/app/src/main/java/kz/com/aman/kassa/plugins/BankNfcPlugins.java @@ -89,7 +89,7 @@ public class BankNfcPlugins implements MethodCallHandler { showTransaction(call, result); break; case "version": - result.success("version: "+ Build.VERSION.SDK_INT); + result.success(String.valueOf(Build.VERSION.SDK_INT)); break; case "get": AmanDao dao = new AmanDao<>(); diff --git a/lib/core/locator.dart b/lib/core/locator.dart index f09757e..682e4c7 100644 --- a/lib/core/locator.dart +++ b/lib/core/locator.dart @@ -1,5 +1,6 @@ +import 'package:aman_kassa_flutter/core/services/BankService.dart'; import 'package:aman_kassa_flutter/core/services/DataService.dart'; import '../core/services/DbService.dart'; @@ -32,5 +33,7 @@ class LocatorInjector { _log.d('Initializing DataService Service'); locator.registerLazySingleton(() => DataService()); + _log.d('Initializing BankService Service'); + locator.registerLazySingleton(() => BankService()); } } \ No newline at end of file diff --git a/lib/core/route_names.dart b/lib/core/route_names.dart index 0bd6924..05777c6 100644 --- a/lib/core/route_names.dart +++ b/lib/core/route_names.dart @@ -7,4 +7,5 @@ const String HistoryViewRoute = "HistoryView"; const String InfoKkmViewRoute = "InfoKkmViewRoute"; const String QrViewRoute = "QrViewRoute"; const String BankViewRoute = "BankViewRoute"; +const String BankSettingViewRoute = "BankSettingViewRoute"; // Generate the views here diff --git a/lib/core/router.dart b/lib/core/router.dart index e47389e..1a213ef 100644 --- a/lib/core/router.dart +++ b/lib/core/router.dart @@ -1,3 +1,4 @@ +import 'package:aman_kassa_flutter/views/bank_setting/bank_setting_view.dart'; import 'package:aman_kassa_flutter/views/bank_view/bank_view.dart'; import 'package:aman_kassa_flutter/views/check/image_show_container.dart'; import 'package:aman_kassa_flutter/views/history/history_view.dart'; @@ -53,6 +54,11 @@ Route generateRoute(RouteSettings settings) { routeName: settings.name, viewToShow: BankView(), ); + case BankSettingViewRoute: + return _getPageRoute( + routeName: settings.name, + viewToShow: BankSettingView(), + ); case QrViewRoute: ImageShowModel data = settings.arguments as ImageShowModel; return _getPageRoute( diff --git a/lib/core/services/BankService.dart b/lib/core/services/BankService.dart new file mode 100644 index 0000000..261dc15 --- /dev/null +++ b/lib/core/services/BankService.dart @@ -0,0 +1,114 @@ +import 'dart:convert'; +import 'package:aman_kassa_flutter/core/base/base_service.dart'; +import 'package:aman_kassa_flutter/core/models/aman_dao.dart'; +import 'package:flutter/services.dart'; + +class BankService extends BaseService { + static const String _url = 'http://185.98.84.231:2000'; + final MethodChannel _channel = MethodChannel('channel:com.amanKassa/bank'); + + + Future version() async { + String result; + try { + result = await _channel.invokeMethod('version'); + } catch (e, stack) { + log.e("BankService", e, stack); + result = '0'; + } + log.i(result); + return int.parse(result) ?? 0; + } + + Future imei() async { + String result; + try { + result = await _channel.invokeMethod('imei'); + } catch (e, stack) { + log.e("BankService", e, stack); + result = '0'; + } + log.i(result); + return result; + } + + Future init() async { + try { + String response = await _channel.invokeMethod('init', { + 'serverUrl': _url, + }); + AmanDao dao = AmanDao.fromJson(json.decode(response)); + log.i('${dao.success} - ${dao.msg}'); + return dao.success; + } catch (e, stack) { + log.e("BankService", e, stack); + return false; + } + } + + Future connect() async { + try { + String response = await _channel.invokeMethod("connection"); + AmanDao dao = AmanDao.fromJson(json.decode(response)); + log.i('${dao.success} - ${dao.msg}'); + return dao.success; + } catch (e, stack) { + log.e("BankService", e, stack); + return false; + } + } + + Future auth({String login, String password}) async { + try { + String response = await _channel.invokeMethod("auth", + {'login': login, 'password': password}); + AmanDao dao = AmanDao.fromJson(json.decode(response)); + log.i('${dao.success} - ${dao.msg}'); + return dao; + } catch (e, stack) { + log.e("BankService", e, stack); + return new AmanDao(msg: 'Ошибка авторизации'); + } + } + + Future pay({double amount}) async { + try { + + double total = amount * 100; + log.i('total: $total, ${total.toInt()}'); + String response = await _channel.invokeMethod("pay", {'amount': total.toInt()}); + AmanDao dao = AmanDao.fromJson(json.decode(response)); + log.i('${dao.success} - ${dao.msg}'); + return dao; + } catch (e, stack) { + log.e("BankService", e, stack); + return new AmanDao(msg: 'Ошибка оплаты'); + } + } + + Future shutdown() async { + try { + String response = await _channel.invokeMethod("shutdown"); + AmanDao dao = AmanDao.fromJson(json.decode(response)); + log.i('${dao.success} - ${dao.msg}'); + return dao.success; + } catch (e, stack) { + log.e("BankService", e, stack); + return false; + } + } + + Future cancel() async { + try { + String response = await _channel.invokeMethod("cancel"); + AmanDao dao = AmanDao.fromJson(json.decode(response)); + log.i('${dao.success} - ${dao.msg}'); + return dao.success; + } catch (e, stack) { + log.e("BankService", e, stack); + return false; + } + } + + +} diff --git a/lib/redux/actions/bank_actions.dart b/lib/redux/actions/bank_actions.dart new file mode 100644 index 0000000..b27c1cf --- /dev/null +++ b/lib/redux/actions/bank_actions.dart @@ -0,0 +1,19 @@ + +import 'package:aman_kassa_flutter/redux/state/bank_state.dart'; +import 'package:meta/meta.dart'; +import 'package:redux/redux.dart'; +import 'package:redux_thunk/redux_thunk.dart'; + +import '../store.dart'; + +@immutable +class SetBankStateAction { + final BankState bankState; + SetBankStateAction(this.bankState); +} + +ThunkAction saveData(String login, String password) { + return (Store store) async { + store.dispatch(SetBankStateAction(BankState(login: login, password: password))); + }; +} diff --git a/lib/redux/reducers/bank_reducer.dart b/lib/redux/reducers/bank_reducer.dart new file mode 100644 index 0000000..174c126 --- /dev/null +++ b/lib/redux/reducers/bank_reducer.dart @@ -0,0 +1,7 @@ +import 'package:aman_kassa_flutter/redux/actions/bank_actions.dart'; +import 'package:aman_kassa_flutter/redux/state/bank_state.dart'; + +bankReducer(BankState prevState, SetBankStateAction action) { + final payload = action.bankState; + return prevState.copyWith(login: payload.login, password: payload.password); +} diff --git a/lib/redux/state/bank_state.dart b/lib/redux/state/bank_state.dart new file mode 100644 index 0000000..c7efeb0 --- /dev/null +++ b/lib/redux/state/bank_state.dart @@ -0,0 +1,41 @@ +import 'package:aman_kassa_flutter/redux/constants/setting_const.dart'; +import 'package:meta/meta.dart'; + +@immutable +class BankState { + final String login; + final String password; + + BankState({this.login, this.password}); + + //read hive + factory BankState.initial(BankState payload) { + return BankState( + login: payload?.login, + password: payload?.password); + } + + //write hive + BankState copyWith({ + @required login, + @required password, + }) { + return BankState( + login: login ?? this.login, + password: password ?? this.password, + ); + } + + static BankState fromJson(dynamic json) { + return json != null + ? BankState( + password: json['password'], + login: json['login'], + ) + : null; + } + + dynamic toJson() { + return {"password": password, "login": login}; + } +} diff --git a/lib/redux/store.dart b/lib/redux/store.dart index 1c34fdf..97b3ca0 100644 --- a/lib/redux/store.dart +++ b/lib/redux/store.dart @@ -1,10 +1,12 @@ import 'package:aman_kassa_flutter/redux/actions/kassa_actions.dart'; import 'package:aman_kassa_flutter/redux/actions/setting_actions.dart'; import 'package:aman_kassa_flutter/redux/actions/user_actions.dart'; +import 'package:aman_kassa_flutter/redux/reducers/bank_reducer.dart'; import 'package:aman_kassa_flutter/redux/reducers/calc_reducer.dart'; import 'package:aman_kassa_flutter/redux/reducers/main_reducer.dart'; import 'package:aman_kassa_flutter/redux/reducers/setting_reducer.dart'; import 'package:aman_kassa_flutter/redux/reducers/user_reducer.dart'; +import 'package:aman_kassa_flutter/redux/state/bank_state.dart'; import 'package:aman_kassa_flutter/redux/state/calc_state.dart'; import 'package:aman_kassa_flutter/redux/state/kassa_state.dart'; import 'package:aman_kassa_flutter/redux/state/setting_state.dart'; @@ -15,6 +17,7 @@ import 'package:redux_persist_flutter/redux_persist_flutter.dart'; import 'package:redux_thunk/redux_thunk.dart'; import 'package:redux_persist/redux_persist.dart'; +import 'actions/bank_actions.dart'; import 'actions/calc_actions.dart'; //reducer context @@ -35,6 +38,10 @@ AppState appReducer(AppState state, dynamic action) { /** CalcAction **/ final nextCalcState = calcReducer(state.calcState, action); return state.copyWith(calcState: nextCalcState); + } else if (action is SetBankStateAction) { + /** BankAction **/ + final nextBankState = bankReducer(state.bankState, action); + return state.copyWith(bankState: nextBankState); } return state; } @@ -46,12 +53,14 @@ class AppState { final KassaState kassaState; final SettingState settingState; final CalcState calcState; + final BankState bankState; AppState({ this.userState, this.kassaState, this.settingState, this.calcState, + this.bankState, }); //stable work @@ -60,29 +69,32 @@ class AppState { KassaState kassaState, SettingState settingState, CalcState calcState, + BankState bankState, }) { return AppState( userState: userState ?? this.userState, kassaState: kassaState ?? this.kassaState, settingState: settingState ?? this.settingState, calcState: calcState ?? this.calcState, + bankState: bankState ?? this.bankState, ); } - static AppState fromJson(dynamic json){ - print(json); - return json !=null + static AppState fromJson(dynamic json) { + return json != null ? AppState( - settingState: SettingState.fromJson(json['settingState']), - userState: UserState.fromJson(json['userState']), - ) + settingState: SettingState.fromJson(json['settingState']), + userState: UserState.fromJson(json['userState']), + bankState: BankState.fromJson(json['bankState']), + ) : null; } dynamic toJson() { return { "settingState": settingState.toJson(), - "userState" : userState.toJson(), + "userState": userState.toJson(), + "bankState": bankState.toJson(), }; } } @@ -103,7 +115,8 @@ class Redux { // Create Persistor final persist = Persistor( storage: FlutterStorage(), // Or use other engines - serializer: JsonSerializer(AppState.fromJson), // Or use other serializers + serializer: JsonSerializer( + AppState.fromJson), // Or use other serializers ); final initialState = await persist.load(); @@ -112,15 +125,17 @@ class Redux { final kassaStateInitial = KassaState.initial(); final settingStateInitial = SettingState.initial(initialState?.settingState); final calcStateInitial = CalcState.initial(); + final bankStateInitial = BankState.initial(initialState?.bankState); _store = Store( appReducer, - middleware: [thunkMiddleware, persist.createMiddleware() ], + middleware: [thunkMiddleware, persist.createMiddleware()], initialState: AppState( userState: userStateInitial, kassaState: kassaStateInitial, settingState: settingStateInitial, - calcState: calcStateInitial), + calcState: calcStateInitial, + bankState: bankStateInitial), ); } } diff --git a/lib/views/bank_setting/bank_setting_view.dart b/lib/views/bank_setting/bank_setting_view.dart new file mode 100644 index 0000000..d62176b --- /dev/null +++ b/lib/views/bank_setting/bank_setting_view.dart @@ -0,0 +1,114 @@ +import 'dart:convert'; + +import 'package:aman_kassa_flutter/core/locator.dart'; +import 'package:aman_kassa_flutter/core/services/BankService.dart'; +import 'package:aman_kassa_flutter/core/services/dialog_service.dart'; +import 'package:aman_kassa_flutter/redux/actions/bank_actions.dart'; +import 'package:aman_kassa_flutter/redux/state/bank_state.dart'; +import 'package:aman_kassa_flutter/redux/store.dart'; +import 'package:aman_kassa_flutter/shared/app_colors.dart'; +import 'package:aman_kassa_flutter/shared/ui_helpers.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +class BankSettingView extends StatefulWidget { + BankSettingView(); + + @override + _BankSettingViewState createState() => _BankSettingViewState(); +} + +class _BankSettingViewState extends State { + TextEditingController _emailController; + TextEditingController _passwordController; + final BankService _bankService = locator(); + final DialogService _dialogService = locator(); + String _platformImei = 'Unknown'; + String _bankImei = 'Unknown'; + + @override + void initState() { + super.initState(); + BankState state = Redux.store.state.bankState; + _emailController = new TextEditingController(text: state.login); + _passwordController = new TextEditingController(text: state.password); + initBankImeiState(); + } + + Future initBankImeiState() async { + String imei; + + try { + imei = await _bankService.imei(); + } on PlatformException { + imei = 'Failed to get platform version.'; + } + if (!mounted) return; + setState(() { + _bankImei = imei; + }); + } + + + @override + void dispose() { + _emailController.dispose(); + _passwordController.dispose(); + super.dispose(); + } + + void _saveData() async { + await Redux.store.dispatch(saveData(_emailController.text, _passwordController.text)); + _dialogService.showDialog(description: 'Данные сохранены'); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + centerTitle: true, + title: Text('Настройка Tap2Phone'), + ), + body: SingleChildScrollView( + child: Container( + margin: const EdgeInsets.symmetric(horizontal: 14.0), + child: Column( + children: [ + verticalSpaceTiny, + Text( + 'Необходимо указать почту и пароль для подключения к системе проведения платежей', + style: TextStyle(fontSize: 15.0), + textAlign: TextAlign.center, + ), + Text('Ваш IMEI-код:$_platformImei'), + Text('Ваш IMEI-код:$_bankImei'), + verticalSpaceTiny, + TextField( + controller: _emailController, + decoration: InputDecoration( + labelText: 'E-Mail', hintText: "Введите адрес почты"), + keyboardType: TextInputType.emailAddress, + ), + TextField( + controller: _passwordController, + decoration: InputDecoration( + labelText: 'Пароль', hintText: "Введите пароль"), + ), + verticalSpaceMedium, + RaisedButton( + onPressed: this._saveData, + child: Text( + 'Cохранить', + style: TextStyle(color: whiteColor, fontSize: 25.0), + ), + color: primaryColor, + padding: + const EdgeInsets.symmetric(vertical: 5.0, horizontal: 20.0), + ) + ], + ), + ), + ), + ); + } +} diff --git a/lib/views/home/components/popup_menu.dart b/lib/views/home/components/popup_menu.dart index 9ce80a0..61269bd 100644 --- a/lib/views/home/components/popup_menu.dart +++ b/lib/views/home/components/popup_menu.dart @@ -1,23 +1,46 @@ +import 'package:aman_kassa_flutter/core/locator.dart'; import 'package:aman_kassa_flutter/core/models/choice.dart'; +import 'package:aman_kassa_flutter/core/services/BankService.dart'; import 'package:aman_kassa_flutter/shared/app_colors.dart'; import 'package:flutter/material.dart'; +import 'package:material_design_icons_flutter/material_design_icons_flutter.dart'; -const List choices = const [ - //const Choice(title: 'Обновить номенклатуру', icon: Icons.update, command: 'update'), - //const Choice(title: 'Помощь', icon: Icons.help, command: 'help'), - const Choice( - title: 'Информация о ККМ', icon: Icons.info_outline, command: 'infokkm'), - //const Choice(title: 'Язык', icon: Icons.language, command: 'language'), - const Choice(title: 'Bank', icon: Icons.text_fields, command: 'bank'), - const Choice(title: 'Выйти', icon: Icons.exit_to_app, command: 'exit') -]; - -class PopupMenu extends StatelessWidget { +class PopupMenu extends StatefulWidget { final void Function(Choice value) onSelectChoice; PopupMenu({this.onSelectChoice}); + @override + _PopupMenuState createState() => _PopupMenuState(); +} + +class _PopupMenuState extends State { + BankService _bankService = locator(); + List choices; + @override + void initState() { + // TODO: implement initState + super.initState(); + load(); + } + + load () async { + int version = await _bankService.version(); + + List _choices = [ + const Choice(title: 'Информация о ККМ', icon: Icons.info_outline, command: 'infokkm'), + if (version >= 24 ) + const Choice(title: 'Bank', icon: Icons.text_fields, command: 'bank'), + if (version >= 24 ) + const Choice(title: 'Настройка Tap2Phone', icon: MdiIcons.nfc, command: 'tap2phone'), + const Choice(title: 'Выйти', icon: Icons.exit_to_app, command: 'exit') + ]; + setState(() { + choices= _choices; + }); + } + @override Widget build(BuildContext context) { return PopupMenuButton( @@ -25,7 +48,7 @@ class PopupMenu extends StatelessWidget { Icons.more_vert, color: menuColor, ), - onSelected: onSelectChoice, + onSelected: widget.onSelectChoice, itemBuilder: (BuildContext context) { return choices.map((Choice choice) { return PopupMenuItem( diff --git a/lib/views/home/home_view.dart b/lib/views/home/home_view.dart index f288906..ec2fbcd 100644 --- a/lib/views/home/home_view.dart +++ b/lib/views/home/home_view.dart @@ -58,7 +58,7 @@ class _HomeViewState extends State { if (choice.command == 'exit') { Dialogs.showLoadingDialog(context, _keyLoader); Response result = - await _api.logout(Redux.store.state.userState.user.token); + await _api.logout(Redux.store.state.userState.user.token); if (result.operation && result.status == 200) { Redux.store.dispatch(logoutAction); } @@ -67,6 +67,8 @@ class _HomeViewState extends State { _navigatorService.push(InfoKkmViewRoute); } else if (choice.command == 'bank') { _navigatorService.push(BankViewRoute); + } else if (choice.command == 'tap2phone') { + _navigatorService.push(BankSettingViewRoute); } } diff --git a/lib/views/payment_nfc/payment_nfc_view.dart b/lib/views/payment_nfc/payment_nfc_view.dart index 30aa1d3..506fd19 100644 --- a/lib/views/payment_nfc/payment_nfc_view.dart +++ b/lib/views/payment_nfc/payment_nfc_view.dart @@ -1,8 +1,11 @@ import 'package:aman_kassa_flutter/core/locator.dart'; +import 'package:aman_kassa_flutter/core/logger.dart'; +import 'package:aman_kassa_flutter/core/models/aman_dao.dart'; import 'package:aman_kassa_flutter/core/models/calc_model.dart'; import 'package:aman_kassa_flutter/core/models/product_dao.dart'; import 'package:aman_kassa_flutter/core/models/response.dart'; import 'package:aman_kassa_flutter/core/route_names.dart'; +import 'package:aman_kassa_flutter/core/services/BankService.dart'; import 'package:aman_kassa_flutter/core/services/DataService.dart'; import 'package:aman_kassa_flutter/core/services/dialog_service.dart'; import 'package:aman_kassa_flutter/core/services/navigator_service.dart'; @@ -11,24 +14,25 @@ import 'package:aman_kassa_flutter/redux/actions/kassa_actions.dart'; import 'package:aman_kassa_flutter/redux/actions/user_actions.dart'; import 'package:aman_kassa_flutter/redux/constants/operation_const.dart'; import 'package:aman_kassa_flutter/redux/constants/setting_const.dart'; +import 'package:aman_kassa_flutter/redux/state/bank_state.dart'; import 'package:aman_kassa_flutter/redux/state/calc_state.dart'; import 'package:aman_kassa_flutter/redux/state/kassa_state.dart'; import 'package:aman_kassa_flutter/redux/store.dart'; import 'package:aman_kassa_flutter/shared/app_colors.dart'; -import 'package:aman_kassa_flutter/shared/ui_helpers.dart'; import 'package:aman_kassa_flutter/views/check/image_show_container.dart'; import 'package:aman_kassa_flutter/views/payment/payment_view.dart'; +import 'package:aman_kassa_flutter/views/payment_nfc/widgets/action_view.dart'; import 'package:aman_kassa_flutter/views/payment_nfc/widgets/background_view.dart'; import 'package:aman_kassa_flutter/views/payment_nfc/widgets/card_view.dart'; import 'package:aman_kassa_flutter/views/payment_nfc/widgets/phone_view.dart'; import 'package:aman_kassa_flutter/views/payment_nfc/widgets/text_state.dart'; import 'package:aman_kassa_flutter/widgets/components/calculator/calculator.dart'; -import 'package:aman_kassa_flutter/widgets/fields/busy_button.dart'; import 'package:aman_kassa_flutter/widgets/loader/Dialogs.dart'; -import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:flutter_screenutil/screenutil.dart'; +import 'package:logger/logger.dart'; class PaymentNfcView extends StatefulWidget { final PaymentModel model; @@ -40,14 +44,184 @@ class PaymentNfcView extends StatefulWidget { } class _PaymentNfcViewState extends State { + final GlobalKey _keyLoader = new GlobalKey(); + BankService _bankService = locator(); + DialogService _dialogService = locator(); + final DataService _dataService = locator(); + final NavigatorService _navigatorService = locator(); + Logger log = getLogger('PaymentNfcView'); bool isBusy; - bool isPhoneScaled = false; - int status = 0; + bool isPhoneScaled; + int status; @override void initState() { super.initState(); isBusy = false; + isPhoneScaled = false; + status = 0; + start(); + } + + void start() async { + //Инициализация + bool initialized = await _bankService.init(); + log.i(initialized); + if (!initialized) { + setState(() { + status = 4; + }); + return; + } + //Проверка связи + bool connected = await _bankService.connect(); + log.i(connected); + if (!connected) { + setState(() { + status = 5; + }); + return; + } + //Авторизация + BankState bankState = Redux.store.state.bankState; + AmanDao authDao = await _bankService.auth( + login: bankState.login, password: bankState.password); + if (!authDao.success) { + setState(() { + status = 6; + }); + + if (authDao.msg != null) { + log.i(authDao.msg); + _dialogService.showDialog(description: authDao.msg); + } + return; + } + + pay(); + } + + pay() async { + //Платеж + num total = 0.0; + if (widget.model.mode == SettingModeCalc) { + total = totalCalc(Redux.store.state.calcState.calcItems); + } else { + total = totalKassa(Redux.store.state.kassaState.kassaItems); + } + + setState(() { + status = 1; + isPhoneScaled = true; + }); + + log.i('total: $total'); + AmanDao payDao = await _bankService.pay(amount: total); + if (!payDao.success) { + int _status = 7; + if (payDao.data != null ) { + if("onWrongApiCalled" == payDao.data.toString()) { + cancel(); + } else if("notAuthorized" == payDao.data.toString() ) { + cancel(); + _status = 6; + } + } + + setState(() { + status = _status; + isPhoneScaled = false; + }); + + if (payDao.msg != null) { + log.i(payDao.msg); + _dialogService.showDialog(description: payDao.msg); + } + return; + } + + setState(() { + status = 3; + isPhoneScaled = false; + }); + + //check + pressPayment('card'); + } + + cancel() async { + bool isCanceled = await _bankService.cancel(); + _navigatorService.pop(); + } + + pressPayment(String type) async { + setState(() { + isBusy = true; + }); + Dialogs.showLoadingDialog(context, _keyLoader); + try { + AppState _state = Redux.store.state; + String _token = _state.userState.user.token; + String _tradeType = _state.settingState.tradeType; + String _mode = _state.settingState.mode; + if (_mode == SettingModeCalc) { + _tradeType = SettingTradeTypeGood; + } + List kassaItems = _state.kassaState.kassaItems; + List calcItems = _state.calcState.calcItems; + Response response = await _dataService.sellOrReturn( + token: _token, + kassaItems: kassaItems, + paymentType: type, + operationType: widget.model.operationType, + tradeType: _tradeType, + calcItems: calcItems, + mode: _mode); + setState(() { + isBusy = false; + }); + if (response != null) { + if (response.operation) { + String message = response.body['message']; + String check = response.body['check']; + String url = response?.body['link']; + print('url : $url'); + if (_mode == SettingModeCalc) { + Redux.store.dispatch(cleanCalcItems); + } else if (_mode == SettingModeKassa) { + Redux.store.dispatch(cleanKassaItems); + } + Redux.store.dispatch(checkMoney); + Redux.store.dispatch(openSmenaPseudo); + Navigator.of(_keyLoader.currentContext, rootNavigator: true).pop(); + _navigatorService.replace(HomeViewRoute); + _navigatorService.push(ImageShowRoute, + arguments: ImageShowModel(data: check, title: message, url: url)); + } else if (!response.operation && + ![401, 402, 403, 412, 500].contains(response.status)) { + Navigator.of(_keyLoader.currentContext, rootNavigator: true).pop(); + _dialogService.showDialog(description: response.body['message']); + } else { + Navigator.of(_keyLoader.currentContext, rootNavigator: true).pop(); + } + } else { + Navigator.of(_keyLoader.currentContext, rootNavigator: true).pop(); + } + } catch (e) { + print(e); + Navigator.of(_keyLoader.currentContext, rootNavigator: true).pop(); + } finally { + //Navigator.of(context, rootNavigator: true).pop(); + setState(() { + isBusy = false; + }); + } + } + + @override + void dispose() { + _bankService.shutdown(); + super.dispose(); } @override @@ -71,16 +245,6 @@ class _PaymentNfcViewState extends State { dataTitle(), style: TextStyle(color: whiteColor), ), - actions: [ - FlatButton( - onPressed: () { - setState(() { - isPhoneScaled = !isPhoneScaled; - status += 1; - }); - }, - child: Icon(Icons.add)), - ], ), body: Container( decoration: BoxDecoration(color: purpleColor), @@ -108,7 +272,11 @@ class _PaymentNfcViewState extends State { CardView( show: isPhoneScaled, ), - PhoneView(scaled: isPhoneScaled, status: status,), + PhoneView( + scaled: isPhoneScaled, + status: status, + ), + buildActionView() ], ), ) @@ -119,6 +287,55 @@ class _PaymentNfcViewState extends State { ); } + ActionView buildActionView() { + switch (status) { + case 5: + return ActionView( + show: true, + acceptText: 'Повторить', + acceptCallback: () async { + await _bankService.shutdown(); + start(); + }, + declineText: 'Отмена', + declineCallback: () { + cancel(); + }, + ); + break; + case 6: + return ActionView( + show: true, + acceptText: 'Повторить', + acceptCallback: () async { + await _bankService.shutdown(); + start(); + }, + declineText: 'Отмена', + declineCallback: () { + cancel(); + }, + ); + break; + case 7: + return ActionView( + show: true, + acceptText: 'Повторить', + acceptCallback: () { + pay(); + }, + declineText: 'Отмена', + declineCallback: () { + cancel(); + }, + ); + break; + default: + } + + return ActionView(); + } + String dataTitle() => widget.model.operationType == OperationTypePay ? 'Оплата' : 'Возврат'; @@ -149,15 +366,15 @@ class _PaymentNfcViewState extends State { }); } - String totalKassa(List kassaItems) { + num totalKassa(List kassaItems) { num total = 0.0; kassaItems.forEach((element) { total += element.total == null ? 0.0 : element.total.toDouble(); }); - return total.toString(); + return total; } - String totalCalc(List items) { + num totalCalc(List items) { num total = 0.0; items.forEach((element) { if (element.operation == Calculations.MULTIPLY) { @@ -168,6 +385,6 @@ class _PaymentNfcViewState extends State { total += element.num1 == null ? 0.0 : double.parse(element.num1); } }); - return total.toString(); + return total; } } diff --git a/lib/views/payment_nfc/widgets/action_view.dart b/lib/views/payment_nfc/widgets/action_view.dart new file mode 100644 index 0000000..a92ba5e --- /dev/null +++ b/lib/views/payment_nfc/widgets/action_view.dart @@ -0,0 +1,49 @@ +import 'package:aman_kassa_flutter/shared/app_colors.dart'; +import 'package:aman_kassa_flutter/widgets/fields/busy_button.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +class ActionView extends StatelessWidget { + final String acceptText; + final String declineText; + final void Function() acceptCallback; + final void Function() declineCallback; + final bool show; + + const ActionView( + {Key key, + this.acceptText, + this.declineText, + this.acceptCallback, + this.declineCallback, + this.show = false}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return Positioned( + bottom: ScreenUtil().setSp(100), + left: ScreenUtil().setSp(25), + right: ScreenUtil().setSp(25), + child: AnimatedOpacity( + duration: const Duration(milliseconds: 300), + opacity: show ? 1.0 : 0.0, + child: AnimatedContainer( + duration: const Duration(milliseconds: 300), + child: buildContainer()), + )); + } + + Row buildContainer() { + return Row( + children: [ + if (acceptCallback !=null && acceptText !=null) + Expanded(child: BusyButton(title: acceptText, onPressed: acceptCallback)), + SizedBox(width: 5.0,), + if (declineCallback !=null && declineText !=null) + BusyButton(title: declineText, onPressed: declineCallback, mainColor: redColor,) + ], + ); + } +} diff --git a/lib/views/payment_nfc/widgets/phone_view.dart b/lib/views/payment_nfc/widgets/phone_view.dart index 24d44c5..242dd49 100644 --- a/lib/views/payment_nfc/widgets/phone_view.dart +++ b/lib/views/payment_nfc/widgets/phone_view.dart @@ -101,7 +101,39 @@ class _PhoneViewState extends State { children: [ Icon(MdiIcons.closeOctagon, color: redColor,size: ScreenUtil().setSp(90.0),), verticalSpaceSmall, - AutoSizeText('Ошибка', style: TextStyle(fontWeight: FontWeight.bold),) + AutoSizeText('Ошибка инициализации', style: TextStyle(fontWeight: FontWeight.bold),) + ], + ); + } + if(widget.status == 5){ + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(MdiIcons.closeOctagon, color: redColor,size: ScreenUtil().setSp(90.0),), + verticalSpaceSmall, + AutoSizeText('Ошибка соединения', style: TextStyle(fontWeight: FontWeight.bold),), + AutoSizeText('попробуйте еще раз', style: TextStyle(fontWeight: FontWeight.bold),) + ], + ); + } + if(widget.status == 6){ + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(MdiIcons.closeOctagon, color: redColor,size: ScreenUtil().setSp(90.0),), + verticalSpaceSmall, + AutoSizeText('Ошибка авторизации', style: TextStyle(fontWeight: FontWeight.bold),), + ], + ); + } + + if(widget.status == 7){ + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(MdiIcons.closeOctagon, color: redColor,size: ScreenUtil().setSp(90.0),), + verticalSpaceSmall, + AutoSizeText('Ошибка чтения карты', style: TextStyle(fontWeight: FontWeight.bold),), ], ); } diff --git a/pubspec.lock b/pubspec.lock index 452ac19..d2c59fb 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,27 +1,13 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: - archive: - dependency: transitive - description: - name: archive - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.13" - args: - dependency: transitive - description: - name: args - url: "https://pub.dartlang.org" - source: hosted - version: "1.6.0" async: dependency: transitive description: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.4.1" + version: "2.4.2" auto_size_text: dependency: "direct main" description: @@ -43,6 +29,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.0" + characters: + dependency: transitive + description: + name: characters + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" charcode: dependency: transitive description: @@ -50,13 +43,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.1.3" + clock: + dependency: transitive + description: + name: clock + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" collection: dependency: transitive description: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.14.12" + version: "1.14.13" convert: dependency: transitive description: @@ -99,6 +99,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.2" + fake_async: + dependency: transitive + description: + name: fake_async + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" file: dependency: transitive description: @@ -170,13 +177,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.1.4" - image: - dependency: transitive - description: - name: image - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.12" intl: dependency: "direct main" description: @@ -204,7 +204,7 @@ packages: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.6" + version: "0.12.8" material_design_icons_flutter: dependency: "direct main" description: @@ -232,7 +232,7 @@ packages: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.6.4" + version: "1.7.0" path_provider: dependency: "direct main" description: @@ -268,13 +268,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.9.0" - petitparser: - dependency: transitive - description: - name: petitparser - url: "https://pub.dartlang.org" - source: hosted - version: "2.4.0" platform: dependency: transitive description: @@ -338,13 +331,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.2.0" - quiver: - dependency: transitive - description: - name: quiver - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.3" redux: dependency: "direct main" description: @@ -440,7 +426,7 @@ packages: name: stack_trace url: "https://pub.dartlang.org" source: hosted - version: "1.9.3" + version: "1.9.5" stream_channel: dependency: transitive description: @@ -475,14 +461,14 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.15" + version: "0.2.17" typed_data: dependency: transitive description: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.1.6" + version: "1.2.0" url_launcher: dependency: "direct main" description: @@ -532,13 +518,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.1.0" - xml: - dependency: transitive - description: - name: xml - url: "https://pub.dartlang.org" - source: hosted - version: "3.6.1" sdks: - dart: ">=2.8.0 <3.0.0" + dart: ">=2.9.0-14.0.dev <3.0.0" flutter: ">=1.17.0 <2.0.0"