authentic.network
Overview
On this and the next pages you will find the necessary things to use our technology and integrate it into your own systems and apps.
There are mainly two different user groups interacting with our technology. On the one hand, this is the manufacturer of an item, or in the later lifecycle, the owner. The manufacturer and owner maintain the contents of the item via the API and are informed about the events that have occurred, e.g. item was scanned. This interaction takes place purely via our API. The other user group are the users who scan our authentic.code, e.g. because they have bought a product on which our authentic.code is applied. These users want to know if it is an original. Various items also allow interaction such as calling services.
Get authentic.codes
To get authentic.codes please contact us by mail. We provide a welcome package with several codes for testing. We will send this to you by mail.
Use Cases
API
We provide a documention and example calls (request/response) of our API here. For an embeded version open navigation link "Rest-API" on left side in menu.
SDK
This chapter explains how a third party developer can integrate our technology into their own app. For this purpose, we offer various integration options. The detection of original/fake is provided as an easy to integrate plugin. This allows our technology to be used very easily and quickly in native apps in Android and IOS. Likewise, we offer a cross-compile solution with Flutter.
Android
The implementation examples are being created.
IOS
The implementation examples are being created.
Flutter
The following code example shows a complete minimal application to scan an authentic.code. More information about flutter you can find here. To get access on our plugin, contact us by mail.
pubspec.yml
dependencies:
authentic_scan:
git:
url: contact us
ref: current version
main.dart
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
void main() {
runApp(AuthenticScanExample());
}
Route<dynamic> generateRoute(RouteSettings settings) {
switch (settings.name) {
case ScanScreen.name:
return MaterialPageRoute(builder: (context) => ScanScreen());
case ResultScreen.name:
return MaterialPageRoute(builder: (context) {
return ResultScreen(arguments: settings.arguments);
});
default:
return MaterialPageRoute(
builder: (context) => Scaffold(
body: Center(
child: Text('No path for ${settings.name}'),
),
),
);
}
}
class AuthenticScanExample extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Example App',
supportedLocales: _defaultSupportedLocales,
onGenerateRoute: generateRoute,
initialRoute: ScanScreen.name,
);
}
}
Simple scan screen.
import 'dart:async';
import 'package:authentic_scan/client/client_api_v2.dart';
import 'package:authentic_scan/controller/scan_controller.dart';
import 'package:authentic_scan/widgets/scan_widget.dart';
import 'package:authentic_scan_example/result_screen.dart';
import 'package:flutter/material.dart';
import 'package:authentic_scan/model/scan_result_event.dart';
import 'package:geolocator/geolocator.dart';
import 'package:authentic_scan/model/location.dart';
import 'package:authentic_scan/authentic_scan_version.dart';
class ScanScreen extends StatefulWidget {
static const String name = 'ScanScreen';
ScanScreen({Key key}) : super(key: key);
@override
_ScanScreenState createState() => _ScanScreenState();
}
class _ScanScreenState extends State<ScanScreen> {
ScanController scanController;
String description;
bool readyForNextScanEvent = true;
bool cameraOn = false;
Location location;
VersionInfo versionInfo;
_ScanScreenState() {
description = '';
}
@override
void initState() {
print('- INIT SCANSCREEN -');
super.initState();
Geolocator.checkPermission().then((result) async {
if ((result == LocationPermission.always) ||
(result == LocationPermission.whileInUse)) {
var position = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.high);
location = Location(position.latitude, position.longitude);
}
});
AuthenticScanInfo.getVersionInfo().then((value) => versionInfo = value);
}
@override
void dispose() {
scanController.removeScanResultEventListener(onScanResult);
scanController = null;
super.dispose();
}
Future<bool> initController() async {
print('- INIT CONTROLLER -');
// TODO: handle different locale for client?
scanController = ScanController(
apiClientOptions: ClientApiOptions.testing(locale: 'en'),
simulatorMode: false);
scanController.addScanResultEventListener(onScanResult);
return true;
}
void onScanResult(ScanResultEvent event) {
if (!event.scanResultAccepted) {
return;
}
if (!readyForNextScanEvent) {
return;
}
readyForNextScanEvent = false;
scanController.stopScanSession().then((result) {
_pushResultScreen(event);
});
}
void _pushResultScreen(ScanResultEvent event) {
Navigator.pushNamed(context, ResultScreen.name,
arguments: ScanResultArguments(
scanResultEvent: event,
scanSessionLog: scanController.scanSessionLog))
.then((value) {
setState(() {
readyForNextScanEvent = true;
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color.fromARGB(255, 0, 72, 117),
body: Stack(alignment: Alignment(0, 0), children: <Widget>[
FutureBuilder<bool>(
future: initController(),
builder: (context, snapshot) {
return snapshot.connectionState == ConnectionState.done
? ScanWidget(
scanController: scanController,
showCheckmarkDetection: false)
: Container();
}),
Text(description),
]));
}
}
Simple result screen.
import 'dart:io';
import 'dart:ui';
import 'package:authentic_scan/client/scan_verification.dart';
import 'package:authentic_scan/model/scan_result_event.dart';
import 'package:authentic_scan/helper/enum.dart';
import 'package:flutter/material.dart';
import 'package:authentic_scan/authentic_scan_types.dart';
import 'package:authentic_scan/authentic_scan_version.dart';
import 'package:authentic_scan/device_check.dart';
class ScanResultArguments {
ScanResultEvent scanResultEvent;
List<ScanSessionLogEvent> scanSessionLog;
ScanResultArguments({this.scanResultEvent, this.scanSessionLog});
}
class ResultScreen extends StatefulWidget {
static const String name = 'ResultScreen';
final ScanResultArguments arguments;
ResultScreen({Key key, @required this.arguments}) : super(key: key);
@override
_ResultScreenState createState() => _ResultScreenState();
}
class _ResultScreenState extends State<ResultScreen> {
bool showDebug = false;
ScanVerificationState scanVerification;
var textStyle = TextStyle(color: Colors.white, fontSize: 15);
var textStyleHeadline =
TextStyle(color: Colors.white, fontSize: 17, fontWeight: FontWeight.bold);
@override
void initState() {
super.initState();
scanVerification = ScanVerificationStarted();
requestVerification();
}
void requestVerification() async {
return widget.arguments.scanResultEvent.scanVerification
.then((scanVerificationResult) {
_setScanVerification(
ScanVerificationDone(result: scanVerificationResult));
}).catchError((error) {
print(error);
_setScanVerification(ScanVerificationError());
});
}
void _setScanVerification(ScanVerificationState state) {
if (mounted) {
setState(() {
scanVerification = state;
});
}
}
Widget buildScanEventResult(BuildContext context) {
return Column(
children: <Widget>[
Text('ScanEvent', style: textStyleHeadline),
SizedBox(height: 10),
Text('Code: ${widget.arguments.scanResultEvent.id}',
style: textStyle),
Text(
'CopyClassification: ${enumToString(widget.arguments.scanResultEvent.copyClassification)}',
style: textStyle),
Text(
'DetectedCheckmarVersion: ${widget.arguments.scanResultEvent.detectedCheckmarkVersion}',
style: textStyle),
Text(
'TimeToResult: ${widget.arguments.scanSessionLog.isEmpty ? 'scanSessionLog is empty' : widget.arguments.scanSessionLog.last.timeFromStart}ms',
style: textStyle)
],
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start);
}
Widget buildVersion(BuildContext context) {
var list = <Widget>[];
list.add(Container(height: 30));
list.add(Text('AuthenticScan', style: textStyleHeadline));
list.add(Container(height: 10));
list.add(FutureBuilder<VersionInfo>(
future: AuthenticScanInfo.getVersionInfo(),
builder: (context, snapshot) {
var value = snapshot.connectionState == ConnectionState.done
? snapshot.data.getVersionString()
: 'waiting ...';
return Text('Version: $value', style: textStyle);
}));
return Column(
children: list,
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start);
}
Widget buildDeviceInfo(BuildContext context) {
var list = <Widget>[];
list.add(Container(height: 30));
list.add(Text('DeviceInfo', style: textStyleHeadline));
list.add(Container(height: 10));
list.add(FutureBuilder<Map<String, dynamic>>(
future: DeviceCheck.requestDeviceInfo(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
var list = <Widget>[];
list.add(Text('OS: ${snapshot.data['os'] ?? 'unknown'}',
style: textStyle));
if (Platform.isIOS) {
list.add(Text(
'Machine: ${snapshot.data['environment']['utsname']['machine'] ?? 'unknown'}',
style: textStyle));
list.add(Text(
'Model: ${snapshot.data['environment']['model'] ?? 'unknown'}',
style: textStyle));
list.add(Text(
'Model: ${snapshot.data['environment']['systemVersion'] ?? 'unknown'}',
style: textStyle));
} else if (Platform.isAndroid) {
list.add(Text(
'Brand: ${snapshot.data['environment']['brand'] ?? 'unknown'}',
style: textStyle));
list.add(Text(
'Model: ${snapshot.data['environment']['model'] ?? 'unknown'}',
style: textStyle));
list.add(Text(
'Device: ${snapshot.data['environment']['device'] ?? 'unknown'}',
style: textStyle));
}
return Column(
children: list,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start);
} else {
return Container();
}
}));
return Column(
children: list,
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start);
}
Widget buildScanSessionLog(BuildContext context) {
var list = <Widget>[];
list.add(Container(height: 30));
list.add(Text('ScanSessionLog', style: textStyleHeadline));
list.add(Container(height: 10));
var first = true;
widget.arguments.scanSessionLog.forEach((event) {
if (!first) {
list.add(Container(height: 10));
}
first = false;
list.add(buildScanSessionLogEntry(context, event));
});
return Column(
children: list,
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start);
}
Widget buildScanSessionLogEntry(
BuildContext context, ScanSessionLogEvent event) {
var imageQualityString = 'iq:';
if (event.data.containsKey('imageQuality')) {
(event.data['imageQuality'] as Map<String, dynamic>)
?.forEach((key, value) {
if (key != 'all' && !value) {
imageQualityString += ' $key';
}
});
if (imageQualityString == 'iq:') {
// if we did not name a quality issue above
imageQualityString +=
event.data['imageQuality']['all'] ? ' ok' : ' unspecified problem';
}
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text('after ${event.timeFromStart.toString()}ms',
style: textStyle, textAlign: TextAlign.left),
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('id: ${event.data['id'] == '' ? '-' : event.data['id']}',
style: textStyle),
Text("cc: ${event.data["copyClassification"]}",
style: textStyle)
]),
Text(imageQualityString, style: textStyle)
]);
}
Widget buildVerificationResult(BuildContext context) {
var list = <Widget>[];
list.add(Container(height: 30));
list.add(Text('Verification', style: textStyleHeadline));
list.add(Container(height: 10));
if (scanVerification is ScanVerificationDone) {
var result = (scanVerification as ScanVerificationDone).result;
if (result.identifier != null) {
list.add(Text('Title: ${result.identifier.title}', style: textStyle));
list.add(Text('Scan-ID: ${result.scan.id}', style: textStyle));
if (result.identifier.imageUrl != null) {
list.add(Padding(
child: Image.network(result.identifier.imageUrl),
padding: EdgeInsets.fromLTRB(0, 10, 0, 10)));
}
} else {
list.add(Text('No data available, identifier not registered.',
style: textStyle));
}
} else if (scanVerification is ScanVerificationStarted) {
list.add(Padding(
padding: EdgeInsets.fromLTRB(0, 10, 0, 10),
child: Center(child: CircularProgressIndicator())));
}
return Column(
children: list,
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start);
}
Widget buildResult(BuildContext context) {
var list = <Widget>[];
list.add(buildScanEventResult(context));
list.add(buildVersion(context));
list.add(buildDeviceInfo(context));
list.add(buildScanSessionLog(context));
list.add(buildVerificationResult(context));
return Padding(
child: ListView(children: list), padding: EdgeInsets.all(20));
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Container(
color: Color.fromARGB(255, 0, 72, 117),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Expanded(
child: Padding(
child: buildResult(context),
padding: EdgeInsets.fromLTRB(0, 0, 0, 0)))
],
),
));
}
}
Clowd
The implementation examples are being created.
OnPremise
The implementation examples are being created.