diff --git a/android/app/src/main/kotlin/kz/com/aman/kassa/MainActivity.kt b/android/app/src/main/kotlin/kz/com/aman/kassa/MainActivity.kt index c94650b..749f4e5 100644 --- a/android/app/src/main/kotlin/kz/com/aman/kassa/MainActivity.kt +++ b/android/app/src/main/kotlin/kz/com/aman/kassa/MainActivity.kt @@ -88,7 +88,9 @@ class MainActivity : FlutterActivity() { val operDay = call.argument("operDay").toString() val transNum = call.argument("transNum").toString() val operationParameters = createOperationParameters(token) - startOperation(OperationType.REVERSAL, JsonForExternalCall.getReversalJson(operationParameters.authToken, terminalId, operDay, transNum)) + val body = JsonForExternalCall.getReversalJson(operationParameters.authToken, terminalId, operDay, transNum); + println(body) + startOperation(OperationType.REVERSAL, body) } private fun operationCloseDay(call: MethodCall) { diff --git a/lib/core/services/BankService.dart b/lib/core/services/BankService.dart index e642c8f..0339563 100644 --- a/lib/core/services/BankService.dart +++ b/lib/core/services/BankService.dart @@ -83,6 +83,20 @@ class BankService extends BaseService { } } + Future reversal({ String token, int terminalId, int operDay, int transNum }) async { + try { + String response = await _channel.invokeMethod("reversal", { + 'token': token , 'terminalId': terminalId, 'operDay': operDay, 'transNum': transNum + }); + log.i(response); + HalykResponse dao = HalykResponse.fromMap(json.decode(response)); + return dao; + } catch (e, stack) { + log.e("BankService", e, stack); + return new HalykResponse(result: ResultBean(description: 'Ошибка при возврате', code: -1)); + } + } + CloseDayData closeDayDataConvert(Cd.TransactionsBean transactions) { final DateFormat formatter = DateFormat('dd.MM.yyyy'); diff --git a/lib/views/check/image_show_container.dart b/lib/views/check/image_show_container.dart index f02a403..07eabba 100644 --- a/lib/views/check/image_show_container.dart +++ b/lib/views/check/image_show_container.dart @@ -45,7 +45,6 @@ class ImageShowContainer extends StatefulWidget { } class _ImageShowContainerState extends State { - final PrinterBluetoothManager printerManager = PrinterBluetoothManager(); final DialogService _dialogService = locator(); @@ -64,11 +63,9 @@ class _ImageShowContainerState extends State { if (val == 12) { print('on'); _print(); - } else if (val == 10) { print('off'); - _dialogService.showDialog( - description: 'Отсутвует соеденение Bluetooth или он отключен' , title: 'Bluetooth'); + _dialogService.showDialog(description: 'Отсутвует соеденение Bluetooth или он отключен', title: 'Bluetooth'); } print('state is $val'); }); @@ -77,7 +74,7 @@ class _ImageShowContainerState extends State { void _print() async { final SettingState state = Redux.store.state.settingState; - if(state.printerBT == null) { + if (state.printerBT == null) { _dialogService.showDialog(description: 'Укажите в настройках принтер для печати чеков'); return; } @@ -86,7 +83,7 @@ class _ImageShowContainerState extends State { int chunkSizeBytes = 3096; int queueSleepTimeMs = 100; - if(isIos){ + if (isIos) { chunkSizeBytes = 75; queueSleepTimeMs = 10; } @@ -96,9 +93,7 @@ class _ImageShowContainerState extends State { }); try { printerManager.selectPrinter(PrinterBluetooth(state.printerBT)); - PaperSize paper = state.printerPaperSize == SettingPrinterPaperM80 - ? PaperSize.mm80 - : PaperSize.mm58; + PaperSize paper = state.printerPaperSize == SettingPrinterPaperM80 ? PaperSize.mm80 : PaperSize.mm58; if (SettingPrinterEncodingImage == state.printerEncoding) { final PosPrintResult res = await printerManager.printTicket( await printImageCheck(paper, widget.showModel.data.base64Data), @@ -109,9 +104,7 @@ class _ImageShowContainerState extends State { } } else { final PosPrintResult res = await printerManager.printTicket( - await printTextCheck( - paper, state.printerEncoding, - jsonDecode(widget.showModel.data.textData)), + await printTextCheck(paper, state.printerEncoding, jsonDecode(widget.showModel.data.textData)), chunkSizeBytes: chunkSizeBytes, queueSleepTimeMs: queueSleepTimeMs); if (res.value != 1) { @@ -134,7 +127,7 @@ class _ImageShowContainerState extends State { //backgroundColor: fillColor, title: Text(widget.showModel.title), actions: [ - if(_printing) + if (_printing) Padding( padding: const EdgeInsets.only(right: 8.0), child: SizedBox( @@ -142,8 +135,7 @@ class _ImageShowContainerState extends State { child: Center( child: CircularProgressIndicator( strokeWidth: 2, - valueColor: new AlwaysStoppedAnimation( - whiteColor), + valueColor: new AlwaysStoppedAnimation(whiteColor), ), ), ), @@ -179,7 +171,9 @@ class ImageShowModel { class MyFloatingActionButton extends StatefulWidget { final ImageShowModel data; + MyFloatingActionButton(this.data); + @override _MyFloatingActionButtonState createState() => _MyFloatingActionButtonState(); } @@ -191,44 +185,74 @@ class _MyFloatingActionButtonState extends State { final GlobalKey _keyLoader = new GlobalKey(); final DataService _dataService = locator(); - double sheetHeight = 260; - - @override Widget build(BuildContext context) { - - if (showFab) { return Column( mainAxisAlignment: MainAxisAlignment.end, children: [ - if (widget.data.cardData != null && widget.data.cardData.transactionType == "payment") FloatingActionButton( - backgroundColor: redColor, - child: Icon( - Icons.settings_backup_restore, - color: whiteColor, - ), - onPressed: () async { - _navigatorService.replace(HomeViewRoute); - try { - await Redux.store.dispatch(changePinSkipFromSetting(true)); - AmanDao response = await refundHalykPos(widget.data.cardData, widget.data.voucher.total); - if (response.success) { - pressRefund(); - } else { - _dialog.showDialog(description: response.msg); - } - } finally { - await Redux.store.dispatch(changePinSkipFromSetting(false)); - } + if (widget.data.cardData != null && widget.data.cardData.transactionType == "payment") + FloatingActionButton( + backgroundColor: redColor, + tooltip: 'Отмена', + child: Icon( + Icons.cancel, + color: whiteColor, + ), + onPressed: () async { - }, - heroTag: null, - ) else SizedBox( - height: 0, + try { + await Redux.store.dispatch(changePinSkipFromSetting(true)); + AmanDao response = await reversalHalykPos(widget.data.cardData, widget.data.voucher.total); + if (response.success) { + pressRefund(); + } else { + _dialog.showDialog(description: response.msg); + } + } finally { + await Redux.store.dispatch(changePinSkipFromSetting(false)); + } + _navigatorService.replace(HomeViewRoute); + }, + heroTag: null, + ) + else + SizedBox( + height: 0, + ), + SizedBox( + height: 10, ), + if (widget.data.cardData != null && widget.data.cardData.transactionType == "payment") + FloatingActionButton( + backgroundColor: redColor, + tooltip: 'Возврат', + child: Icon( + Icons.settings_backup_restore, + color: whiteColor, + ), + onPressed: () async { + + try { + await Redux.store.dispatch(changePinSkipFromSetting(true)); + AmanDao response = await refundHalykPos(widget.data.cardData, widget.data.voucher.total); + if (response.success) { + pressRefund(); + } else { + _dialog.showDialog(description: response.msg); + } + } finally { + await Redux.store.dispatch(changePinSkipFromSetting(false)); + } + }, + heroTag: null, + ) + else + SizedBox( + height: 0, + ), SizedBox( height: 10, ), @@ -242,12 +266,7 @@ class _MyFloatingActionButtonState extends State { decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(15)), - boxShadow: [ - BoxShadow( - blurRadius: 10, - color: Colors.grey[300], - spreadRadius: 5) - ]), + boxShadow: [BoxShadow(blurRadius: 10, color: Colors.grey[300], spreadRadius: 5)]), height: 260, child: Column( children: [ @@ -296,11 +315,8 @@ class _MyFloatingActionButtonState extends State { String _token = _state.userState.user.token; CardData _cardData = widget.data.cardData; CheckData _checkData = CheckData.fromJson(json.decode(widget.data.voucher.data)); - Response response = await _dataService.refundM4Bank( - token: _token, - cardData: _cardData, - checkData: _checkData - ); + Response response = + await _dataService.refundM4Bank(token: _token, cardData: _cardData, checkData: _checkData); if (response != null) { if (response.operation) { String message = response.body['message']; @@ -313,9 +329,12 @@ class _MyFloatingActionButtonState extends State { 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)) { + 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(); _dialog.showDialog(description: response.body['message']); } else { @@ -332,25 +351,19 @@ class _MyFloatingActionButtonState extends State { void shareFile() async { try { - await Share.file('Aman Kassa', 'aman_kassa_check.png', - base64Decode(widget.data.data.base64Data), 'image/png'); + await Share.file('Aman Kassa', 'aman_kassa_check.png', base64Decode(widget.data.data.base64Data), 'image/png'); } catch (e) { print('error: $e'); } } void qrGenerate() async { - _navigatorService.push(QrViewRoute, - arguments: - ImageShowModel(url: widget.data.url, title: 'Спасибо за покупку')); + _navigatorService.push(QrViewRoute, arguments: ImageShowModel(url: widget.data.url, title: 'Спасибо за покупку')); } void callWhatsApp() async { DialogResponse response = await _dialog.showConfirmationDialogInput( - description: 'Номер телефона', - cancelTitle: 'Отмена', - confirmationTitle: 'Отправить', - formatType: 'phone'); + description: 'Номер телефона', cancelTitle: 'Отмена', confirmationTitle: 'Отправить', formatType: 'phone'); if (response.confirmed) { String phoneNumber = response.responseText; String msg = "Спасибо за покупку! \r\n ${widget.data.url} "; @@ -382,5 +395,4 @@ class _MyFloatingActionButtonState extends State { showFab = value; }); } - } diff --git a/lib/views/payment/halyk_pos_service.dart b/lib/views/payment/halyk_pos_service.dart index 6437acd..7e32b40 100644 --- a/lib/views/payment/halyk_pos_service.dart +++ b/lib/views/payment/halyk_pos_service.dart @@ -66,7 +66,34 @@ Future> refundHalykPos(CardData refundData, double total) asyn operationDay: response.transaction.operationDay, transactionNumber: response.transaction.transactionNumber, terminalId: response.transaction.terminalId, - transactionType: 'payment' + transactionType: 'refund' + ); + return AmanDao(msg: response.result.description, success: true, data: cardData); + } + return AmanDao(msg: response.result.errorData !=null ? response.result.errorData.description : response.result.description, success: false); +} + +Future> reversalHalykPos(CardData refundData, double total) 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); + if (session.token == null) { + return AmanDao(success: false, msg: 'Отказано в доступе к API банка'); + } + log.i(refundData.toJson()); + HalykResponse response = await _bankService.reversal(token: session.token, operDay: refundData.operationDay, terminalId: refundData.terminalId, transNum: refundData.transactionNumber ); + if (response.result.code == 0) { + CardData cardData = new CardData( + authorizationCode: response.transaction.instrumentSpecificData.authorizationCode, + cardholderName: response.transaction.instrumentSpecificData.cardholderName, + cardNumber: response.transaction.instrumentSpecificData.maskedPan, + operationDay: response.transaction.operationDay, + transactionNumber: response.transaction.transactionNumber, + terminalId: response.transaction.terminalId, + transactionType: 'reversal' ); return AmanDao(msg: response.result.description, success: true, data: cardData); }