FORMAT: 1A
HOST: http://pos.dev.qnips.com/api
# Qnips POS API
# Mobile Payment
In der Qnips App sind mehrere Zahlungsdienste eingebunden, über welche eine bargeldlose Bezahlung über das Smartphone möglich ist. Dabei ist Qnips selbst kein Zahlungsdienstleister, sondern nur ein Mediator mit einer
einheitlichen Schnittstelle zum Abwickeln einer mobilen Zahlung.
Um eine mobile Zahlung anzustoßen, muss die Kasse einen Payment Identifier (PID) generieren und einen Zahlungswunsch inkl. Währung + Betrag unter Nutzung dieser PID beim Qnips System einreichen. Weiterhin ist der PID
als Trigger für den Start des Bezahlprozesses in der Qnips App (z.B. als QrCode, NFC- oder BLE-Signal) auszugeben. Sobald die App den PID erkennt, wird der Bezahlprozess gestartet. Jede Zustandsänderung des
Zahlungswunsches wird an die Kasse zurückgegeben.
Zur Zeit eingebundene Zahlungsdienstleister sind:
Anbieter | Zahlart | Rückerstattung
---|---|---
**kesh** | Prepaid | nein
**PayPal** | Postpaid | nein
weitere werden folgen.
blabla
## Begrifflichkeiten
### Zahlungswunsch (Payment)
Um eine mobile Zahlung über das Smartphone zu initiieren, muss die Kasse einen Zahlungswunsch über die Qnips-API in unserem System unter Nutzung eines eindeutigen Payment Identifiers (PID) einreichen.
Sobald die Qnips-App den PID erkennt (z.B. über einen QrCode-Scan oder über ein BLE-Signal), startet sie die Bezahlfunktion auf dem Smartphone.
Ein Zahlungswunsch besteht aus folgenden Angaben:
Name | Typ | Bedeutung
---|---|---
**qtid**|*string*|Der Identifier der Transaktion auf welche sich dieser Zahlungswunsch bezieht
**currency**|*string*|Währungskennung laut [ISO 4217-Spezifikation](http://de.wikipedia.org/wiki/ISO_4217) (z.B. "EUR")
**total_value**|*decimal*|Gesamtbetrag, der vom Qnips-Nutzer einzuziehen ist inkl. eventueller Trinkgelder und aller Steuer
**included_vat**|*decimal*|Mehrwertsteuer-Anteil im Gesamtbetrag
**included_tip**|*decimal, optional*|Eventuell in der Kasse eingegebenes Trinkgeldanteil im Gesamtbetrag
**allowed_payment_providers**|*string, optional*|Die Qnips App listet in der Bezahlansicht standardmäßig alle in der aktuellen Filiale eingerichteten Zahlungswege auf. Möchte die Kasse bei bestimmten Nutzern bestimmte Zahlungswege sperren, so isthier eine kommaseparierte Liste der IDs der Zahlungsproviders anzugeben, die für diesen einen Zahlungswunsch erlaubt sein sollen
### Payment Identifier (PID)
Darunter ist eine von der Kassensoftware erzeugte ID gemeint, unter welcher der Zahlungswunsch im Qnips-Backend eingereicht und getrackt wird. Der PID kann nach beliebigem Algorithmus erzeugt werden und
muss lediglich folgenden Anforderungen entsprechen:
* kann nur aus Nummern und lateinischen Groß- und Kleinbuchstaben bestehen (keine Umlaute, keine Sonderzeichen)
* darf minimal 5 und maximal 20 Zeichen lang sein
* muss über die gesamte Einsatzzeit einer Kasse unter demselben QnipsPOSIdentifier eindeutig sein.
### Qnips Transaction Identifier (QTID)
Was der PID für den Zahlungswunsch ist, ist der QTID für die Transaktion (siehe dazu Kapitel 'referenz setzen'). Damit Qnips im Webportal den Zahlungsvorgang mit einer Transaktion verlinkt anzeigen kann, muss
ein Zahlungswunsch mit dem Transaktionsdatensatz über das Setzen des QTID-Feldes auf dem Zahlungswunsch verbunden werden.
### Zustände des Zahlungswunsches (Payment.State)
Name | Bedeutung
--- | ---
`Submitted` | Zahlungswunsch ist im Qnips-System erfasst und wartet darauf, auf dem Smartphone gestartet zu werden. Ausschließlich Bezahlvorgänge in diesem Zustand können noch vom Submitter zurückgezogen werden
`InProcess` | Sobald der User in der Qnips-App den Zahlungsdienstleister ausgewählt hat, sich ihm gegenüber authentifiziert hat und die App bereit ist, den Zahlungswunsch an den Zahlungsdienstleister zu übergeben, wird der Zahlungswunsch auf den Zustand 'InPayment' gesetzt und kann von der Kasse nicht mehr abgebrochen werden
`CancelledByUser` | Wird gesetzt, wenn der Zahlungswunsch vom Nutzer in der Qnips-App vollständig abgebrochen wurde. Die Qnips-App kann diesen Zahlungswunsch allerdings wiederaufnehmen (z.B. durch erneuten Scan des QrCodes mit dem selben PID), solange der Zahlungswunsch nicht vom Submitter beendet wird oder in den Zustand `Expired` wechselt.
`CancelledBySubmitter` | Wird gesetzt, wenn der Erzeuger (Submitter) des Zahlungswunsches diesen über einen DELETE-Call auf die payments-Resource explizit abbricht. Das geht nur solange der Zahlungswunsch im Zustand `Submitted` ist. Zahlungswünsch mit diesem Zustand können keine Bezahlfunktion in der Qnips-App mehr auslösen.
`Succeeded` | Wird gesetzt, sobald der gewählte Zahlungsdienstleister uns einen erfolgreichen Geldtransfer meldet
`Refunded` | Wird gesetzt, wenn der Erzeuger (Submitter) des Zahlungswunsches über einen expliziten POST-Call auf die Refund-Resource eine Rückerstattung beantragt und diese uns vom Zahlungsdienstleister als erfolgt gemeldet wird
`Expired` | Jeder in unserem System erzeugte Zahlungswunsch, der nach Ablauf von 30 Minuten immer noch den Zustand `Submitted` hat, wird automatisch auf den Zustand `Expired` gesetzt und gilt ab da für die Qnips-App als nicht existent. Eine Wiederaufnahme des zuvor vom User abgebrochenen Zahlungswunsches verlängert diesen Timeout **nicht**
### PaymentProviderTransactionId
Qnips selbst ist kein Zahlungsdienstleister, sondern eine Wallet, die unterschiedliche Zahlungsdienstleister (wie PayPal, kesh, etc.) in einer App vereint. Die eigentliche Zahlung wird also von nachgeschalteten Providern
abgewickelt. Daher bekommt jeder Zahlungswunsch nach einem erfolgreichen Geldtransfer durch den vom Qnips-App-Nutzer gewählten Provider, eine Provider-spezifische TransaktionsID, welche wir zur besseren
Nachvollziehbarkeit an den Erzeuger des Zahlungswunsches (i.d.R. die Kassensoftware) als PaymentProviderTransactionId weiterreichen.
### Discounts
Eine über die Qnips-API initiierte Zahlung kann optional automatisch um das für die verknüpfte Transaktion evtl. errechnete Qnips-Cashback reduziert werden.
Ist die Funktion vom Kunden gewünscht, wird Qnips den Zahlbetrag eines mobilen Zahlungswunsches ggf. automatisch um das für die mit dem Zahlungswunsch verknüpfte Transaktion errechnete Cashback reduzieren und den reduzierten
Zahlbetrag über den Payment Provider abwickeln. Als Nachweis gegenüber dem Finanzamt für die Korrektheit des Preisnachlasses wird in dem Feld **Discount** die Information über das angefallene Cashback abgespeichert und
auf Anfrage an die Kassensoftware ausgeliefert. Die Kasse ist dann in der Pflicht, diesen Datensatz gemäß eigener Richtlinien für angewandte Preisnachlässe als Bestandteil der Transaktion abzuspeichern.
## Erzeugung des Zahlungswunsches
1. Generieren Sie einen PaymentIdentifier (PID) , der den oben beschriebenen Kriterien entspricht und reichen Sie den Zahlungswunsch unter Nutzung dieser PID mit mindestens dem *QTID*, dem *Betrag*, der *Währung* und
der *PaymentTerminalId* mit einem POST-Call auf die payments-Resource bei uns ein.
2. Beachten Sie bitte, dass zu diesem Zeitpunkt der Transaktionsdatensatz, auf den sich der aktuelle Zahlungswunsch bezieht, schon bei uns im System hinterlegt sein sollte
3. Damit ein QR-Code als Trigger für die Bezahlfunktion dienen kann, muss der PID eines Zahlungswunsches in den QR-Code gepackt werden. Erzeugen Sie dazu einen QrCode mit folgendem Inhalt: **http:// app.qnips.com/tt/{TransactionSubmitterId}/{QTID}{PZ1}/{PID}{PZ2}**, wobei:
Name | Bedeutung
---|---
TransactionSubmitterId | der Identifier, den die Kasse bei der Aktivierung am Qnips-Backend zugewiesen bekommen hat
QTID | Qnips Transaction Identifier mit dem der Transaktionsdatensatz eingereicht wurde
PZ1 | Prüfsumme für QTID, deren Berechnungslogik in [Prüfzifferberechnung](#cscalc) beschrieben ist
PID | Payment Identifer
PZ2 | Prüfsumme für PID, deren Berechnungslogik in [Prüfzifferberechnung](#cscalc) beschrieben ist
## Abbruch des Zahlungswunsches
1. Ein Zahlungswunsch kann durch die Kasse solange zurückgenommen werden, bis die Qnips App eine nicht mehr terminierbare Zahlungsanfrage an den vom Nutzer in der App ausgewählten Payment Provider übermittelt wurde.
Um einen Zahlungswunsch durch die Kasse zurückzunehmen, führen Sie einen DELETE-Call auf die payments-Resource aus.
2. Werten Sie hiernach unbedingt den Response aus, denn dieser enthält die Information, ob dem Abbruchwunsch entsprochen werden konnte, oder nicht, weil z.B. eine Zahlung gerade im Gange oder bereits erfolgt ist.
## Zustandsabfrage zum Zahlungswunsch
Nach der Übermittlung des Zahlungswunsches muss die Kasse für jeden Zahlungswunsch eine Zustandsüberwachung implementieren, bis eines der folgenden Zustände erreicht worden ist:
* Confirmed - Geldtransfer hat stattgefunden
* Expired - Zahlungswunsch ist abgelaufen und wird von der Qnips App nie mehr verarbeitet werden
* CancelledByUser oder CancelledBySubmitter - Zahlungswunsch wurde abgebrochen.
Liefert ein Payment Provider für eine Bezahlanweisung eine Mißerfolgsmeldung (z.B. "Konto nicht gedeckt" o.ä.), reicht Qnips solche Zwischenzustände bewusst nicht an die Kasse weiter.
Statt dessen wird dem Nutzer in der Qnips App die Möglichkeit gegeben, die Bezahlung erneut, ggf. über einen anderen Zahlungsdienst zu veranlassen bis die Zahlung entweder erfolgreich durchläuft oder der Nutzer
den Bezahlprozess aktiv abbricht.
Für die Zustandsüberwachung existieren grundsätzlich zwei Möglichkeiten:
1. Eine Pull-Abfrage für einen bestimmten PID oder für eine Liste von PIDs (siehe dazu den GET-Call auf die paymentstates-Resource)
2. Eine direkte Push-Notification über einen WebSocket. Siehe dazu Kapitel [Qnips-Websocket](#websocket). In diesem Fall wird Qnips bei jedem Zustandswechsel eines PIDs eine direkte Benachrichtigung an die entsprechenden
Subscriber versenden, die in der Kasse nach Möglichkeit asynchron verarbeitet werden sollen.
> Generell empfehlen wir für den Empfang zwei Wege zu implementieren:
> + Eine permanente Verbindung mit dem Websocket aufbauen, um asynchron auf Zahlungsbestätigungen zu warten und beim ankommen der Bestätigung eine visuell sichtbare Meldung über den Zahlungserfolg an den Kellner zu erzeugen.
> + Zusätzlich in der Kassensoftware einen Button oder Menüeintrag einbauen, mit dem über einen GET-Call aktiv der Zustand einer Zahlungsanforderung im Qnips System abgefragt werden kann.
Beiden Wegen ist es jedoch gemein, dass die Zustände der Zahlungswünsche in einem einheitlichen Format geliefert werden, nämlich folgendem:
Name | Typ | Bedeutung
---|---|---
**payment_terminal_id**|*string*|Sind in einer Filiale mehrere Plätze installiert, die mit dem selben QnipsPOSIdentifier arbeiten und über die eine Zahlung veranlasst werden kann (z.B. in einem Client-Server-Verbund), so muss für einen Zahlungswunsch ein Identifier des genauen Platzes angegeben werden, der den Zahlungswunsch angelegt hat. Dadurch kann sichergestellt werden, dass jede Zustandsmeldung zum Zahlungswunsch genau dem Platz zugeordnet werden kann, an dem der Zahlungswunsch erzeugt wurde
**currency**|*string*|Währungskennung laut [ISO 4217-Spezifikation](http://de.wikipedia.org/wiki/ISO_4217) (z.B. "EUR")
**total_value**|*decimal*|Gesamtbetrag, der vom Qnips-Nutzer einzuziehen ist bzw. eingezogen wurde inkl. eventueller Trinkgelder und aller Steuer. ACHTUNG: Der Betrag kann nach erfolgter Zahlung größer ausfallen, als der von der Kasse eingereichte Wert, da hier u.U. ein vom Qnips App Nutzer bestimmtes Trinkgeld hinzukommen kann
**included_vat**|*decimal*|Mehrwertsteuer-Anteil im Gesamtbetrag
**included_tip**|*decimal, optional*|Eventuell in der Kasse eingegebenes Trinkgeldanteil im Gesamtbetrag. Ist das Trinkgeld nicht durch die Kasse angegeben, kann der Qnips Nutzer u.U. eigenes Trinkgeld in der Qnips App hinzunehmen. Daher kann der Wert hier nach erfolgter Zahlung ggf. von dem Wert abweichen, der in diesem Feld bei der Erstellung eines Zahlungswunsches angegeben wurde.
**qtid**|*string*|Der Identifier der Transaktion auf welche sich dieser Zahlungswunsch bezieht
**state**|*string*|Einer der unter [Zustände des Zahlungswunsches](#paymentstate) beschriebenen Zustände
**is_refundable**|*boolean*|**Nur gesetzt wenn state = Succeeded oder Refunded.** Gibt an, ob der Betrag nach erfolgter Zahlung über den verwendeten Zahlungsdienstleisters elektronisch zurückerstattbar ist. Dies ist nicht bei allen Zahlungsdienstleistern der Fall
**pp_id**|*number*|**Nur gesetzt wenn state = Succeeded oder Refunded.** Feste, von Qnips vergebene Id eines Zahlungsdienstleisters (oder kurz pp für payment provider). Mögliche Werte sind: 1=PayPal, 2=kesh.
**pp_transaction_id**|*string*|**Nur gesetzt wenn state = Succeeded oder Refunded.** Das ist die ID, unter welcher der Zahlungsvorgang im System des gewählten Zahlungsdienstleisters geführt wird.
**discount**|*object*| **Nur gesetzt wenn state = Succeeded oder Refunded.** Ist vom Kunden eine direkte Verrechnung eventueller Cashbacks mit dem Zahlbetrag gewünscht, wird hier der Discount-Betrag und der Mehrwertsteueranteil darin ausgewiesen sofern die mit diesem Zahlungswunsch verknüpfte Transaktion Cashbacks erzeugt hat.
## Rücküberweisung
Bei einer Rücküberweisung wird das Geld, das im Kontext einer mobilen Zahlung über das Qnips System auf das Empfängerkonto transferiert wurde, wieder vom Empfängerkonto abgebucht und auf das Konto des ursprünglichen Zahlers überwiesen.
Damit reduziert der Zahlungsdienstleister für sich die Betrungsmöglichkeiten und kann i.d.R. somit günstigere Transaktionspreise anbieten.
Leider wird diese Möglichkeit nicht von jedem Zahlungsdienstleister unterstützt. Daher wird Qnips bei der Meldung einer erfolgreichen Zahlung an die Kasse immer auch die Angabe im Feld "IsRefundable" liefern, ob für diese Zahlung eine
elektronische Rücküberweisung möglich ist. Speichern Sie daher bitte bei jeder ankommenden Zahlungsbestätigung diese Information und bieten Sie die Rückerstattung auf dem User Interface nur für solche Zahlungen an, bei welchen IsRefundable = true ist.
Um eine Rücküberweisung zu veranlassen, führen Sie bitte einen POST-Call auf die refunds-resource aus.
# Qnips-Websocket
Die von uns empfohlene Variante zum Empfang der Zahlungsbestätigungen ist über einen Websocket.
> „Das WebSocket-Protokoll ist ein auf TCP basierendes Netzwerk¬protokoll, das entworfen wurde, um eine bidirektionale Verbindung zwischen einer (Web-) Anwendung und einem WebSocket-Server bzw. einem Web-Server,
der auch WebSockets unterstützt, herzustellen.“ - Zitat Wikipedia (http://de.wikipedia.org/wiki/WebSocket).
Ein weiterer Vorteil eines Websockets ist, dass es, obwohl das Protokoll noch sehr jung ist, eine vielzahl der Client-Libs für unterschiedlichste Programmierplattformen und Programmiersprachen gibt. Hier eine kleine Übersicht:
+ .NET (2.0, 3.5, 4.0, Mono, Silverlight, WindowsPhone): *http://websocket4net.codeplex.com/*
+ Javascript (WebSocket-Klasse in den Browser-Engines): siehe Unterkapitel “Browser-Implementierungen” unter *http://de.wikipedia.org/wiki/WebSocket*
+ Delphi (basierend auf Indy 10): *http://websockets.esegece.com*
+ C (Windows, Linux) *http://www.zaphoyd.com/websocketpp/* *http://www.aspl.es/nopoll/*
Unser Websocket funktioniert nach dem Publish/Subscribe-Prinzip. D.h. es bietet mehrere Kanäle an, auf denen Informationen zum Client gepusht werden sollen. Hier ist ausschließlich der Kanal „payment“ interessant.
Das Websocket liegt auf **„wss://pos.dev.qnips.com/qnipsws“**. Nachfolgend ein einfaches Beispiel in Javascript, welches eine Subscription auf dem Payment-Kanal eingeht und auf Zahlungsbestätigungen reagiert.
```javascript
qnipsWebsocket = function () {
var ws = new WebSocket('wss://pos.dev.qnips.com/qnipsws');
ws.onopen = function () {
var qpIdent = "abc";
wsPayments.send('{"subscribe":"payment", "qnipsposidentifier":"' + qpIdent + '"}');
};
// success
ws.onmessage = function (evt) {
console.log(evt.data);
};
// error
ws.onerror = function (evt) {
console.log(evt.message);
};
// close
ws.onclose = function () {
console.log('disconnected');
// try to reconnect each 30 seconds, until connection is established
};
};
```
Der Parameter ‚evt‘ der ‚onmessage‘-Funktion ist dann wie folgt aufgebaut:
```javascript
{
„channel“:“payment“,
„data“:{
"payment_terminal_id":"1",
"currency": "EUR",
"total_value": 19.95,
"included_tip": 1.99,
"included_vat": 3.81,
"qtid":"af63457485af8745655cd",
"state":"1,2,3",
"is_refundable":"1,2,3",
"pp_id":1,
"pp_transaction_id":"1f7685qwef765",
"discount":{
"total_discount_value": 1.19,
"included_vat": 0.19,
}
}
}
```
# Prüfsummenberechnung
Da bei Calls der Qnips-WebAPI-Resourcen die Parameter im Klartext übertragen werden, können auch bei hinreichender SSL-Verschlüsselung die Man-in-the-Middle-Angriffe nicht vollständig ausgeschlossen werden.
Daher wird Qnips die Übertragung von sicherheitsrelevanten Parametern über eine Prüfsumme schützen, die unter Nutzung eines je Kassenplatz individuellen Geheimschlüssels auf der Kasse berechnet und im
Qnips-Backend validiert wird.
Alle API-Calls mit mind. einer falsch angegebenen Prüfsumme werden abgewiesen.
Nun das Verfahren für die Bildung der Prüfsumme:
* einen String mit `Identifier` + `„qPnsS14` + `CSSecret` bilden, mit:
Name | Wert
---|---
`Identifier`| der Wert, für den die Prüfsumme berechnet werden soll, z.B. ein QnipsTransactionIdentifier (QTID) oder ein PaymentIdentifier (PID)
`„qPnsS14"` | ein konstanter String
`CSSecret` | der geheime Schlüssel, der je Kasse unterschiedlich ist
Beispiel: Identifier=“123456“ und CSSecret=“af87b1“ ergeben `„123456qPnsS14af87b1“`
2. Für das Ergebnis aus vorherigem Schritt einen MD5-Hash bilden.
Für den Wert aus dem oben gezeigten Beispiel („123456qPnsS14af87b1“), würde der MD5-Hash folgender sein: `1283ff82ae8e9ace636449a519d99fa9`.
Die ersten 6 Zeichen dieses Hash-Wertes bilden die Prüfsumme.
Für den bisherigen Beispiel wäre die Prüfsumme aslo **`1283ff`**
# Group Mobile Payment
Nachfolgend sind alle relevanten Resourcen rund um das Thema 'Mobile Payment mit Qnips' zusammengetragen
## Payments [/payments/{pid_pz}]
Ein Payment ist ein Zahlungswunsch und besteht aus folgenden Angaben:
Name | Typ | Bedeutung
---|---|---
**payment_terminal_id**|*string*|Sind in einer Filiale mehrere Plätze installiert, die mit dem selben QnipsPOSIdentifier arbeiten und über die eine Zahlung veranlasst werden kann (z.B. in einem Client-Server-Verbund), so muss für einen Zahlungswunsch ein Identifier des genauen Platzes angegeben werden, der den Zahlungswunsch angelegt hat. Dadurch kann sichergestellt werden, dass jede Zustandsmeldung zum Zahlungswunsch genau dem Platz zugeordnet werden kann, an dem der Zahlungswunsch erzeugt wurde
**currency**|*string*|Währungskennung laut [ISO 4217-Spezifikation](http://de.wikipedia.org/wiki/ISO_4217) (z.B. "EUR")
**total_value**|*decimal*|Gesamtbetrag, der vom Qnips-Nutzer einzuziehen ist inkl. eventueller Trinkgelder und aller Steuer
**included_vat**|*decimal*|Mehrwertsteuer-Anteil im Gesamtbetrag
**included_tip**|*decimal, optional*|Eventuell in der Kasse eingegebenes Trinkgeldanteil im Gesamtbetrag
**qtid**|*string*|Der Identifier der Transaktion auf welche sich dieser Zahlungswunsch bezieht
**allowed_payment_providers**|*string, optional*|Die Qnips App listet in der Bezahlansicht standardmäßig alle in der aktuellen Filiale eingerichteten Zahlungswege auf. Möchte die Kasse bei bestimmten Nutzern bestimmte Zahlungswege sperren, so isthier eine kommaseparierte Liste der IDs der Zahlungsproviders anzugeben, die für diesen einen Zahlungswunsch erlaubt sein sollen
Folgende Aktionen stehen für diese Resource zur Verfügung:
+ Model (application/json)
+ Headers
DevKey: {Ihr DeveloperKey}
SubmitterId: {transactionSubmitterId} welchen die Kasse bei der Aktivierung zugewiesen bekommen hat
+ Body
{
"payment_terminal_id":"1",
"currency": "EUR",
"total_value": 19.95,
"included_tip": 1.99,
"included_vat": 3.81,
"qtid":"af63457485af8745655cd",
"allowed_payment_providers":"1,2,3"
}
### POST: Zahlungswunsch erstellen [POST]
* Wurden im Qnips Dashboard-Portal noch keine Empfängerkontendaten für mindestens einen der im Qnips-System eingebundenen Zahlungsdienstleister hinterlegt, wird die Erstellung eines Zahlungswunsches mit
HTTP-PreconditionFailed (Error Code 412) verweigert
* Ein Zahlungswunsch kann für die selbe PID nur einmal erstellt werden
* Jeder weitere Versuch, einen POST-Call mit der selben PID auszuführen, wird mit 412 abgewiesen
* Sollte die Kasse einen Parameter eines Zahlungswunsches (z.B. total_value) aktualisieren wollen bzw. müssen, so ist der vorherige Zahlungswunsch zurückzuziehen (siehe DELETE auf payments), ein neuer Zahlungswunsch
mit neuer PID zu erstellen und ein neuer QRCode zu drucken, da der alte hinsichtlich der Bezahlfunktion durch den DELETE Call implizit unwirksam gemacht wurde.
+ Request (application/json)
[Payments][]
+ Parameters
+ pid_pz (string) ... ein String, der aus dem PID und seiner Prüfsumme besteht (siehe dazu das Kapitel [Prüfsummenberechnung](#checksum).
+ Response 200
// In diesem Fall ist der Zahlungswunsch korrekt angelegt.
// Sobald die Qnips App die PID erkennt, wird der Bezahlprozess auf dem Smartphone gestartet.
// Der Responsebody bleibt leer.
+ Response 412
// HTTP-Error 412 = PreconditionFailed
{
"reason_id":1,
"reason_text":"further error details as text"
}
// Hier die möglichen Gründe:
// 1 | Prüfsumme ist falsch
// 2 | PID wurde bereits verwendet
// 3 | In aktueller Filiale wurden keine Zahlungsempfängerdaten für mobile Zahlung hinterlegt
// 99 | Sonstiges (in diesem Fall wird das Feld reason_text genauere Angaben enthalten.
### DELETE: Zahlungswunsch zurückziehen [DELETE]
* Ein Zahlungswunsch kann ausschließlich dann zurückgezogen werden, wenn sein Zustand im Qnips System den Wert 'Submitted' hat.
* Wenn Sie mit dem Qnips-Websocket als Rückkanal arbeiten, über welchen die Kasse jede Zustandsänderung nahezu in Echtzeit mitbekommt, empfiehlt es sich, vor dem Zurückziehen des Zahlungswunsches, seinen Zustand aus dem lokalen Datenbestand abzufragen und die Zurückziehung nur dann zu veranlassen, wenn der State = Submitted ist
* Wenn Sie die Zustände der Zahlungswünsche über einen Polling-Mechanismus abfragen, empfiehlt es sich vor dem Zurückziehen des Zahlungswunsches zunächst seinen aktuellen Zustand einzuholen und nur wenn auch dann der Zustand = Submitted ist, einen Rückzug des Zahlungswunsches zu veranlassen.
+ Parameters
+ pid_pz (string) ... ein String, der aus dem PID und seiner Prüfsumme besteht (siehe dazu das Kapitel [Prüfsummenberechnung](#checksum).
+ Response 200
// In diesem Fall ist der Zahlungswunsch korrekt zurückgezogen.
// Die damit verlinkte PID verliert ihre Funktion als Trigger der Bezahlfunktion
// in der Qnips-App. Der Responsebody bleibt leer.
+ Response 412
// HTTP-Error 412 = PreconditionFailed
{
"reason_id":2,
"reason_text":"further error details as text"
}
// Hier die möglichen Gründe:
// 1 | Prüfsumme ist falsch
// 2 | PID nicht gefunden
// 3 | externer Zahlungsdienstleister wurde mit der Zahlung beauftragt
// 4 | Geldtransfer hat schon stattgefunden
// 99 | Sonstiges (in diesem Fall wird das Feld reason_text genauere Angaben enthalten.
## PaymentStates [/paymentstates?pids={pids}]
Ein paymentstate ist ein Objekt mit Detailinformationen zum aktuellen Zustand eines vorher über den POST-Call auf payments erstellten Zahlungswunsches und besteht aus folgenden Parametern:
Name | Typ | Bedeutung
---|---|---
**payment_terminal_id**|*string*|Sind in einer Filiale mehrere Plätze installiert, die mit dem selben QnipsPOSIdentifier arbeiten und über die eine Zahlung veranlasst werden kann (z.B. in einem Client-Server-Verbund), so muss für einen Zahlungswunsch ein Identifier des genauen Platzes angegeben werden, der den Zahlungswunsch angelegt hat. Dadurch kann sichergestellt werden, dass jede Zustandsmeldung zum Zahlungswunsch genau dem Platz zugeordnet werden kann, an dem der Zahlungswunsch erzeugt wurde
**currency**|*string*|Währungskennung laut [ISO 4217-Spezifikation](http://de.wikipedia.org/wiki/ISO_4217) (z.B. "EUR")
**total_value**|*decimal*|Gesamtbetrag, der vom Qnips-Nutzer einzuziehen ist bzw. eingezogen wurde inkl. eventueller Trinkgelder und aller Steuer. ACHTUNG: Der Betrag kann nach erfolgter Zahlung größer ausfallen, als der von der Kasse eingereichte Wert, da hier u.U. ein vom Qnips App Nutzer bestimmtes Trinkgeld hinzukommen kann
**included_vat**|*decimal*|Mehrwertsteuer-Anteil im Gesamtbetrag
**included_tip**|*decimal, optional*|Eventuell in der Kasse eingegebenes Trinkgeldanteil im Gesamtbetrag. Ist das Trinkgeld nicht durch die Kasse angegeben, kann der Qnips Nutzer u.U. eigenes Trinkgeld in der Qnips App hinzunehmen. Daher kann der Wert hier nach erfolgter Zahlung ggf. von dem Wert abweichen, der in diesem Feld bei der Erstellung eines Zahlungswunsches angegeben wurde.
**qtid**|*string*|Der Identifier der Transaktion auf welche sich dieser Zahlungswunsch bezieht
**state**|*string*|Einer der unter [Zustände des Zahlungswunsches](#paymentstate) beschriebenen Zustände
**is_refundable**|*boolean*|**Nur gesetzt wenn state = Succeeded oder Refunded.** Gibt an, ob der Betrag nach erfolgter Zahlung über den verwendeten Zahlungsdienstleisters elektronisch zurückerstattbar ist. Dies ist nicht bei allen Zahlungsdienstleistern der Fall
**pp_id**|*string*|**Nur gesetzt wenn state = Succeeded oder Refunded.** Feste, von Qnips vergebene Id eines Zahlungsdienstleisters (oder kurz pp für payment provider). Mögliche Werte sind: 1=PayPal, 2=kesh.
**pp_transaction_id**|*string*|**Nur gesetzt wenn state = Succeeded oder Refunded.** Das ist die ID, unter welcher der Zahlungsvorgang im System des gewählten Zahlungsdienstleisters geführt wird.
**discount**|*object*| **Nur gesetzt wenn state = Succeeded oder Refunded.** Ist vom Kunden eine direkte Verrechnung eventueller Cashbacks mit dem Zahlbetrag gewünscht, wird hier der Discount-Betrag und der Mehrwertsteueranteil darin ausgewiesen sofern die mit diesem Zahlungswunsch verknüpfte Transaktion Cashbacks erzeugt hat.
Folgende Aktionen stehen für diese Resource zur Verfügung:
### GET: Status der Zahlungswünsche abfragen [GET]
* Wollen Sie den Status eines einzelnen Zahlungswunsches abfragen, so geben Sie nur seine PID+Prüfsumme im pids-Queryparameter ein. In diesem Fall kann das Backend mit 404 (HTTP-NotFound) antworten, wenn zur gegebenen PID kein Zahlungswunsch gefunden wurde
* Wird eine kommaseparierte Liste der PIDs im Queryparameter angegeben, so werden nicht gefundene PIDs ignoriert und führen nicht zu einem Fehler, sodass theoretisch auch eine leere Liste in der Rückgabe möglich ist, wenn zu keiner der angegebenen PIDs ein Zahlungwunsch gefunden werden konnte
* Ist bei mindestens einem der angegebenen PIDs die Prüfsumme nicht korrekt, so wird der gesamte Request mit einem 412 (PreconditionFailed) abgewiesen.
+ Parameters
+ pids (string) ... ein String mit durch ein Komma separierten PIDs inkl. deren jeweiliger Prüfsumme, z.B. pids=123456,123467,123478 (siehe dazu das Kapitel [Prüfsummenberechnung](#checksum).
+ Request
+ Headers
Accept: application/json oder application/xml
DevKey: {Ihr DeveloperKey}
SubmitterId: {transactionSubmitterId} welchen die Kasse bei der Aktivierung zugewiesen bekommen hat
+ Response 200
[{
"payment_terminal_id":"1",
"currency": "EUR",
"total_value": 19.95,
"included_tip": 1.99,
"included_vat": 3.81,
"qtid":"af63457485af8745655cd",
"state":"1,2,3",
"is_refundable":"1,2,3",
"pp_id":1,
"pp_transaction_id":"1f7685qwef765",
"discount":{
"total_discount_value": 1.19,
"included_vat": 0.19,
}
}]
+ Response 412
// HTTP-Error 412 = PreconditionFailed
{
"reason_id":2,
"reason_text":"further error details as text"
}
// Hier die möglichen Gründe:
// 1 | Prüfsumme bei einem oder mehreren PIDs falsch
// 99 | Sonstiges (in diesem Fall wird das Feld reason_text genauere Angaben enthalten.
## Refunds [/refunds/{pid_pz}?descr={descr}]
Ein Refund ist eine Rückerstattungsanfrage für eine über das Qnips System getätigte mobile Zahlung. Ein Refund ist nur bei bestimmten Zahlungsdienstleistern möglich. Ob eine Rückerstattung für eine erfolgte
mobile Zahlung möglich ist, steht in der Zahlungsbestätigung zur jeweiligen Zahlung im Feld "IsRefundable". Speichern Sie daher bitte bei jeder ankommenden Zahlungsbestätigung diese Information und bieten
Sie die Rückerstattung auf dem User Interface nur für solche Zahlungen, bei welchen IsRefundable = true ist.
Bei einem Refund wird das Geld vom Empfängerkonto wieder abgebucht und auf das Konto des ursprünglichen Zahlers überwiesen.
Eine Refundanfrage ist immer synchron zu verarbeiten (d.h. die Kasse muss den Response abwarten), um ggf. einen entsprechenden Beleg im Erfolgsfall erzeugen zu können.
### POST: Rückerstattung starten [POST]
+ Parameters
+ pid_pz (string, required) ... ein String, der aus dem PID und seiner Prüfsumme besteht (siehe dazu das Kapitel [Prüfsummenberechnung](#checksum).
+ descr (string, optional) ... optionaler Hinweis, z.B. Grund für die Erstattungsanfrage
+ Request
+ Headers
Accept: application/json oder application/xml
DevKey: {Ihr DeveloperKey}
SubmitterId: {transactionSubmitterId} welchen die Kasse bei der Aktivierung zugewiesen bekommen hat
+ Response 200
// Alles OK. Beleg über Rückerstattung kann gedruckt werden.
+ Response 412
// HTTP-Error 412 = PreconditionFailed
{
"reason_id":2,
"reason_text":"further error details as text"
}
// Hier die möglichen Gründe:
// 1 | Prüfsumme des PIDs falsch
// 2 | PID nicht gefunden
// 3 | Wurde schon zurückerstattet
// 4 | Zahlung noch nicht erfolgt
// 99 | Sonstiges (in diesem Fall wird das Feld reason_text genauere Angaben enthalten.