Перенес хранение информации о сессии (токен, din, posid) в базу данных
This commit is contained in:
@@ -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<String, ?> 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() {
|
||||
|
||||
}
|
||||
|
||||
@@ -17,8 +17,6 @@ extension ZBarSymbolSet: Sequence {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Реализовать окно сканнера в этом контроллере, вместо вызова ZBarReaderViewController
|
||||
|
||||
@objc class ScannerViewController: UIViewController, ZBarReaderDelegate {
|
||||
|
||||
override func viewDidLoad() {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
82
lib/db.dart
Normal file
82
lib/db.dart
Normal file
@@ -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<String> getToken() async {
|
||||
Map session = await _getSession();
|
||||
return session != null ? session[columnToken] : null;
|
||||
}
|
||||
|
||||
Future<String> getMerchantID() async {
|
||||
Map session = await _getSession();
|
||||
return session != null ? session[columnMerchantID] : null;
|
||||
}
|
||||
|
||||
Future<String> getPosID() async {
|
||||
Map session = await _getSession();
|
||||
return session != null ? session[columnPosID] : new DateTime.now().millisecondsSinceEpoch.toString();
|
||||
}
|
||||
|
||||
Future<Map> _getSession() async {
|
||||
|
||||
List<Map> 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();
|
||||
|
||||
}
|
||||
@@ -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<FinishRegistrationScreen> {
|
||||
|
||||
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<FinishRegistrationScreen> {
|
||||
// Если нет, то отправляется запрос на проверку статуса токена.
|
||||
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<FinishRegistrationScreen> {
|
||||
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(),
|
||||
|
||||
@@ -108,7 +108,7 @@ class PurchaseScreenState<T> extends BaseState<PurchaseScreen> {
|
||||
|
||||
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<T> extends BaseState<PurchaseScreen> {
|
||||
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'];
|
||||
|
||||
@@ -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<RegistrationScreen> {
|
||||
/// Получение от платформы 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<RegistrationScreen> {
|
||||
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());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user