1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
..
This file is part of GNU TALER.
Copyright (C) 2019 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 2.1, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
==========================
Taler Bank Wire Plugin API
==========================
This section describes the API that the ``taler-bank`` wire plugin expects.
This API is currently implemented by the Taler Demo Bank, as well as by
LibEuFin (work in progress).
--------------
Authentication
--------------
The wire plugin authenticates requests to the bank service via
`HTTP basic auth <https://tools.ietf.org/html/rfc7617>`_.
-------------------
Making Transactions
-------------------
.. http:post:: /taler/transaction
This API allows the exchange to make a transaction, typically to a merchant. The bank account
of the exchange is not included in the request, but instead derived from the user name in the
authentication header.
To make the API idempotent, the client must include a nonce. Requests with the same nonce
are rejected unless the request is the same.
**Request:** The body of this request must have the format of a `TransactionRequest`.
**Response:**
:status 200 OK:
The request has been correctly handled, so the funds have been transferred to
the recipient's account. The body is a `TransactionResponse`
:status 400 Bad Request: The bank replies a `BankError` object.
:status 406 Not Acceptable: The request had wrong currency; the bank replies a `BankError` object.
:status 409 Conflict:
A transaction with the same ``transaction_uid`` but different transaction details
has been submitted before.
**Details:**
.. ts:def:: TransactionResponse
interface TransactionResponse {
// Timestamp related to the transaction being made.
timestamp: Timestamp;
// Opaque of the transaction that the bank has made.
row_id: string;
}
.. ts:def:: TransactionRequest
interface TransactionRequest {
// Nonce to make the request idempotent. Requests with the same
// transaction_uid that differ in any of the other fields
// are rejected.
transaction_uid: HashCode;
// Amount to transfer.
amount: Amount;
// Reserve public key, will be included in the details
// of the wire transfer.
reserve_pub: string;
// The recipient's account identifier as a payto URI
credit_account: string;
}
.. ts:def:: BankError
interface BankError {
// Human readable explanation of the failure.
error: string;
// Numeric Taler error code (`TALER_ErrorCode`)
ec: number;
}
--------------------------------
Querying the transaction history
--------------------------------
.. http:get:: /taler/history
Return a list of transactions made to the exchange. The transaction
list shall be filtered to only include transactions that include a valid
reserve public key.
The bank account of the exchange is determined via the user name in the ``Authorization`` header.
In fact the transaction history might come from a "virtual" account, where multiple real bank accounts
are merged into one history.
Transactions are identified by an opaque string identifier, referred to here
as "row ID". The semantics of the row ID (including its sorting order) are
determined by the bank server and completely opaque to the client.
The list of returned transactions is determined by a row ID *starting point*
and a signed non-zero integer *delta*:
* If *delta* is positive, return a list of up to *delta* transactions (all matching
the filter criteria) strictly **after** the starting point. The transactions are sorted
in **ascending** order of the row ID.
* If *delta* is negative, return a list of up to *-delta* transactions (allmatching
the filter criteria) strictly **before** the starting point. The transactions are sorted
in **descending** order of the row ID.
If *starting point* is not explicitly given, it defaults to:
* A value that is **smaller** than all other row IDs if *delta* is **positive**.
* A value that is **larger** than all other row IDs if *delta* is **negative**.
**Request**
:query start: *Optional.*
Row identifier to explicitly set the *starting point* of the query.
:query delta:
The *delta* value that determines the range of the query.
:query long_poll_ms: *Optional.* If this parameter is specified and the
result of the query would be empty, the bank will wait up to ``long_poll_ms``
milliseconds for new transactions that match the query to arrive and only
then send the HTTP response. A client must never rely on this behavior, as
the bank may return a response immediately or after waiting only a fraction
of ``long_poll_ms``.
**Response**
:status 200 OK: JSON object whose field ``transactions`` is an array of type `BankTransaction`.
:status 204 No content: in case no records exist for the targeted user.
.. ts:def:: BankTransaction
interface BankTransaction {
// Opaque identifier of the returned record
row_id: string;
// Date of the transaction
date: Timestamp;
// Amount transferred
amount: Amount;
// Payto URI to identify the sender of funds
debit_account: string;
// The reserve public key extracted from the transaction details
reserve_pub: string;
}
|