© M&S SystemSolutions GmbH und Fa. Compilager.de
Unsere Insika-Bibliothek verbindet sich automatisch mit einem im System vorhandenen
Kartenlesegerät und kommuniziert mit der TIM Karte.
Im Folgenden werden Beispiele anhand der gemanagten .Net Version der API genannt.
Wir haben unter anderem auch eine native API als alternative jedoch wird derzeit nur die
.NEt Variante aktiv von uns genutzt da mono/core mittlerweile zuverlässig und anstandslos
auf Linux basierten Systemen funktionieren
Die Bibliothek wurde gegen .Net Standart 2.0 kompiliert und benötigt eine .Net
Laufzeitumgebung von 4.6.1, Mono 5.2.0 oder Net Core 2.0 und nutzt das cross-platform
PCSC Interface zur Kommunikation mit dem Kartenleser
Nachdem die Bibliothek in den Verweisen eingetragen wurde hat man zugriff auf die Klasse
>>InsikaServer.
Es wird empfohlen eine statische Instanz dieser klasse für die Dauer des Betriebs im
Speicher zu haben.
Die Methode SCardConnnect() wird verwendet um sich mit dem Lesegerät zu verbinden,
anschließend nutzen wir die Methode SmartCardInitialization() um die SmartCard selbst zu
initialisieren.
Neben den zurückgegebenen Daten werden derzeit auch alle Transaktionen in einem XML
log festgehalten dieser wird in ein Unterverzeichnis mit dem Namen Journal in das
Programmverzeichnis geschrieben, möchte man diese Funktion nutzen so ist es notwendig
zu prüfen ob dieses vorhanden ist.
Beispiel Initialisierung:
_fiscalConnect = new InsikaServer();
if(_fiscalConnect.SCardConnect())
{
_fiscalConnect.SmartCardInitialization();
var xmlFileNameL = DateTime.Now.ToString(„yyMMdd“) + „XMLExpBak“;
var xmlFileNameS = xmlFileNameL;
var dateien = System.IO.Directory.GetFiles(„Journal“);
var fileNoL = dateien.Count(s =>
xmlFileNameL == System.IO.Path.GetFileName(s).Substring(0, 15) &&
System.IO.Path.GetFileName(s)[17] == ‚L‘);
xmlFileNameL += $“{fileNoL + 1,0:D2}L.xml“;
xmlFileNameS += $“{fileNoL + 1,0:D2}S.xml“;
xmlFileNameL = xmlFileNameL.Insert(0, „.\\Journal“ + System.IO.Path.DirectorySeparatorChar);
xmlFileNameS = xmlFileNameS.Insert(0, „.\\Journal“ + System.IO.Path.DirectorySeparatorChar);
_fiscalConnect.XmlFileName = xmlFileNameL;
_fiscalConnect.XmlFileName64 = xmlFileNameS;
_fiscalConnect.CardInserted += FiscalCard_Inserted;
_fiscalConnect.CardRemoved += FiscalCard_Removed;
}
In den letzten Zeilen werden zusätzlich auch Events welche beim entnehmen sowie
einstecken einer Karte von Kartenleser ausgegeben werden registriert.
Zum Ausführen einer Transaktion werden bei der InsikaServer Klasse die nötigen Parameter
gesetzt in welchem festgelegt wird ob es sich hierbei um einen Training oder Liefer -Beleg
handelt, von wem dieser angefordert wird als auch die zu verrechnenden Artikel.
Beispiel:
_fiscalConnect.TrainingMode = (bool)transactionRequest.TrainingMode;
_fiscalConnect.DeliveryMode = (bool)transactionRequest.DeliveryNote;
_fiscalConnect.InsikaOperator =
(string)transactionRequest.InsikaOperator;
_fiscalConnect.HashItems =
transactionRequest.GoodsHashItemsSelected.ToArray();
if (!_fiscalConnect.Transaction())
{
return _fiscalConnect.ExceptionMessage;
}
Das Objekt unter dem Namen “InsikaHashItem” enthällt Informationen zu
einem Artikel aus dem “Warenkorb” und sieht folgendermaßen aus:
public class InsikaHashItem
{
public float QuantityOrNumber { get; set; } = 1;
public string QuantityUnit { get; set; } = null;
public string CommercialDesignation { get; set; }
public bool DiscountOrSurcharge { get; set; } = false;
public bool Voucher { get; set; } = false;
public bool ThirdParty { get; set; } = false;
public bool DeliveryNote { get; set; } = false;
public long[] Prices { get; set; } = new long[6];
public InsikaHashItem()
{
for (var i = 0; i < Prices.Length; i++) { Prices[i] = 0; } } public long Sum => Prices.Sum();
}
Beim Feld “Prices” handelt es sich um eine Auflistung der
unterschiedlichen Mehrwertsteuern und die dazugehörige Summe in Cents
Zum Beispiel handelt es sich bei Prices[0] um den mit 19% zu besteuernden
Betrag und bei Prices[1] um den mit 7%.
// 0 – Normalsatz: 19%
// 1 – Ermäßigter Satz: 7%
// 2 – Nicht vorhanden
// 3 – Umsatzsteuerfrei 0 %
// 4 – Durchschnittssatz 1: 10,7%
// 5 – Durchschnittssatz 2: 5,5%
Nach dem Ausführen der Transaktion kann die Zeile aus welcher der QR-Code
Generiert wird über _fiscalConnect.QrBase64String ausgelesen werden.
Weitere Teile der Transaktion zur Speicherung in der Beleg-Datenbank sind
unter folgenden Properties der Insika-Server Klasse verfügbar:
_fiscalConnect.HashCode32Parts5
_fiscalConnect.Signature32Part5,
_fiscalConnect.TransactionDate
_fiscalConnect.TransactionTime
_fiscalConnect.InsikaOperator,
_fiscalConnect.TaxPayerId,
_fiscalConnect.TaxPayerIdCurrentNumber,
_fiscalConnect.BookingSeqenceNumber
Nutzerdaten wie die Steuerzahler Id werden bei Bestellung der Smartcard
von der Bundesdruckerei in der Karte eingetragen, die Sequenznummer ist
eine fortlaufende Nummer die NICHT zurückgesetzt werden kann.
Beim ausschreiben des nächsten Beleges werden die auslesbaren daten mit
den Werten der nächsten Rechnung überschrieben
Zusätzlich lassen sich Informationen zur Smartcard nach ihrer
Initialisierung einsehen. In unserer eigenen Software wird hierfür ein
Objekt mit dem Namen “TIMStatusResponseObject” generiert und sieht
folgendermaßen aus:
var status = new TIMStatusResponseObject
{
CardReaderName = _fiscalConnect.SCardReaderName,
VersionCardOS = _fiscalConnect.VersionCardOs,
VersionCard = _fiscalConnect.VersionCard,
LifeCycle = _fiscalConnect.LifeCycle,
Version = _fiscalConnect.TimVersion,
TaxPayerID = _fiscalConnect.TaxPayerId,
TaxPayerIDCurrentNummer = _fiscalConnect.TaxPayerIdCurrentNumber,
SerialNumber = _fiscalConnect.SerialNumber,
CurrencyCode = _fiscalConnect.CurrencyCode,
LastMonth = _fiscalConnect.LastMonth,
BookingSequenceNummer = _fiscalConnect.BookingSeqenceNumber,
EndOfDaySequenceNummer = _fiscalConnect.EndOfDaySeqeneceNumber,
CountryCode = _fiscalConnect.CountryCode,
HashLength = _fiscalConnect.HashLength,
CryptographicAlgorithm0 = _fiscalConnect.CryptographicAlgorythm[0],
CryptographicAlgorithm1 = _fiscalConnect.CryptographicAlgorythm[1],
CryptographicAlgorithm2 = _fiscalConnect.CryptographicAlgorythm[2]
};
Hierbei handelt es sich um ein Beispiel einer Klasse wie sie in unserem
REST basierten Client-Server Kassensystem genutzt wird.
Zusammenfassend:
1. Wird eine laufende Instanz der “InsikaServer” Klasse benötigt welche
2. Die bereits von der Druckerei gebrandete Karte auslesen und
beschreiben kann.
3. Wird der Klasse bei jeder Transaktion die Parameter der Zahlung neu
gesetzt und die Preise der waren nach Steuerklasse sortiert in
Centbeträgen übergeben.
4. Können nach erfolgreicher Transaktion die Ergebnisse dieser
jederzeit bis zum ausführen der nächsten Transaktion aus der Klasse
ausgelesen werden.
Im jedem Fall wird für die Nutzung der API ein Windows oder Linux
basiertes System (auch mit ARM Prozessoren) benötigt das in der Lage ist
zumindest Mono 5.2.0 auszuführen.
Unsere eigenen Tests zeigen dass hierfür sogar ein Monocore/ARM system wie
es in manchen heim NAS Geräten genutzt wird ausreicht solange die nötige
Laufzeitumgebung für dieses System kompilierbar ist.
Um eine vollständig lauffähige Demonstration des Systems zu erhalten kann
eine beliebige Version(S,M,L, Handel2) unseres Kassensystems installiert
werden, der integrierte REST Server wird im Programmverzeichnis abgelegt
und kann über die dabei BlitzkasseNetOrder.exe gestartet werden,
alternativ wird dieser automatisch beim Starten der Kasse im Einzelplatzbetrieb ausgeführt.
Danach ist die Kassen Konfiguration im Webbrowser unter
http://localhost:8001 verfügbar.
Nach dem Einstellen der Kasse kann ein neu laden der Insika Konfiguration
unter http://localhost:8001/TimStatus erreicht werden(GET), zudem liefert
das auch den derzeitigen zustand der Smartcard.
Unter http://localhost:8001/FiscalTransaktion kann das oben genannte
TransactionRequestObject as JSON gepostet (POST) werden und als Antwort
wird ein TransactionResponseObject zurueck gegeben(JSON).
De -serialisiert sieht das Objekt folgendermaßen aus:
public class TransactionResponseObject
{
public string ErrorMessage { get; set; }
public string QrBase64String { get; set; }
public ReceiptContainer[] BonContainers { get; set; }
public string HashCode32Parts5 { get; set; }
public string Signatur32Parts5 { get; set; }
public string SransactionDate { get; set; }
public string TransactionTime { get; set; }
public string InsikaOperator { get; set; }
public string TaxPayerID { get; set; }
public uint TaxPayerIDCurrentNummer { get; set; }
public uint BookingSequenceNummer { get; set; }
}
Die “ErrorMessage” ist bei einer erfolgreichen Transaktion leer,
Die ReceiptContainer enthalten informationen zur verbuchten Steuer jeder
versendeten Ware:
public class ReceiptContainer
{
public double TaxPercentage { get; set; } = 0;
public double Gross { get; set; } = 0;
public double Net { get; set; } = 0;
public double TaxValue { get; set; } = 0;
}
Weitere Information finden Sie auf der Homepage des Finanzamt:
https://www.bsi.bund.de/DE/Themen/DigitaleGesellschaft/Grundaufzeichnungen/FAQ/faq_node.html