From 569c69e2687f932c2323544973879639095ae21f Mon Sep 17 00:00:00 2001 From: Ivan Murashov Date: Wed, 6 Sep 2017 17:19:11 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B5=D0=BD=D0=B5=D1=81=20?= =?UTF-8?q?=D1=85=D1=80=D0=B0=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B8=D0=BD?= =?UTF-8?q?=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=86=D0=B8=D0=B8=20=D0=BE=20?= =?UTF-8?q?=D1=81=D0=B5=D1=81=D1=81=D0=B8=D0=B8=20(=D1=82=D0=BE=D0=BA?= =?UTF-8?q?=D0=B5=D0=BD,=20din,=20posid)=20=D0=B2=20=D0=B1=D0=B0=D0=B7?= =?UTF-8?q?=D1=83=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/dinect/checker/MainActivity.java | 82 +------------------ ios/Runner/ScannerViewController.swift | 2 - lib/common.dart | 8 +- lib/db.dart | 82 +++++++++++++++++++ lib/finish_registration.dart | 26 +++--- lib/purchase.dart | 4 +- lib/registration.dart | 16 +++- lib/splash.dart | 67 +++++++++------ pubspec.yaml | 2 + 9 files changed, 162 insertions(+), 127 deletions(-) create mode 100644 lib/db.dart diff --git a/android/app/src/main/java/com/dinect/checker/MainActivity.java b/android/app/src/main/java/com/dinect/checker/MainActivity.java index 3bccbf7..67bf35c 100644 --- a/android/app/src/main/java/com/dinect/checker/MainActivity.java +++ b/android/app/src/main/java/com/dinect/checker/MainActivity.java @@ -29,9 +29,6 @@ public class MainActivity extends FlutterActivity { static final String TAG = "Checker.MainActivity"; private static final int START_SCANNER_REQUEST_CODE = 2017; - private static final String PREF_POS_MERCHANT_ID = "pref_pos_merchant_id"; - private static final String PREF_DOC_ID = "pref_doc_id"; - private static final String PREF_POS_ID = "pref_pos_id"; static final String PREF_API_URL = "prefs_api_token"; static final String PREF_APP_TOKEN = "pres_app_token"; static final String PREF_POS_TOKEN = "pref_pos_token"; @@ -52,34 +49,17 @@ public class MainActivity extends FlutterActivity { initLocale(this); mPreferences = getPreferences(Context.MODE_PRIVATE); - Log.d(TAG, "application prefs:"); - for(final Map.Entry kv: mPreferences.getAll().entrySet()){ - Log.d(TAG, " key = " + kv.getKey() + ", value = " + kv.getValue().toString()); - } - mChannel = new MethodChannel(getFlutterView(), "com.dinect.checker/instance_id"); mChannel.setMethodCallHandler( new MethodCallHandler() { @Override public void onMethodCall(MethodCall call, Result result) { switch (call.method) { - case "saveToken": - Map tokenArguments = call.arguments(); - mPreferences.edit().putString(PREF_POS_TOKEN, (String) tokenArguments.get("token")).apply(); - break; - case "getToken": - result.success(mPreferences.getString(PREF_POS_TOKEN, null)); - break; - case "saveMerchantID": - Map merchantIDArguments = call.arguments(); - mPreferences.edit().putString(PREF_POS_MERCHANT_ID, (String) merchantIDArguments.get("merchantID")).apply(); - break; + case "getLocale": result.success(BuildConfig.locale); break; - case "getMerchantID": - result.success(mPreferences.getString(PREF_POS_MERCHANT_ID, null)); - break; + case "startScanner": final Map arguments = call.arguments(); final int idx = mPreferences.getInt(SCANNER_BACKEND_KEY, 0); @@ -90,18 +70,7 @@ public class MainActivity extends FlutterActivity { cameraIntent.putExtra(PREF_POS_TOKEN, (String) arguments.get("token")); startActivityForResult(cameraIntent, START_SCANNER_REQUEST_CODE); break; - case "removeKeys": - mPreferences.edit().remove(PREF_POS_TOKEN).apply(); - mPreferences.edit().remove(PREF_POS_MERCHANT_ID).apply(); - mPreferences.edit().remove(PREF_DOC_ID).apply(); - mPreferences.edit().remove(PREF_POS_ID).apply(); - result.success(null); - break; - case "getDocID": - int docId = mPreferences.getInt(PREF_DOC_ID, 0) + 1; - mPreferences.edit().putInt(PREF_DOC_ID, docId).apply(); - result.success(String.valueOf(docId)); - break; + case "isOnline": boolean online = Utils.isOnline(MainActivity.this); if (!online) { @@ -109,14 +78,7 @@ public class MainActivity extends FlutterActivity { } result.success(online); break; - case "getPosID": - String posId = mPreferences.getString(PREF_POS_ID, null); - if (posId == null) { - posId = String.valueOf(System.currentTimeMillis()); - } - mPreferences.edit().putString(PREF_POS_ID, posId).apply(); - result.success(posId); - break; + default: result.notImplemented(); break; @@ -169,53 +131,17 @@ public class MainActivity extends FlutterActivity { res.updateConfiguration(configuration, res.getDisplayMetrics()); break; } - } public void getLocale() { } - public void handleItemClick() { - - } - - public void getDocID() { - - } - - public void removeKeys() { - - } public void startScanner() { } - public void getInstanceID() { - - } - - public void saveToken() { - - } - - public void getToken() { - - } - - public void getPosID() { - - } - - public void saveMerchantID() { - - } - - public void getMerchantID() { - - } - public void isOnline() { } diff --git a/ios/Runner/ScannerViewController.swift b/ios/Runner/ScannerViewController.swift index 0cae00b..91a18a1 100644 --- a/ios/Runner/ScannerViewController.swift +++ b/ios/Runner/ScannerViewController.swift @@ -17,8 +17,6 @@ extension ZBarSymbolSet: Sequence { } } -// TODO: Реализовать окно сканнера в этом контроллере, вместо вызова ZBarReaderViewController - @objc class ScannerViewController: UIViewController, ZBarReaderDelegate { override func viewDidLoad() { diff --git a/lib/common.dart b/lib/common.dart index 78c0075..a616ca2 100644 --- a/lib/common.dart +++ b/lib/common.dart @@ -25,7 +25,7 @@ faq(BuildContext context, bool returnToScanner) { // В методе отправляется запрос на удаление токена кассы, очищаются SharedPreferences приложения. logout(BuildContext context) async { - String token = await platform.invokeMethod('getToken'); + String token = await sqliteHelper.getToken(); VoidCallback positiveCalback = () { if (token != null) { deleteToken(token).then((response) { @@ -48,7 +48,7 @@ logout(BuildContext context) async { } forceLogout(BuildContext context) async { - String token = await platform.invokeMethod('getToken'); + String token = await sqliteHelper.getToken(); deleteToken(token).then((response) { print(response.body); platform.invokeMethod('removeKeys').then((result) { @@ -64,9 +64,9 @@ forceLogout(BuildContext context) async { /// Может производиться с нескольких экранов (splash, finish_registration). startScanner(BuildContext context) async { - String token = await platform.invokeMethod('getToken'); + String token = await sqliteHelper.getToken(); // Канал ловит вызовы методов из "нативной" части приложения. - // Могут быть вызваны либо logaut либо faq, либо purchase. + // Могут быть вызваны либо logout либо faq, либо purchase. if (token != null) { platform.setMethodCallHandler((MethodCall call) async { diff --git a/lib/db.dart b/lib/db.dart new file mode 100644 index 0000000..2443ccc --- /dev/null +++ b/lib/db.dart @@ -0,0 +1,82 @@ +import 'dart:async'; +import 'dart:io'; + +import 'package:path/path.dart'; +import 'package:sqflite/sqflite.dart'; +import 'package:path_provider/path_provider.dart'; + +const String tableSession = "session"; +const String columnMerchantID = "merchant_id"; // DIN code, который вводится при авторизации +const String columnToken = "token"; // Токен для pos. Приходит с бэкэнда. +const String columnPosID = "pos_id"; // идентификатор для создания токена на бэке. +const String columnDocID = "doc_id"; // идентификатор, для проведения покупки на бэкенде. + +//{ +// columnMerchantID: merchantID, +// columnToken: token, +// columnPosID: posID, +// columnDocID: docID +//} + +/// База данных, для хранения временных данных (din, token, locale, etc.) +class SqliteHelper { + + Database db; + + Future open() async { + Directory documentsDirectory = await getApplicationDocumentsDirectory(); + String path = join(documentsDirectory.path, "demo.db"); + db = await openDatabase(path, version: 1, + onCreate: (Database db, int version) async { + await db.execute('''create table session ( + $columnMerchantID text primary key, + $columnToken text, + $columnPosID text, + $columnDocID integer)'''); + }); + } + + Future insert(String merchantID, String posID, String token) async { + + Map session = { + columnMerchantID: merchantID, + columnPosID: posID, + columnToken: token + }; + + return db.insert(tableSession, session); + } + + Future getToken() async { + Map session = await _getSession(); + return session != null ? session[columnToken] : null; + } + + Future getMerchantID() async { + Map session = await _getSession(); + return session != null ? session[columnMerchantID] : null; + } + + Future getPosID() async { + Map session = await _getSession(); + return session != null ? session[columnPosID] : new DateTime.now().millisecondsSinceEpoch.toString(); + } + + Future _getSession() async { + + List maps = await db.query(tableSession, columns: null); + + if (maps.length > 0) { + return maps.first; + } + + return null; + } + + Future clear() async { + return await db.delete(tableSession, where: null); + } + + Future close() async => db.close(); + +} \ No newline at end of file diff --git a/lib/finish_registration.dart b/lib/finish_registration.dart index 30b2351..46959a7 100644 --- a/lib/finish_registration.dart +++ b/lib/finish_registration.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:checker/db.dart'; import 'dart:convert'; // Пакет для обработки json с ответом от сервера. import 'package:checker/common.dart'; @@ -14,12 +15,22 @@ class FinishRegistrationScreen extends StatefulWidget { class _RegistrationScreenState extends BaseState { + SqliteHelper helper; + bool _tokenActive = false; String _merchantID = ''; _RegistrationScreenState() { + helper = new SqliteHelper(); if (textFieldValue == "") { - getSavedMerchantID(); + helper.open().then((_){ + helper.getMerchantID().then((result) { + setState(() { + _merchantID = result; + print('merchanID: ${_merchantID}'); + }); + }); + }); } } @@ -47,10 +58,11 @@ class _RegistrationScreenState extends BaseState { // Если нет, то отправляется запрос на проверку статуса токена. handleTap() async { if (_tokenActive) { + helper.close(); startScanner(context); } else { if (await platform.invokeMethod('isOnline')) { - String token = await platform.invokeMethod('getToken'); + String token = await helper.getToken(); checkTokenStatus(token).then((response) { print(response.body); @@ -74,16 +86,6 @@ class _RegistrationScreenState extends BaseState { style: new TextStyle(color: Colors.black, fontSize: 16.0))]); } - /// Достаем сохраненный в SharedPreferences merchantID. - getSavedMerchantID() { - platform.invokeMethod('getMerchantID').then((result) { - setState(() { - _merchantID = result; - print('merchanID: ${_merchantID}'); - }); - }); - } - /// Метод возвращает контейнер с текстом сообщения и бэкграундом. getMessage() { return new Container(height: _tokenActive ? 72.0 : 108.0, decoration: _getDecorationForMessageField(), diff --git a/lib/purchase.dart b/lib/purchase.dart index 6922afc..4a44169 100644 --- a/lib/purchase.dart +++ b/lib/purchase.dart @@ -108,7 +108,7 @@ class PurchaseScreenState extends BaseState { if (await platform.invokeMethod('isOnline')) { - String token = await platform.invokeMethod('getToken'); + String token = await sqliteHelper.getToken(); var headers = { 'DM-Authorization': 'dmapptoken $appToken', @@ -198,7 +198,7 @@ class PurchaseScreenState extends BaseState { if (!purchaseInProgress) { purchaseInProgress = true; - String token = await platform.invokeMethod('getToken'); + String token = await sqliteHelper.getToken(); platform.invokeMethod('getDocID').then((result) { String url = user['purchases_url']; diff --git a/lib/registration.dart b/lib/registration.dart index 0213c8b..4ea45b5 100644 --- a/lib/registration.dart +++ b/lib/registration.dart @@ -1,3 +1,4 @@ +import 'package:checker/db.dart'; import 'package:checker/finish_registration.dart'; import 'package:flutter/material.dart'; import 'dart:convert'; // Пакет для обработки json с ответом от сервера. @@ -70,7 +71,12 @@ class _RegistrationScreenState extends BaseState { /// Получение от платформы id установки, формирование запроса на получение токена, сохранение токена. _register() async { if (await platform.invokeMethod('isOnline')) { - createToken(textFieldValue, await platform.invokeMethod('getPosID')).then((response) { + + SqliteHelper helper = new SqliteHelper(); + await helper.open(); + String posID = await helper.getPosID(); + + createToken(textFieldValue, posID).then((response) { setState(() { error = null; @@ -80,17 +86,19 @@ class _RegistrationScreenState extends BaseState { print(response.body); Map parsedMap = JSON.decode(response.body); + if (response.statusCode == 201) { - String token = parsedMap['token']; - platform.invokeMethod('saveToken', {'token' : token}); - platform.invokeMethod('saveMerchantID', {'merchantID' : textFieldValue}); + helper.insert(textFieldValue, posID, parsedMap['token']); + helper.close(); pushRoute(context, new FinishRegistrationScreen()); } else { + helper.close(); setState(() { error = parsedMap['errors'][0]; }); } }).catchError((error) { + helper.close(); print(error.toString()); }); } diff --git a/lib/splash.dart b/lib/splash.dart index 16cef33..84323b0 100644 --- a/lib/splash.dart +++ b/lib/splash.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:http/http.dart'; import 'package:intl/intl.dart'; import 'dart:async'; @@ -9,7 +10,7 @@ import 'network.dart'; import 'consts.dart'; import 'registration.dart'; import 'finish_registration.dart'; -import 'strings.dart'; +import 'db.dart'; class SplashScreen extends StatelessWidget { @@ -18,7 +19,7 @@ class SplashScreen extends StatelessWidget { // Появляется splash screen, проверяется токен. new Future.delayed(const Duration(milliseconds: 500), () { - platform.invokeMethod("getLocale").then((locale) { + platform.invokeMethod('getLocale').then((locale) { Intl.defaultLocale = locale; print(Intl.defaultLocale); showNextScreen(context); @@ -49,19 +50,24 @@ class SplashScreen extends StatelessWidget { /// Запуск следующего экрана приложения. showNextScreen(BuildContext context) async { - String token = await platform.invokeMethod('getToken'); - + SqliteHelper helper = new SqliteHelper(); + await helper.open(); + String token = await helper.getToken(); + // В случае, если в приложении отсутствует токен, // необходимо запустить регистрацию кассы. if (token == null) { + await helper.close(); pushRoute(context, new RegistrationScreen()); } else { if (await platform.invokeMethod('isOnline')) { checkTokenStatus(token).then((statusResponse) { - handleStatusResponse(context, statusResponse); + handleStatusResponse(context, statusResponse, helper); }).catchError((error) { - print(error.toString()); - return false; + helper.close().then((_) { + print(error.toString()); + return false; + }); }); } } @@ -70,14 +76,15 @@ class SplashScreen extends StatelessWidget { /// Обработка ответа. /// В случае, если токен был удален может прийти active: false, либо 404. /// Если токен не активен, попробовать создать его еще раз. - handleStatusResponse(BuildContext context, var statusResponse) async { + handleStatusResponse(BuildContext context, var statusResponse, SqliteHelper helper) async { int code = statusResponse.statusCode; print('resp: ${code}'); if (code == 404) { - platform.invokeMethod('removeKeys').then((result) { - print('try to start registration'); - pushRoute(context, new RegistrationScreen()); + helper.clear().then((result) { + helper.close().then((_) { + pushRoute(context, new RegistrationScreen()); + }); }); } else { @@ -88,7 +95,7 @@ class SplashScreen extends StatelessWidget { startScanner(context); } else { if (await platform.invokeMethod('isOnline')) { - _createToken(context); + _createToken(context, helper); } } } @@ -101,24 +108,34 @@ class SplashScreen extends StatelessWidget { /// /// Если вернулся код 200, значит токен был ранее удален и только что снова создался. /// Нужно удалить его и направить пользователя на экран регистрации. - _createToken(BuildContext ctx) async { - String merchantID = await platform.invokeMethod('getMerchantID'); - String posID = await platform.invokeMethod('getPosID'); + _createToken(BuildContext ctx, SqliteHelper helper) async { + + String merchantID = await helper.getMerchantID(); + String posID = await helper.getPosID(); + createToken(merchantID, posID).then((response) { if (response.statusCode == 409) { + helper.close(); pushRoute(ctx, new FinishRegistrationScreen()); } else if (response.statusCode == 201) { - platform.invokeMethod('removeKeys').then((result) { - Map parsedMap = JSON.decode(result); - deleteToken(parsedMap['token']).then((response) { - print(response.body); - Navigator.of(ctx).pop(); // Убираем текущий route - pushRoute(ctx, new RegistrationScreen()); // Запускаем регистрацию - }).catchError((error) { - print(error.toString()); - }); - }); + clearToken(response, ctx, helper); } }).catchError((error) => print(error.toString())); } + + /// Очищаем бд, делаем запрос на удаление токена. + void clearToken(Response response, BuildContext ctx, SqliteHelper helper) { + + helper.clear().then((_) { + Map parsedMap = JSON.decode(response.body); + deleteToken(parsedMap['token']).then((_) { + helper.close(); + Navigator.of(ctx).pop(); // Убираем текущий route + pushRoute(ctx, new RegistrationScreen()); // Запускаем регистрацию + }).catchError((error) { + helper.close(); + print(error.toString()); + }); + }); + } } diff --git a/pubspec.yaml b/pubspec.yaml index eb6d9a4..eb63b7f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -6,6 +6,8 @@ dependencies: intl: '>=0.14.0 <0.16.0' intl_translation: '>=0.14.0 <0.16.0' sprintf: "^3.0.2" + path_provider: "^0.2.1+1" + sqflite: any flutter: sdk: flutter