import 'dart:convert'; import 'package:aman_kassa_flutter/core/entity/Voucher.dart'; 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/card_data.dart'; import 'package:aman_kassa_flutter/core/models/check_data.dart'; import 'package:aman_kassa_flutter/core/models/check_image_modal.dart'; import 'package:aman_kassa_flutter/core/models/halyk_post_session.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'; import 'package:aman_kassa_flutter/redux/actions/calc_actions.dart'; 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/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/logo_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/loader/Dialogs.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; const PaymentNfcView({Key key, this.model}) : super(key: key); @override _PaymentNfcViewState createState() => _PaymentNfcViewState(); } 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; int status; @override void initState() { super.initState(); isBusy = false; isPhoneScaled = false; status = 0; start(); } void start() async { //Авторизация String token = Redux.store.state.userState.user.token; BankState bankState = Redux.store.state.bankState; //права доступа HalykPosSession session = await _bankService.renewToken(token: token, login: bankState.login, password: bankState.password); log.i(session); if (session.token ==null) { setState(() { status = 4; }); return; } //Инициализация bool initialized = await _bankService.init(token: session.token); log.i(initialized); if (1 == 1) { setState(() { status = 4; }); return; } //права доступа // bool success = await _bankService.permissions(); // log.i(success); // if (!success) { // setState(() { // status = 4; // }); // return; // } var today = new DateTime.now(); var yesterday = today.subtract(new Duration(days: 1)); if( Redux.store.state.userState == null || Redux.store.state.userState.smena == null || Redux.store.state.userState.smena.startedAt == null || yesterday.isAfter(Redux.store.state.userState.smena.startedAt)) { _dialogService.showDialog(description: 'Текущая смена открыта более 24 ч. Необходимо закрыть смену и открыть ее заново.'); _navigatorService.pop(); return; } // //Инициализация // 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; } 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; } //валюта bool currency = await _bankService.currency(); log.i(currency); if (!currency) { setState(() { status = 4; }); return; } if(widget.model.voucher == null) { pay(); } else { refund(); } } refund() async { CardData _cardData = widget.model.cardData; AmanDao findTransaction = await _bankService.findTransaction(transactionNumber: _cardData.transactionNumber, authorizationCode: _cardData.authorizationCode); if(!findTransaction.success){ _dialogService.showDialog(description: findTransaction.msg); setState(() { status = 8; }); return; } setState(() { status = 1; isPhoneScaled = true; }); AmanDao refundDao = await _bankService.refund(); if (!refundDao.success) { int _status = 7; setState(() { status = _status; isPhoneScaled = false; }); if (refundDao.msg != null) { log.i(refundDao.msg); _dialogService.showDialog(description: refundDao.msg); } return; } setState(() { status = 9; isPhoneScaled = false; }); //check pressRefund('card' , refundDao.data); } 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' , payDao.data); } cancel() async { bool isCanceled = await _bankService.cancel(); _navigatorService.pop(); } pressPayment(String type, dynamic cardDataDynamic) 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; } CardData cardData = cardDataDynamic != null ? CardData.fromJson(cardDataDynamic) : null; 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, cardData: cardData ); setState(() { isBusy = false; }); if (response != null) { if (response.operation) { String message = response.body['message']; String check = response.body['check']; var checkText = response.body['check_text']; 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: new CheckImageModal(base64Data: check, textData: checkText !=null ? jsonEncode(checkText) : null ), 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; }); } } pressRefund(String type, dynamic cardDataDynamic) async { setState(() { isBusy = true; }); Dialogs.showLoadingDialog(context, _keyLoader); try { AppState _state = Redux.store.state; String _token = _state.userState.user.token; CardData _cardData = cardDataDynamic != null ? CardData.fromJson(cardDataDynamic) : null; CheckData _checkData = CheckData.fromJson(json.decode(widget.model.voucher.data)); Response response = await _dataService.refundM4Bank( token: _token, cardData: _cardData, checkData: _checkData ); setState(() { isBusy = false; }); if (response != null) { if (response.operation) { String message = response.body['message']; String check = response.body['check']; var checkText = response.body['check_text']; String url = response?.body['link']; print('url : $url'); Redux.store.dispatch(checkMoney); Redux.store.dispatch(openSmenaPseudo); Navigator.of(_keyLoader.currentContext, rootNavigator: true).pop(); _navigatorService.replace(HomeViewRoute); _navigatorService.push(ImageShowRoute, arguments: ImageShowModel(data: new CheckImageModal(base64Data: check, textData: checkText !=null ? jsonEncode(checkText) : null ), 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 Widget build(BuildContext context) { return WillPopScope( onWillPop: () { if (!isBusy) Navigator.pop(context); return new Future(() => false); }, child: Scaffold( appBar: AppBar( brightness: Brightness.light, backgroundColor: purpleColor, elevation: 0, leading: IconButton( icon: Icon(Icons.arrow_back_ios), color: whiteColor, onPressed: () => Navigator.pop(context), ), title: Text( dataTitle(), style: TextStyle(color: whiteColor), ), ), body: Container( decoration: BoxDecoration(color: purpleColor), padding: EdgeInsets.symmetric( vertical: ScreenUtil().setSp(12.0), horizontal: ScreenUtil().setSp(12.0)), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( dataText(), style: TextStyle( fontWeight: FontWeight.bold, color: whiteColor.withOpacity(0.7), fontSize: ScreenUtil().setSp(15.0)), ), buildStoreConnector(), Expanded( child: Stack( children: [ BackgroundView(), LogoView(), TextStateView( status: status, ), CardView( show: isPhoneScaled, ), PhoneView( scaled: isPhoneScaled, status: status, ), buildActionView() ], ), ) ], ), ), ), ); } 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; case 8: return ActionView( show: true, acceptText: 'Повторить', acceptCallback: () { refund(); }, declineText: 'Отмена', declineCallback: () { cancel(); }, ); break; default: } return ActionView(); } String dataTitle() => widget.model.operationType == OperationTypePay ? 'Оплата' : 'Возврат'; String dataText() => widget.model.operationType == OperationTypePay ? 'К оплате' : 'К возврату'; StoreConnector buildStoreConnector() { if (widget.model.mode == SettingModeCalc) { return StoreConnector( converter: (store) => store.state.calcState, builder: (_, vm) { return Text('${totalCalc(vm.calcItems)} тнг', style: TextStyle( fontWeight: FontWeight.bold, color: whiteColor, fontSize: 35)); }); } if(widget.model.voucher !=null) { return StoreConnector( converter: (store) => store.state.kassaState, builder: (_, vm) { return Text('${widget.model.voucher.total} тнг', style: TextStyle( fontWeight: FontWeight.bold, color: whiteColor, fontSize: 35)); }); } return StoreConnector( converter: (store) => store.state.kassaState, builder: (_, vm) { return Text('${totalKassa(vm.kassaItems)} тнг', style: TextStyle( fontWeight: FontWeight.bold, color: whiteColor, fontSize: 35)); }); } num totalKassa(List kassaItems) { num total = 0.0; kassaItems.forEach((element) { total += element.total == null ? 0.0 : element.total.toDouble(); }); return total; } num totalCalc(List items) { num total = 0.0; items.forEach((element) { if (element.operation == Calculations.MULTIPLY) { double num1 = element.num1 == null ? 0.0 : double.parse(element.num1); double num2 = element.num2 == null ? 0.0 : double.parse(element.num2); total += num1 * num2; } else { total += element.num1 == null ? 0.0 : double.parse(element.num1); } }); return total; } }