From a1ae94973e9a549acb022c009f06828ec12d21f3 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Tue, 24 Mar 2020 16:37:40 +0530 Subject: remove outdated wallet docs --- taler-wallet.rst | 210 +------------------------------------------------------ 1 file changed, 1 insertion(+), 209 deletions(-) diff --git a/taler-wallet.rst b/taler-wallet.rst index 1889c585..bb9b34e8 100644 --- a/taler-wallet.rst +++ b/taler-wallet.rst @@ -77,212 +77,4 @@ Android Wallet APIs and Data Formats ===================== -This section describes the wallet backend API. The goal of this API is to -be easy to consume without having to implement Taler-specific data formats -or algorithms. This is why some redundancy is present, for example in -how amounts are returned. - -Balance -------- - -The balance is computed with different types of "slicing": - -* ``byExchange``: Balance by the exchange it was withdrawn from -* ``byAuditor``: Balance by each auditor trusted by the wallet -* ``byCurrency``: Balance by currency - -Each balance entry contains the following information: - -* ``amountCurrent``: Amount available to spend **right now** -* ``amountAvailable``: Amount available to spend after refresh and withdrawal - operations have completed. -* ``amountPendingOutgoing``: Amount that is allocated to be spent on a payment - but hasn't been spent yet. -* ``amountPendingIncoming``: Amount that will be available but is not available yet - (from refreshing and withdrawal) -* ``amountPendingIncomingWithdrawal``: Amount that will be available from pending withdrawals -* ``amountPendingIncomingRefresh``: Amount that will be available from pending refreshes - - -History -------- - -All events contain a ``type``, a ``timestamp`` and a ``eventUID``. When -querying the event history, a level can be specified. Only events with a -verbosity level ``<=`` the queried level are returned. - -The following event types are available: - -``exchange-added`` - Emitted when an exchange has ben added to the wallet. - -``exchange-update-started`` - Emitted when updating an exchange has started. - -``exchange-update-finished`` - Emitted when updating an exchange has started. - -``reserve-created`` (Level 1) - A reserve has been created. Contains the following detail fields: - - * ``exchangeBaseUrl`` - * ``reservePub``: Public key of the reserve - * ``expectedAmount``: Amount that is expected to be in the reserve. - * ``reserveType``: How was the reserve created? Can be ``taler-withdraw`` when - created by dereferencing a ``taler://pay`` URI or ``manual`` when the reserve - has been created manually. - -``reserve-bank-confirmed`` (Level 1) - Only applies to reserves with ``reserveType`` of ``taler-withdraw``. - This event is emitted when the wallet has successfully sent the details about the - withdrawal (reserve key, selected exchange). - -``reserve-exchange-confirmed`` (Level 0) - This event is emitted the first time that the exchange returns a success result - for querying the status of the resere. - - * ``exchangeBaseUrl`` - * ``reservePub``: Public key of the reserve - * ``currentAmount``: Amount that is expected to be in the reserve. - -``reserve-exchange-updated`` (Level 0) - Emitted when a reserve has been updated **and** the remaining amount has changed. - -``withdraw-started`` (Level 1) - Emitted when the wallet starts a withdrawal from a reserve. Contains the following detail fields: - - * ``withdrawReason``: Why was the withdraw started? Can be ``initial`` (first withdrawal to drain a - reserve), ``repeat`` (withdrawing from a manually topped-up reserve) or ``tip`` - * ``withdrawRawAmount``: Amount that is subtracted from the reserve, includes fees. - * ``withdrawEffectiveAmount``: Amount that will be added to the balance. - -``withdraw-coin-finished`` (Level 2) - An individual coin has been successfully withdrawn. - -``withdraw-finished`` (Level 0) - Withdraw was successful. Details: - - * ``withdrawRawAmount``: Amount that is subtracted from the reserve, includes fees. - * ``withdrawEffectiveAmount``: Amount that will be added to the balance. - -``order-offered`` (Level 1) - A merchant has offered the wallet to download an order. - -``order-claimed`` (Level 1) - The wallet has downloaded and claimed an order. - -``order-pay-confirmed`` (Level 0) - The wallet's user(-agent) has confirmed that a payment should - be made for this order. - -``pay-coin-finished`` (Level 2) - A coin has been sent successfully to the merchant. - -``pay-finished`` (Level 0) - An order has been paid for successfully for the first time. - This event is not emitted for payment re-playing. - -``refresh-started`` (Level 1) - A refresh session (one or more coins) has been started. Details: - - * ``refreshReason``: One of ``forced``, ``pay`` or ``refund``. - -``refresh-coin-finished`` (Level 2) - Refreshing a single coin has succeeded. - -``refresh-finished`` (Level 0) - A refresh session has succeeded. - -``tip-offered`` (Level 1) - A tip has been offered, but not accepted yet. - -``tip-accepted`` (Level 1) - A tip has been accepted. Together with this event, - a corresponding ``withdraw-started`` event is also emitted. - -``refund`` (Level 0) - The wallet has been notified about a refund. A corresponding - ``refresh-started`` event with ``refreshReason`` set to ``refund`` - will be emitted as well. - - -Pending Operations ------------------- - - -``exchange-update``: - Shown when exchange information (``/keys`` and ``/wire``) is being updated. - -``reserve``: - Shown when a reserve has been created (manually or via dereferencing a ``taler://withdraw`` URI), - but the reserve has not been confirmed yet. - - Details: - - * ``reserveType``: How was the reserve created? Can be ``taler-withdraw`` when - created by dereferencing a ``taler://pay`` URI or ``manual`` when the reserve - has been created manually. - * ``expectedAmount``: Amount we expect to be in the reserve. - * ``status``: Either ``new`` or ``confirmed-bank``. - * ``lastError``: If present, contains the last error pertaining to the reserve, - either from the bank or from the exchange. - - **Rendering**: The pending operation is rendered as "waiting for money transfer". - -``withdrawal`` - Shown when a withdrawal is in progress (either from a reserve in the wallet or - from tipping). - - Details: - - * ``exchangeBaseUrl`` - * ``coinsPending`` - * ``coinsWithdrawn`` - * ``amountWithdrawn`` - * ``amountPending`` - * ``totalWithdrawnAmount``: Amount actually subtracted from the reserve, including fees - * ``totalEffectiveAmount``: Amount that will be added to the balance - * ``lastErrors``: If present, contains the last error for every coin that is - part of this withdrawal operation. - - **Rendering**: The pending operation is rendered as "withdrawing digital cash". - -``pay`` - Shown when a payment is in progress. - - Details: - - * ``amountPrice``: Price of the order that is being purchased - * ``coinsPaid``: Number of coins successfully submitted as payment. - * ``coinsPending``: Number of coins successfully submitted as payment. - * ``amountEffectivePrice``: Effective price, including fees for refreshing *and* - coins that are too small to refresh. - * ``lastErrors``: If present, contains the last error for every coin that is - part of this pay operation. - - **Rendering**: The pending operation is rendered as "paying". - -``refresh`` - Shown when a refresh is in progress, either one that's manually forced, one - after payment, or one after a refund. - - Details: - - * ``refreshReason``: One of ``forced``, ``pay`` or ``refund`` - * ``totalRefreshedAmount``: Amount that has been successfully refreshed - as part of this session - * ``coinsPending``: Number of coins that are part of the refresh operation, but - haven't been processed yet. - * ``coinsMelted``: Number of coins that have been successfully melted. - * ``coinsRefreshed``: Number of coins that have been successfully refreshed. - * ``lastErrors``: If present, contains the last error for every coin that is - part of this refresh operation. - - **Rendering**: The pending operation is rendered as "fetching change", optionally - with "(after manual request)", "(after payment") or "(after refund)". - -``refund`` - Shown when a merchant's refund permission is handed to the exchange. - -``tip`` - Shown when a tip is being picked up from the merchant +*TBD.* -- cgit v1.2.3 From 149de84d66c86fdd324bb4fe6eb239651c69b78a Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Tue, 24 Mar 2020 17:58:47 +0530 Subject: instructions for integration tests with the wallet --- taler-wallet.rst | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/taler-wallet.rst b/taler-wallet.rst index bb9b34e8..995237bd 100644 --- a/taler-wallet.rst +++ b/taler-wallet.rst @@ -78,3 +78,64 @@ APIs and Data Formats ===================== *TBD.* + + + +Integration Test Example +======================== + +Integration tests can be done with the low-level wallet commands. To select which coins and denominations +to use, the wallet can dump the coins in an easy-to-process format (`CoinDumpJson `__). + +The following example does a simple withdrawal recoup: + +.. code-block:: sh + + # Withdraw digital cash + $ taler-wallet-cli --wallet-db=mydb.json testing withdraw \ + -b https://bank.int.taler.net/ \ + -e https://exchange.int.taler.net/ \ + -a INTKUDOS:10 + + $ coins=$(taler-wallet-cli --wallet-db=mydb.json advanced dump-coins) + + # Find coin we want to revoke + $ rc=$(echo "$coins" | jq -r '[.coins[] | select((.denom_value == "INTKUDOS:5"))][0] | .coin_pub') + # Find the denom + $ rd=$(echo "$coins" | jq -r '[.coins[] | select((.denom_value == "INTKUDOS:5"))][0] | .denom_pub_hash') + # Find all other coins, which will be suspended + $ susp=$(echo "$coins" | jq --arg rc "$rc" '[.coins[] | select(.coin_pub != $rc) | .coin_pub]') + + # The exchange revokes the denom + $ taler-exchange-keyup -r $rd + $ taler-deployment-restart + + # Now we suspend the other coins, so later we will pay with the recouped coin + $ taler-wallet-cli --wallet-db=mydb.json advanced suspend-coins "$susp" + + # Update exchange /keys so recoup gets scheduled + $ taler-wallet-cli --wallet-db=mydb.json exchanges update -f https://exchange.int.taler.net/ + + # Block until scheduled operations are done + $ taler-wallet-cli --wallet-db=mydb.json run-until-done + + # Now we buy something, only the coins resulting from recouped will be + # used, as other ones are suspended + $ taler-wallet-cli --wallet-db=mydb.json testing test-pay -m https://backend.int.taler.net/ -k sandbox -a "INTKUDOS:1" -s "foo" + $ taler-wallet-cli --wallet-db=mydb.json run-until-done + + +To test refreshing, force a refresh: + +.. code-block:: sh + + $ taler-wallet-cli --wallet-db=mydb.json advanced force-refresh "$coin_pub" + + +To test zombie coins, use the timetravel option, it **must** be passed to the top-level command and not the subcommand: + +.. code-block:: sh + + # Update exchange /keys with time travel, value in microseconds + $ taler-wallet-cli --timetravel=1000000 --wallet-db=mydb.json exchanges update -f https://exchange.int.taler.net/ + -- cgit v1.2.3 From da863232486aee72eebf3f76000329f27e5163f5 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Tue, 24 Mar 2020 18:07:54 +0530 Subject: clarifications --- taler-wallet.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/taler-wallet.rst b/taler-wallet.rst index 995237bd..25e4c17b 100644 --- a/taler-wallet.rst +++ b/taler-wallet.rst @@ -87,6 +87,10 @@ Integration Test Example Integration tests can be done with the low-level wallet commands. To select which coins and denominations to use, the wallet can dump the coins in an easy-to-process format (`CoinDumpJson `__). +The database file for the wallet can be selected with the ``--wallet-db`` +option. This option must be passed to the ``taler-wallet-cli`` command and not +the subcommands. If the database file doesn't exist, it will be created. + The following example does a simple withdrawal recoup: .. code-block:: sh @@ -132,7 +136,8 @@ To test refreshing, force a refresh: $ taler-wallet-cli --wallet-db=mydb.json advanced force-refresh "$coin_pub" -To test zombie coins, use the timetravel option, it **must** be passed to the top-level command and not the subcommand: +To test zombie coins, use the timetravel option. It **must** be passed to the +top-level command and not the subcommand: .. code-block:: sh -- cgit v1.2.3 From 470eb01b244913498f7bb5f2991faf7472bef95b Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 28 Mar 2020 21:56:59 +0100 Subject: rename section to better identify command --- core/api-exchange.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/api-exchange.rst b/core/api-exchange.rst index 0b039d38..3d6f7c19 100644 --- a/core/api-exchange.rst +++ b/core/api-exchange.rst @@ -1028,9 +1028,9 @@ the API during normal operation. } -------------------- -Emergency Cash-Back -------------------- +------ +Recoup +------ This API is only used if the exchange is either about to go out of business or has had its private signing keys compromised (so in -- cgit v1.2.3 From 293b3d55d8cd6cf946bb4e86bfe8ef743156838b Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Mon, 30 Mar 2020 15:05:45 +0530 Subject: document protocol version ranges --- core/api-common.rst | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/core/api-common.rst b/core/api-common.rst index 44d4eb00..5fafacb9 100644 --- a/core/api-common.rst +++ b/core/api-common.rst @@ -121,6 +121,59 @@ handle the error as if an internal error (500) had been returned. type_actual?: string; } +----------------------- +Protocol Version Ranges +----------------------- + +Some of the Taler services (e.g. exchange, merchant, bank integration API) +expose the range of API versions they support. Clients in turn have an API +version range they support. These version ranges are written down in the +`libtool version format `__. + +A protocol version is a positive, non-zero integer. A protocol version range consists of three components: + +1. The ``current`` version. This is the latest version of the protocol supported by the client or service. +2. The ``revision`` number. This value is not to be interpreted by the client/server, but serves + purely as a comment. Each time a service/client for a protocol is updated while supporting the same + set of protocol versions, the revision should be increased. +3. The ``age`` number. This non-zero integer identifies with how many previous protocol versions this + implementation is compatible. An ``age`` of 0 implies that the implementation only supports + the ``current`` protocol version. The ``age`` must be less or equal than the ``current`` protocol version. + +To avoid confusion with semantic versions, the protocol version range is written down in the following format: + +.. code:: none + + current[:revision[:age]] + +The angle brackets mark optional components. If either ``revision`` or ``age`` are omitted, they default to 0. + +Examples: + +* "1" and "1" are compatible +* "1" and "2" are **incompatible** +* "2:0:1" and "1:0:0" are compatible +* "2:5:1" and "1:10:0" are compatible +* "4:0:1" and "2:0:0" are **incompatible** +* "4:0:1" and "3:0:0" are compatible + +.. note:: + + `Semantic versions `__ are not a good tool for this job, as we concisely want to express + that the client/server supports the last ``n`` versions of the protocol. + Semantic versions don't support this, and semantic version ranges are too complex for this. + +.. warning:: + + A client doesn't have one single protocol version range. Instead, it has + a protocol version range for each type of service it talks to. + +.. warning:: + + For privacy reasons, the protocol version range of a client should not be + sent to the service. Instead, the client should just use the two version ranges + to decide whether it will talk to the service. + .. _encodings-ref: -- cgit v1.2.3 From ba934cc1ef9158bf0178f6d722bab2eb911583a5 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Mon, 30 Mar 2020 15:58:52 +0530 Subject: integrate Christian's idea about 'revision' field --- core/api-common.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/api-common.rst b/core/api-common.rst index 5fafacb9..1721c42f 100644 --- a/core/api-common.rst +++ b/core/api-common.rst @@ -133,9 +133,11 @@ version range they support. These version ranges are written down in the A protocol version is a positive, non-zero integer. A protocol version range consists of three components: 1. The ``current`` version. This is the latest version of the protocol supported by the client or service. -2. The ``revision`` number. This value is not to be interpreted by the client/server, but serves +2. The ``revision`` number. This value should usually not be interpreted by the client/server, but serves purely as a comment. Each time a service/client for a protocol is updated while supporting the same set of protocol versions, the revision should be increased. + In rare cases, the revision number can be used to work around unintended breakage in deployed + versions of a service. This is discouraged and should only be used in exceptional situations. 3. The ``age`` number. This non-zero integer identifies with how many previous protocol versions this implementation is compatible. An ``age`` of 0 implies that the implementation only supports the ``current`` protocol version. The ``age`` must be less or equal than the ``current`` protocol version. -- cgit v1.2.3 From d71b4e497b93a3f06a4b346d37dabe1351b07b7b Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Mon, 30 Mar 2020 16:22:33 +0530 Subject: document applyRefund api for wallet-core --- taler-wallet.rst | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/taler-wallet.rst b/taler-wallet.rst index 25e4c17b..c619d430 100644 --- a/taler-wallet.rst +++ b/taler-wallet.rst @@ -77,8 +77,24 @@ Android Wallet APIs and Data Formats ===================== -*TBD.* - +Refunds +------- + +:name: ``"applyRefund"`` +:description: Process a refund from a ``taler://refund`` URI. +:request: + .. ts:def:: WalletApplyRefundRequest + + interface WalletApplyRefundRequest { + talerRefundUri: string; + } +:response: + .. ts:def:: WalletApplyRefundResponse + + interface WalletApplyRefundResponse { + // Identifier for the purchase that was refunded + contractTermsHash: string; + } Integration Test Example -- cgit v1.2.3 From ab8836e0bf8167e21be7e6b05fb8664b61bd5ef0 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Mon, 30 Mar 2020 19:24:59 +0530 Subject: better types for the transaction history --- core/api-exchange.rst | 131 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 84 insertions(+), 47 deletions(-) diff --git a/core/api-exchange.rst b/core/api-exchange.rst index 3d6f7c19..963926d0 100644 --- a/core/api-exchange.rst +++ b/core/api-exchange.rst @@ -399,70 +399,107 @@ exchange. .. ts:def:: TransactionHistoryItem - interface TransactionHistoryItem { - // Either "WITHDRAW", "DEPOSIT", "RECOUP", or "CLOSING" - type: string; + // Union discriminated by the "type" field. + type ReserveTransaction = + | ReserveWithdrawTransaction + | ReserveDepositTransaction + | ReserveClosingTransaction + | ReserveRecoupTransaction; + + .. ts:def:: ReserveWithdrawTransaction + + interface ReserveWithdrawTransaction { + type: "WITHDRAW"; - // The amount that was withdrawn or deposited (incl. fee) - // or paid back, or the closing amount. + // Amount withdrawn. amount: Amount; - // Hash of the denomination public key of the coin, if - // type is "WITHDRAW". - h_denom_pub?: Base32; + //Hash of the denomination public key of the coin. + h_denom_pub: HashCode; + + // Hash of the blinded coin to be signed + h_coin_envelope: HashCode; + + // Signature of 'TALER_WithdrawRequestPS' created with the reserves's + // private key. + reserve_sig: EddsaSignature; + + // Fee that is charged for withdraw. + withdraw_fee: Amount; + } + - // Hash of the blinded coin to be signed, if - // type is "WITHDRAW". - h_coin_envelope?: Base32; + .. ts:def:: ReserveDepositTransaction - // Signature of 'TALER_WithdrawRequestPS' created with the `reserves's - // private key `. Only present if type is "WITHDRAW". - reserve_sig?: EddsaSignature; + interface ReserveDepositTransaction { + type: "DEPOSIT"; - // The fee that was charged for "WITHDRAW". - withdraw_fee?: Amount; + // Amount deposited. + amount: Amount; - // The fee that was charged for "CLOSING". - closing_fee?: Amount; + // Sender account payto://-URL + sender_account_url: string; - // Sender account payto://-URL, only present if type is "DEPOSIT". - sender_account_url?: string; + // Transfer details uniquely identifying the transfer. + wire_reference: string; - // Receiver account details, only present if type is "CLOSING". - receiver_account_details?: any; + // Timestamp of the incoming wire transfer. + timestamp: Timestamp; + } + - // Transfer details uniquely identifying the transfer, only present if type is "DEPOSIT". - wire_reference?: any; + .. ts:def:: ReserveClosingTransaction - // Wire transfer subject, only present if type is "CLOSING". - wtid?: any; + interface ReserveClosingTransaction { + type: "CLOSING"; - // Hash of the wire account into which the funds were - // returned to, present if type is "CLOSING". - h_wire?: Base32; + // Closing balance. + amount: Amount; - // If ``type`` is "RECOUP", this is a signature over - // a struct `TALER_RecoupConfirmationPS` with purpose - // TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP. - // If ``type`` is "CLOSING", this is a signature over a - // struct `TALER_ReserveCloseConfirmationPS` with purpose + // Closing fee charged by the exchange. + closing_fee: Amount; + + // Wire transfer subject. + wtid: string; + + // Hash of the wire account into which the funds were returned to. + h_wire: string; + + // This is a signature over a + // struct TALER_ReserveCloseConfirmationPS with purpose // TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED. - // Not present for other values of ``type``. - exchange_sig?: EddsaSignature; + exchange_sig: EddsaSignature; - // Public key used to create ``exchange_sig``, only present if - // ``exchange_sig`` is present. - exchange_pub?: EddsaPublicKey; + // Public key used to create exchange_sig. + exchange_pub: EddsaPublicKey; - // Public key of the coin that was paid back; only present if type is "RECOUP". - coin_pub?: CoinPublicKey; + // Time when the reserve was closed. + timestamp: Timestamp; + } - // Timestamp when the exchange received the /recoup or executed the - // wire transfer. Only present if ``type`` is "DEPOSIT", "RECOUP" or - // "CLOSING". - timestamp?: Timestamp; - } + + .. ts:def:: ReserveRecoupTransaction + + interface ReserveRecoupTransaction { + type: "RECOUP"; + + // Amount paid back. + amount: Amount; + + // This is a signature over + // a struct TALER_PaybackConfirmationPS with purpose + // TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK. + exchange_sig: EddsaSignature; + + // Public key used to create exchange_sig. + exchange_pub: EddsaPublicKey; + // Time when the funds were paid back into the reserve. + timestamp: Timestamp; + + // Public key of the coin that was paid back. + coin_pub: CoinPublicKey; + } .. http:post:: /reserves/$RESERVE_PUB/withdraw @@ -1232,7 +1269,7 @@ typically also view the balance.) **Request:** - :query merchant_sig: EdDSA signature of the merchant made with purpose `TALER_SIGNATURE_MERCHANT_TRACK_TRANSACTION` , affirming that it is really the merchant who requires obtaining the wire transfer identifier. + :query merchant_sig: EdDSA signature of the merchant made with purpose ``TALER_SIGNATURE_MERCHANT_TRACK_TRANSACTION`` , affirming that it is really the merchant who requires obtaining the wire transfer identifier. **Response:** -- cgit v1.2.3 From 83d8d63066fedfffd0bfcf8a03a6bfa85b81007e Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Mon, 30 Mar 2020 19:28:08 +0530 Subject: whitespace --- core/api-exchange.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/api-exchange.rst b/core/api-exchange.rst index 963926d0..b45cddeb 100644 --- a/core/api-exchange.rst +++ b/core/api-exchange.rst @@ -414,7 +414,7 @@ exchange. // Amount withdrawn. amount: Amount; - //Hash of the denomination public key of the coin. + // Hash of the denomination public key of the coin. h_denom_pub: HashCode; // Hash of the blinded coin to be signed -- cgit v1.2.3 From 3d10e7b94f9f68cea4d2731c8ebbaff845fb2dfd Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 30 Mar 2020 18:09:11 +0200 Subject: specification fixes --- core/api-exchange.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/core/api-exchange.rst b/core/api-exchange.rst index b45cddeb..92ff0289 100644 --- a/core/api-exchange.rst +++ b/core/api-exchange.rst @@ -402,7 +402,7 @@ exchange. // Union discriminated by the "type" field. type ReserveTransaction = | ReserveWithdrawTransaction - | ReserveDepositTransaction + | ReserveCreditTransaction | ReserveClosingTransaction | ReserveRecoupTransaction; @@ -429,10 +429,10 @@ exchange. } - .. ts:def:: ReserveDepositTransaction + .. ts:def:: ReserveCreditTransaction - interface ReserveDepositTransaction { - type: "DEPOSIT"; + interface ReserveCreditTransaction { + type: "CREDIT"; // Amount deposited. amount: Amount; @@ -446,7 +446,7 @@ exchange. // Timestamp of the incoming wire transfer. timestamp: Timestamp; } - + .. ts:def:: ReserveClosingTransaction @@ -462,8 +462,8 @@ exchange. // Wire transfer subject. wtid: string; - // Hash of the wire account into which the funds were returned to. - h_wire: string; + // payto:// URI of the the wire account into which the funds were returned to. + receiver_account_details: string; // This is a signature over a // struct TALER_ReserveCloseConfirmationPS with purpose @@ -477,7 +477,7 @@ exchange. timestamp: Timestamp; } - + .. ts:def:: ReserveRecoupTransaction interface ReserveRecoupTransaction { -- cgit v1.2.3 From 9bdf493ebe53a54ae82f3d416dffefdfbbd2867a Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Tue, 31 Mar 2020 00:22:28 +0530 Subject: wire_reference documentation --- core/api-exchange.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/api-exchange.rst b/core/api-exchange.rst index 92ff0289..c6186284 100644 --- a/core/api-exchange.rst +++ b/core/api-exchange.rst @@ -440,8 +440,9 @@ exchange. // Sender account payto://-URL sender_account_url: string; - // Transfer details uniquely identifying the transfer. - wire_reference: string; + // Opaque identifier internal to the exchange that + // uniquely identifies the wire transfer that credited the reserve. + wire_reference: Base32; // Timestamp of the incoming wire transfer. timestamp: Timestamp; -- cgit v1.2.3 From 90d7b517a09eb765b1912bf27ef0a8f668ed84c7 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 31 Mar 2020 20:56:26 +0200 Subject: typos --- developers-manual.rst | 2 +- manpages/taler-auditor-exchange.1.rst | 2 +- manpages/taler.conf.5.rst | 4 ++-- taler-exchange-manual.rst | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/developers-manual.rst b/developers-manual.rst index 7d1f6ab8..4799dbd0 100644 --- a/developers-manual.rst +++ b/developers-manual.rst @@ -892,7 +892,7 @@ from implementing new CMDs and traits within other codebases. :: - /* Withouth loss of generality, let's consider the + /* Without loss of generality, let's consider the * following logic to exist inside the run() method of CMD1 */ .. diff --git a/manpages/taler-auditor-exchange.1.rst b/manpages/taler-auditor-exchange.1.rst index 219ad44e..422d8b06 100644 --- a/manpages/taler-auditor-exchange.1.rst +++ b/manpages/taler-auditor-exchange.1.rst @@ -58,7 +58,7 @@ Bugs We should optionally verify the correctness of this exchange’s base URL and that it matches the master public key (note that the exchange may -still be offline, so it should be possible to bypass such a verfication +still be offline, so it should be possible to bypass such a verification step). Furthermore, if we do verification, as a (less secure) convenience option, we should make **-** m optional and obtain it from the base URL. diff --git a/manpages/taler.conf.5.rst b/manpages/taler.conf.5.rst index acbfa03e..0378845f 100644 --- a/manpages/taler.conf.5.rst +++ b/manpages/taler.conf.5.rst @@ -330,7 +330,7 @@ named “[fees-METHOD]” state the (aggregate) wire transfer fee and the reserve closing fees charged by the exchange. Note that fees are specified using the name of the wire method, not by the plugin name. You need to replace “YEAR” in the option name by the calendar year for which -the fee should apply. Usually, fees should be given for serveral years +the fee should apply. Usually, fees should be given for several years in advance. WIRE-FEE-YEAR @@ -360,7 +360,7 @@ DURATION_SPEND How long do clients have to spend these coins? FEE_WITHDRAW - What fee is charged for withdrawl? + What fee is charged for withdrawal? FEE_DEPOSIT What fee is charged for depositing? diff --git a/taler-exchange-manual.rst b/taler-exchange-manual.rst index 89f6ad77..d7a6c21e 100644 --- a/taler-exchange-manual.rst +++ b/taler-exchange-manual.rst @@ -148,7 +148,7 @@ components: Postgres The exchange requires a DBMS to stores the transaction history for the Taler exchange and aggregator, and a (typically separate) DBMS - for the Taler auditor. For now, the GNU Taler reference implemenation + for the Taler auditor. For now, the GNU Taler reference implementation only supports Postgres, but the code could be easily extended to support another DBMS. @@ -698,7 +698,7 @@ the following command Those arguments are all mandatory. - ``EXCHANGE_MASTER_PUB`` the base32 Crockford-encoded exchange’s - master public key. Tipically, this value lies in the configuration + master public key. Typically, this value lies in the configuration option ``[exchange]/master_public_key``. - ``BLOB`` the blob generated in the previous step. -- cgit v1.2.3 From 5956072e16c75ac45778535dc63365f130dc85f7 Mon Sep 17 00:00:00 2001 From: Dennis Neufeld Date: Wed, 1 Apr 2020 13:57:40 +0000 Subject: small correction --- anastasis.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/anastasis.rst b/anastasis.rst index e451c93f..73a2eeda 100644 --- a/anastasis.rst +++ b/anastasis.rst @@ -635,7 +635,7 @@ In the following, UUID is always defined and used according to `RFC 4122`_. policy_salt: [32]; //bytearray // Master key, AES-encrypted with key derived from - // salt and secrets revealed by the following list of + // salt and keyshares revealed by the following list of // escrow methods identified by UUID. encrypted_master_key: [32]; //bytearray -- cgit v1.2.3 From 8fb7ba400b37184804e9134984c02a5e4d212383 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 3 Apr 2020 21:26:08 +0200 Subject: update docu to match latest merchant API --- core/api-merchant.rst | 58 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 47 insertions(+), 11 deletions(-) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index 469ce766..b9dac413 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -231,14 +231,23 @@ Giving Customer Tips :status 200 OK: A tip has been created. The backend responds with a `TipCreateConfirmation` :status 404 Not Found: - The instance is unknown to the backend, expired or was never enabled or - the reserve is unknown to the exchange or expired (see detailed status - either being TALER_EC_RESERVE_STATUS_UNKNOWN or - TALER_EC_TIP_AUTHORIZE_INSTANCE_UNKNOWN or - TALER_EC_TIP_AUTHORIZE_INSTANCE_DOES_NOT_TIP or - TALER_EC_TIP_AUTHORIZE_RESERVE_EXPIRED. + The instance is unknown to the backend. :status 412 Precondition Failed: - The tip amount requested exceeds the available reserve balance for tipping. + The tip amount requested exceeds the available reserve balance for tipping, or + the instance was never configured for tipping. + :status 424 Failed Dependency: + We are unable to process the request because of a problem with the exchange. + Likely returned with an "exchange-code" in addition to a "code" and + an "exchange-http-status" in addition to our own HTTP status. Also may + include the full exchange reply to our request under "exchange-reply". + Naturally, those diagnostics may be omitted if the exchange did not reply + at all, or send a completely malformed response. + :status 503 Service Unavailable: + We are unable to process the request, possibly due to misconfiguration or + disagreement with the exchange (it is unclear which party is to blame). + Likely returned with an "exchange-code" in addition to a "code" and + an "exchange-http-status" in addition to our own HTTP status. Also may + include the full exchange reply to our request under "exchange-reply". .. ts:def:: TipCreateRequest @@ -276,8 +285,23 @@ Giving Customer Tips :status 200 OK: A tip has been created. The backend responds with a `TipQueryResponse` + :status 404 Not Found: + The instance is unknown to the backend. :status 412 Precondition Failed: The merchant backend instance does not have a tipping reserve configured. + :status 424 Failed Dependency: + We are unable to process the request because of a problem with the exchange. + Likely returned with an "exchange-code" in addition to a "code" and + an "exchange-http-status" in addition to our own HTTP status. Also may + include the full exchange reply to our request under "exchange-reply". + Naturally, those diagnostics may be omitted if the exchange did not reply + at all, or send a completely malformed response. + :status 503 Service Unavailable: + We are unable to process the request, possibly due to misconfiguration or + disagreement with the exchange (it is unclear which party is to blame). + Likely returned with an "exchange-code" in addition to a "code" and + an "exchange-http-status" in addition to our own HTTP status. Also may + include the full exchange reply to our request under "exchange-reply". .. ts:def:: TipQueryResponse @@ -295,7 +319,7 @@ Giving Customer Tips expiration: Timestamp; // Reserve public key of the tipping reserve - reserve_pub: string; + reserve_pub: EddsaPublicKey; } @@ -966,15 +990,27 @@ both by the user's browser and their wallet. the request used the mode "pay", or a `MerchantRefundResponse` if the request used was the mode "abort-refund". The ``frontend`` should now fullfill the contract. - :status 412 Precondition Failed: - The given exchange is not acceptable for this merchant, as it is not in the - list of accepted exchanges and not audited by an approved auditor. + :status 400 Bad request: + Either the client request is malformed or some specific processing error + happened that may be the fault of the client as detailed in the JSON body + of the response. :status 401 Unauthorized: One of the coin signatures was not valid. :status 403 Forbidden: The exchange rejected the payment because a coin was already spent before. The response will include the 'coin_pub' for which the payment failed, in addition to the response from the exchange to the ``/deposit`` request. + :status 404 Not found: + The merchant backend could not find the proposal or the instance + and thus cannot process the payment. + :status 412 Precondition Failed: + The given exchange is not acceptable for this merchant, as it is not in the + list of accepted exchanges and not audited by an approved auditor. + :status 424 Failed Dependency: + The merchant's interaction with the exchange failed in some way. + The client might want to try later again. + This includes failures like the denomination key of a coin not being + known to the exchange as far as the merchant can tell. The backend will return verbatim the error codes received from the exchange's :ref:`deposit ` API. If the wallet made a mistake, like by -- cgit v1.2.3 From bf0a7c8dac654f250aae565efafdef79b27a2552 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 4 Apr 2020 14:23:34 +0200 Subject: document current option names --- manpages/taler.conf.5.rst | 41 +++++++++++++++++++----------- taler-merchant-manual.rst | 64 +++++++++++++++++++++++------------------------ 2 files changed, 58 insertions(+), 47 deletions(-) diff --git a/manpages/taler.conf.5.rst b/manpages/taler.conf.5.rst index 0378845f..5c2b7558 100644 --- a/manpages/taler.conf.5.rst +++ b/manpages/taler.conf.5.rst @@ -201,35 +201,43 @@ TIP_EXCHANGE_PRIV_FILENAME Filename with the private key granting access to the reserve, i.e. “${TALER_CONFIG_HOME}/merchant/reserve/tip.priv” -KNOWN EXCHANGES (for merchants and wallets) -------------------------------------------- +KNOWN EXCHANGES (for merchants) +------------------------------- The merchant configuration can include a list of known exchanges if the merchant wants to specify that certain exchanges are explicitly trusted. -For each trusted exchange, a section [exchange-NAME] must exist, where -NAME is a merchant-given name for the exchange. The following options -must be given in each “[exchange-NAME]” section. +For each trusted exchange, a section [merchant-exchange-$NAME] must exist, where +$NAME is a merchant-given name for the exchange. The following options +must be given in each “[exchange-$NAME]” section. -BASE_URL +EXCHANGE_BASE_URL Base URL of the exchange, i.e. “https://exchange.demo.taler.net/” MASTER_KEY Crockford Base32 encoded master public key, public version of the - exchange´s long-time offline signing key + exchange´s long-time offline signing key. Can be omitted, in that + case the exchange will NOT be trusted unless it is audited by + a known auditor. + Omitting the MASTER_KEY can be useful if we do not trust the exchange + without an auditor, but should pre-load the keys of this + particular exchange on startup instead of waiting for it to be + required by a client. CURRENCY - Name of the currency for which this exchange is trusted, i.e. “KUDOS” + Name of the currency for which this exchange is used, i.e. “KUDOS”. + The entire section is ignored if the currency does not match the currency + we use, which must be given in the [taler] section. -KNOWN AUDITORS (for merchants and wallets) ------------------------------------------- +KNOWN AUDITORS (for merchants) +------------------------------ The merchant configuration can include a list of known exchanges if the merchant wants to specify that certain auditors are explicitly trusted. -For each trusted exchange, a section [auditor-NAME] must exist, where -NAME is a merchant-given name for the exchange. The following options -must be given in each “[auditor-NAME]” section. +For each trusted exchange, a section [merchant-auditor-$NAME] must exist, where +$NAME is a merchant-given name for the auditor. The following options +must be given in each “[merchant-auditor-$NAME]” section. -BASE_URL +AUDITOR_BASE_URL Base URL of the auditor, i.e. “https://auditor.demo.taler.net/” AUDITOR_KEY @@ -237,13 +245,16 @@ AUDITOR_KEY CURRENCY Name of the currency for which this auditor is trusted, i.e. “KUDOS” + The entire section is ignored if the currency does not match the currency + we use, which must be given in the [taler] section. + MERCHANT ACCOUNT OPTIONS ------------------------ PAYTO_URI Specifies the payto://-URL of the account. The general format is - payto://METHOD/DETAILS. + payto://$METHOD/$DETAILS. WIRE_RESPONSE (exchange and merchant) Specifies the name of the file in which the wire details for this merchant diff --git a/taler-merchant-manual.rst b/taler-merchant-manual.rst index 0ac0ca55..771a1a0e 100644 --- a/taler-merchant-manual.rst +++ b/taler-merchant-manual.rst @@ -50,8 +50,8 @@ operating a basic backend. Architecture overview --------------------- -crypto-currency -KUDOS +:keywords: crypto-currency +:keywords: KUDOS Taler is a pure payment system, not a new crypto-currency. As such, it operates in a traditional banking context. In particular, this means that in order to receive funds via Taler, the merchant must have a @@ -224,7 +224,7 @@ the libgnunetutil and GNU Taler exchange dependencies. Installing libgnunetutil ~~~~~~~~~~~~~~~~~~~~~~~~ -GNUnet +:keywords: GNUnet Before you install libgnunetutil, you must download and install the dependencies mentioned in the previous section, otherwise the build may succeed but fail to export some of the tooling required by Taler. @@ -250,7 +250,7 @@ which requires you to run the last step as ``root``. Installing the GNU Taler exchange ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -exchange +:keywords: exchange After installing GNUnet, you can download and install the exchange as follows: @@ -276,7 +276,7 @@ installed GNUnet to ``/usr/local`` in the previous step. Installing the GNU Taler merchant backend ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -backend +:keywords: backend The following steps assume all dependencies are installed. Use the following commands to download and install the merchant backend: @@ -303,8 +303,8 @@ GNUnet to ``/usr/local`` in the previous steps. Installing Taler on Debian GNU/Linux ------------------------------------ -Wheezy -Debian +:keywords: Wheezy +:keywords: Debian Debian wheezy is too old and lacks most of the packages required. On Debian jessie, only GNU libmicrohttpd needs to be compiled from @@ -359,8 +359,8 @@ if you used the Debian wheezy instructions above, you need to pass How to configure the merchant’s backend ======================================= -taler-config -taler.conf +:keywords: taler-config +:keywords: taler.conf The installation already provides reasonable defaults for most of the configuration options. However, some must be provided, in particular the database account and bank account that the backend should use. By @@ -384,8 +384,8 @@ Service address The following option sets the transport layer address used by the merchant backend: - UNIX domain socket - TCP +:keywords: UNIX domain socket +:keywords: TCP :: [MERCHANT]/SERVE = TCP | UNIX @@ -404,7 +404,7 @@ Service address operating system, the use of a UNIX domain socket is recommended to avoid accidentally exposing the backend to the network. - port +:keywords: port To run the Taler backend on TCP port 8888, use: :: @@ -416,8 +416,8 @@ Currency Which currency the Web shop deals in, i.e. “EUR” or “USD”, is specified using the option - currency - KUDOS +:keywords: currency +:keywords: KUDOS :: [TALER]/CURRENCY @@ -431,7 +431,7 @@ Currency $ taler-config -s TALER -o CURRENCY -V KUDOS Database - DBMS +:keywords: DBMS In principle is possible for the backend to support different DBMSs. The option @@ -451,7 +451,7 @@ Database [merchantdb-postgres]/config - Postgres +:keywords: Postgres This option specifies a postgres access path using the format ``postgres:///$DBNAME``, where ``$DBNAME`` is the name of the Postgres database you want to use. Suppose ``$USER`` is the name of @@ -481,7 +481,7 @@ Database -V postgres:///$DBNAME Exchange - exchange +:keywords: exchange To add an exchange to the list of trusted payment service providers, you create a section with a name that starts with “exchange-”. In that section, the following options need to be configured: @@ -510,7 +510,7 @@ Exchange per currency. Instances - instance +:keywords: instance The backend allows the user to run multiple instances of shops with distinct business entities against a single backend. Each instance uses its own bank accounts and key for signing contracts. It is @@ -536,7 +536,7 @@ Instances options are discussed in Tipping visitors Accounts - wire format +:keywords: wire format In order to receive payments, the merchant backend needs to communicate bank account details to the exchange. For this, the configuration must include one or more sections named “ACCOUNT-name” @@ -586,7 +586,7 @@ Accounts Sample backend configuration ---------------------------- -configuration +:keywords: configuration The following is an example for a complete backend configuration: :: @@ -615,8 +615,8 @@ The following is an example for a complete backend configuration: USERNAME = my_user PASSWORD = 1234pass - [EXCHANGE-trusted] - URL = https://exchange.demo.taler.net/ + [merchant-exchange-trusted] + EXCHANGE_BASE_URL = https://exchange.demo.taler.net/ MASTER_KEY = CQQZ9DY3MZ1ARMN5K1VKDETS04Y2QCKMMCFHZSWJWWVN82BTTH00 CURRENCY = KUDOS @@ -636,7 +636,7 @@ them. Launching the backend --------------------- -backend +:keywords: backend taler-merchant-httpd Assuming you have configured everything correctly, you can launch the merchant backend using: @@ -776,7 +776,7 @@ Advanced topics Configuration format -------------------- -configuration +:keywords: configuration In Taler realm, any component obeys to the same pattern to get configuration values. According to this pattern, once the component has been installed, the installation deploys default values in @@ -849,7 +849,7 @@ configuration file used in our demos. See under ``deployment/config``. Using taler-config ------------------ -taler-config +:keywords: taler-config The tool ``taler-config`` can be used to extract or manipulate configuration values; however, the configuration use the well-known INI file format and can also be edited by hand. @@ -903,8 +903,8 @@ option. Merchant key management ----------------------- -merchant key -KEYFILE +:keywords: merchant key +:keywords: KEYFILE The option “KEYFILE” in the section “INSTANCE-default” specifies the path to the instance’s private key. You do not need to create a key manually, the backend will generate it automatically if it is missing. @@ -922,7 +922,7 @@ public key using the ``gnunet-ecc`` command-line tool: Tipping visitors ---------------- -tipping +:keywords: tipping Taler can also be used to tip Web site visitors. For example, you may be running an online survey, and you want to reward those people that have dutifully completed the survey. If they have installed a Taler wallet, @@ -936,8 +936,8 @@ There are four basic steps that must happen to tip a visitor. Configure a reserve and exchange for tipping ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -gnunet-ecc -reserve key +:keywords: gnunet-ecc +:keywords: reserve key To tip users, you first need to create a reserve. A reserve is a pool of money held in escrow at the Taler exchange. This is the source of the funds for the tips. Tipping will fail (resulting in disappointed @@ -992,8 +992,8 @@ Now you can (re)start the backend with the new configuration. Fund the reserve ~~~~~~~~~~~~~~~~ -reserve -close +:keywords: reserve +:keywords: close To fund the reserve, you must first extract the public key from “tip.priv”: -- cgit v1.2.3 From a42a6a69879208f8960384e4ecf2426bc467e67e Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 4 Apr 2020 17:22:51 +0200 Subject: update docs --- core/api-exchange.rst | 2 +- core/api-merchant.rst | 37 +++++++++++++++++++++++++++++++++++++ taler-merchant-manual.rst | 23 ++++++++++++++++++++++- 3 files changed, 60 insertions(+), 2 deletions(-) diff --git a/core/api-exchange.rst b/core/api-exchange.rst index c6186284..536458ec 100644 --- a/core/api-exchange.rst +++ b/core/api-exchange.rst @@ -96,7 +96,7 @@ possibly by using HTTPS. .. ts:def:: ExchangeKeysResponse interface ExchangeKeysResponse { - // libtool-style representation of the Taler protocol version, see + // libtool-style representation of the Exchange protocol version, see // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning // The format is "current:revision:age". version: string; diff --git a/core/api-merchant.rst b/core/api-merchant.rst index b9dac413..e60ea8b0 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -25,6 +25,22 @@ Merchant Backend API .. contents:: Table of Contents + +-------------------- +Compatibility Checks +-------------------- + +.. http:get:: /config + + Return the protocol version and currency supported by this merchant backend. + This endpoint is deprecated, clients should migrate to the (identical) + /public/version API. + + **Response:** + + :status 200 OK: + The exchange accepted all of the coins. The body is a `VersionResponse`. + ------------------ Receiving Payments ------------------ @@ -973,6 +989,27 @@ The ``/public/*`` endpoints are publicly exposed on the internet and accessed both by the user's browser and their wallet. +.. http:get:: /public/config + + Return the protocol version and currency supported by this merchant backend. + + **Response:** + + :status 200 OK: + The exchange accepted all of the coins. The body is a `VersionResponse`. + + .. ts:def:: VersionResponse + + interface VersionResponse { + // libtool-style representation of the Merchant protocol version, see + // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning + // The format is "current:revision:age". + version: string; + + // Currency supported by this backend. + currency: string; + } + .. http:post:: /public/pay Pay for a proposal by giving a deposit permission for coins. Typically used by diff --git a/taler-merchant-manual.rst b/taler-merchant-manual.rst index 771a1a0e..825c7149 100644 --- a/taler-merchant-manual.rst +++ b/taler-merchant-manual.rst @@ -52,6 +52,7 @@ Architecture overview :keywords: crypto-currency :keywords: KUDOS + Taler is a pure payment system, not a new crypto-currency. As such, it operates in a traditional banking context. In particular, this means that in order to receive funds via Taler, the merchant must have a @@ -225,6 +226,7 @@ Installing libgnunetutil ~~~~~~~~~~~~~~~~~~~~~~~~ :keywords: GNUnet + Before you install libgnunetutil, you must download and install the dependencies mentioned in the previous section, otherwise the build may succeed but fail to export some of the tooling required by Taler. @@ -251,6 +253,7 @@ Installing the GNU Taler exchange ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :keywords: exchange + After installing GNUnet, you can download and install the exchange as follows: @@ -277,6 +280,7 @@ Installing the GNU Taler merchant backend ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :keywords: backend + The following steps assume all dependencies are installed. Use the following commands to download and install the merchant backend: @@ -305,6 +309,7 @@ Installing Taler on Debian GNU/Linux :keywords: Wheezy :keywords: Debian + Debian wheezy is too old and lacks most of the packages required. On Debian jessie, only GNU libmicrohttpd needs to be compiled from @@ -361,6 +366,7 @@ How to configure the merchant’s backend :keywords: taler-config :keywords: taler.conf + The installation already provides reasonable defaults for most of the configuration options. However, some must be provided, in particular the database account and bank account that the backend should use. By @@ -386,6 +392,7 @@ Service address :keywords: UNIX domain socket :keywords: TCP + :: [MERCHANT]/SERVE = TCP | UNIX @@ -418,6 +425,7 @@ Currency :keywords: currency :keywords: KUDOS + :: [TALER]/CURRENCY @@ -432,6 +440,7 @@ Currency Database :keywords: DBMS + In principle is possible for the backend to support different DBMSs. The option @@ -452,6 +461,7 @@ Database [merchantdb-postgres]/config :keywords: Postgres + This option specifies a postgres access path using the format ``postgres:///$DBNAME``, where ``$DBNAME`` is the name of the Postgres database you want to use. Suppose ``$USER`` is the name of @@ -482,6 +492,7 @@ Database Exchange :keywords: exchange + To add an exchange to the list of trusted payment service providers, you create a section with a name that starts with “exchange-”. In that section, the following options need to be configured: @@ -511,6 +522,7 @@ Exchange Instances :keywords: instance + The backend allows the user to run multiple instances of shops with distinct business entities against a single backend. Each instance uses its own bank accounts and key for signing contracts. It is @@ -537,6 +549,7 @@ Instances Accounts :keywords: wire format + In order to receive payments, the merchant backend needs to communicate bank account details to the exchange. For this, the configuration must include one or more sections named “ACCOUNT-name” @@ -587,6 +600,7 @@ Sample backend configuration ---------------------------- :keywords: configuration + The following is an example for a complete backend configuration: :: @@ -637,7 +651,8 @@ Launching the backend --------------------- :keywords: backend -taler-merchant-httpd +:keywords: taler-merchant-httpd + Assuming you have configured everything correctly, you can launch the merchant backend using: @@ -777,6 +792,7 @@ Configuration format -------------------- :keywords: configuration + In Taler realm, any component obeys to the same pattern to get configuration values. According to this pattern, once the component has been installed, the installation deploys default values in @@ -850,6 +866,7 @@ Using taler-config ------------------ :keywords: taler-config + The tool ``taler-config`` can be used to extract or manipulate configuration values; however, the configuration use the well-known INI file format and can also be edited by hand. @@ -905,6 +922,7 @@ Merchant key management :keywords: merchant key :keywords: KEYFILE + The option “KEYFILE” in the section “INSTANCE-default” specifies the path to the instance’s private key. You do not need to create a key manually, the backend will generate it automatically if it is missing. @@ -923,6 +941,7 @@ Tipping visitors ---------------- :keywords: tipping + Taler can also be used to tip Web site visitors. For example, you may be running an online survey, and you want to reward those people that have dutifully completed the survey. If they have installed a Taler wallet, @@ -938,6 +957,7 @@ Configure a reserve and exchange for tipping :keywords: gnunet-ecc :keywords: reserve key + To tip users, you first need to create a reserve. A reserve is a pool of money held in escrow at the Taler exchange. This is the source of the funds for the tips. Tipping will fail (resulting in disappointed @@ -994,6 +1014,7 @@ Fund the reserve :keywords: reserve :keywords: close + To fund the reserve, you must first extract the public key from “tip.priv”: -- cgit v1.2.3 From 59e33c8e609da4c6a8784348bc7b1952ccba8bbb Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Mon, 6 Apr 2020 15:48:09 +0200 Subject: detail --- core/api-wire.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/api-wire.rst b/core/api-wire.rst index 98e07419..b5f49355 100644 --- a/core/api-wire.rst +++ b/core/api-wire.rst @@ -95,7 +95,7 @@ Making Transactions exchange_base_url: string; // Wire transfer identifier chosen by the exchange, - // used by the merchant to identify the Taler order + // used by the merchant to identify the Taler order(s) // associated with this wire transfer. wtid: ShortHashCode; -- cgit v1.2.3 From 1f9863d51c23ee39aa27702dc38715149a6e76f9 Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Mon, 6 Apr 2020 17:11:40 +0200 Subject: address typo --- core/api-wire.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/api-wire.rst b/core/api-wire.rst index b5f49355..94956ce2 100644 --- a/core/api-wire.rst +++ b/core/api-wire.rst @@ -45,7 +45,7 @@ Making Transactions 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`. + **Request:** The body of this request must have the format of a `TransferRequest`. **Response:** @@ -79,9 +79,9 @@ Making Transactions } - .. ts:def:: TransactionRequest + .. ts:def:: TransferRequest - interface TransactionRequest { + interface TransferRequest { // Nonce to make the request idempotent. Requests with the same // transaction_uid that differ in any of the other fields // are rejected. -- cgit v1.2.3 From c229493178ef9a1106db76154bbe38d78182f70b Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Mon, 6 Apr 2020 17:21:19 +0200 Subject: typo --- core/api-wire.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/api-wire.rst b/core/api-wire.rst index 94956ce2..fcbd4a5b 100644 --- a/core/api-wire.rst +++ b/core/api-wire.rst @@ -114,7 +114,7 @@ Querying the transaction history Return a list of transactions made from or to the exchange. Incoming transactions must contain a valid reserve public key. If a bank - transaction does not confirm to the right syntax, the wire gatway must not + transaction does not conform to the right syntax, the wire gatway must not report it to the exchange, and sent funds back to the sender if possible. The bank account of the exchange is determined via the base URL and/or the -- cgit v1.2.3 From a6d18f905c15ec8e4ccddaaff04dc91fb177235b Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Mon, 6 Apr 2020 17:22:17 +0200 Subject: typo --- core/api-wire.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/api-wire.rst b/core/api-wire.rst index fcbd4a5b..c7a443c7 100644 --- a/core/api-wire.rst +++ b/core/api-wire.rst @@ -115,7 +115,7 @@ Querying the transaction history Incoming transactions must contain a valid reserve public key. If a bank transaction does not conform to the right syntax, the wire gatway must not - report it to the exchange, and sent funds back to the sender if possible. + report it to the exchange, and send funds back to the sender if possible. The bank account of the exchange is determined via the base URL and/or the user name in the ``Authorization`` header. In fact the transaction history -- cgit v1.2.3 From 308f3a715676c682b52a7051931d8ce39220f2c2 Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Mon, 6 Apr 2020 17:32:13 +0200 Subject: typo --- core/api-wire.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/api-wire.rst b/core/api-wire.rst index c7a443c7..fee78890 100644 --- a/core/api-wire.rst +++ b/core/api-wire.rst @@ -29,7 +29,7 @@ LibEuFin (work in progress). Authentication -------------- -The bank library authenticates requests to the wire gatway via +The bank library authenticates requests to the wire gateway via `HTTP basic auth `_. ------------------- @@ -114,7 +114,7 @@ Querying the transaction history Return a list of transactions made from or to the exchange. Incoming transactions must contain a valid reserve public key. If a bank - transaction does not conform to the right syntax, the wire gatway must not + transaction does not conform to the right syntax, the wire gateway must not report it to the exchange, and send funds back to the sender if possible. The bank account of the exchange is determined via the base URL and/or the -- cgit v1.2.3 From 8c1b31b8c5222544659507e00350fa5312e2be11 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 7 Apr 2020 18:43:14 +0200 Subject: correctly document /refund (increase) API, see #6129: --- core/api-merchant.rst | 82 +++++++++++++++++++++------------------------------ 1 file changed, 34 insertions(+), 48 deletions(-) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index e60ea8b0..46c5dcc4 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -26,20 +26,6 @@ Merchant Backend API .. contents:: Table of Contents --------------------- -Compatibility Checks --------------------- - -.. http:get:: /config - - Return the protocol version and currency supported by this merchant backend. - This endpoint is deprecated, clients should migrate to the (identical) - /public/version API. - - **Response:** - - :status 200 OK: - The exchange accepted all of the coins. The body is a `VersionResponse`. ------------------ Receiving Payments @@ -161,7 +147,7 @@ Giving Refunds .. http:post:: /refund Increase the refund amount associated with a given order. The user should be - redirected to the ``refund_redirect_url`` to trigger refund processing in the wallet. + redirected to the ``taler_refund_url`` to trigger refund processing in the wallet. **Request** @@ -171,8 +157,10 @@ Giving Refunds :status 200 OK: The refund amount has been increased, the backend responds with a `MerchantRefundResponse` - :status 400 Bad request: - The refund amount is not consistent: it is not bigger than the previous one. + :status 404 Not found: + The order is unknown to the merchant + :status 409 Conflict: + The refund amount exceeds the amount originally paid .. ts:def:: RefundRequest @@ -190,39 +178,13 @@ Giving Refunds .. ts:def:: MerchantRefundResponse interface MerchantRefundResponse { - // Public key of the merchant - merchant_pub: string; - - - // Contract terms hash of the contract that - // is being refunded. - h_contract_terms: string; - - // The signed refund permissions, to be sent to the exchange. - refund_permissions: MerchantRefundPermission[]; - - // URL (handled by the backend) that will - // trigger refund processing in the browser/wallet - refund_redirect_url: string; - } - - .. ts:def:: MerchantRefundPermission - interface MerchantRefundPermission { - // Amount to be refunded. - refund_amount: Amount; - - // Fee for the refund. - refund_fee: Amount; - - // Public key of the coin being refunded. - coin_pub: string; - - // Refund transaction ID between merchant and exchange. - rtransaction_id: number; + // Hash of the contract terms of the contract that is being refunded. + h_contract_terms: HashCode; - // Signature made by the merchant over the refund permission. - merchant_sig: string; + // URL (handled by the backend) that the wallet should access to + // trigger refund processing. + taler_refund_url: string; } @@ -1008,8 +970,32 @@ both by the user's browser and their wallet. // Currency supported by this backend. currency: string; + + // optional array with information about the instances running at this backend + instances: InstanceInformation[]; + } + + .. ts:def:: InstanceInformation + + interface InstanceInformation { + + // Human-readable legal business name served by this instance + name: string; + + // Base URL of the instance. Can be of the form "/PizzaShop/" or + // a fully qualified URL (i.e. "https://backend.example.com/PizzaShop/"). + instance_baseurl: string; + + // Public key of the merchant/instance, in Crockford Base32 encoding. + merchant_pub: EddsaPublicKey; + + // Base URL of the exchange this instance uses for tipping. + // Optional, only present if the instance supports tipping. + tipping_exchange_baseurl?: string; + } + .. http:post:: /public/pay Pay for a proposal by giving a deposit permission for coins. Typically used by -- cgit v1.2.3 From 3cba35cb301c527edd4e6d8ccc39be9a400c3147 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 8 Apr 2020 22:21:08 +0530 Subject: design document: new browser integration --- design-documents/000-template.rst | 4 + design-documents/001-new-browser-integration.rst | 179 +++++++++++++++++++++++ design-documents/index.rst | 13 ++ index.rst | 1 + 4 files changed, 197 insertions(+) create mode 100644 design-documents/000-template.rst create mode 100644 design-documents/001-new-browser-integration.rst create mode 100644 design-documents/index.rst diff --git a/design-documents/000-template.rst b/design-documents/000-template.rst new file mode 100644 index 00000000..c969f862 --- /dev/null +++ b/design-documents/000-template.rst @@ -0,0 +1,4 @@ +Template +######## + +FIXME: define template diff --git a/design-documents/001-new-browser-integration.rst b/design-documents/001-new-browser-integration.rst new file mode 100644 index 00000000..1601f716 --- /dev/null +++ b/design-documents/001-new-browser-integration.rst @@ -0,0 +1,179 @@ +Design Doc 001: New Browser Integration +####################################### + +.. note:: + + This design document is currently a draft, it + does not reflect any implementation decisions yet. + +Summary +======= + +A new and improved mechanism for the integration of GNU Taler wallets with web +browsers is proposed. The mechanism is meant for browsers that support the +WebExtension API, but do not have native support for GNU Taler. + +The new approach allows the wallet extension to be installed without +excessive, "scary" permissions, while being simpler and still flexible. + + +Motivation +========== + +The current browser integration of the GNU Taler wallet relies heavily being +able to hook into various browser mechanisms via the following mechanisms: + +* A blocking ``webRequest`` handler that is run for every request the browser + makes, and looks at the status code and the presence of a "``Taler:``" HTTP header. +* A content script that's injected on every (!) page, which injects CSS (for + wallet presence detection) and JavaScript listeners into the page. The + injection is opt-in via a "data-taler" tag on the root html element. + +This has multiple problems: + +* It requires excessive permissions on **all** Websites. This is scary for us (in case we mess up) + and for users. It also slows down the publication of the extension on extension stores. +* We have not measured the performance implications, but our JavaScript code is executed for every + single request the browser is making. +* The CSS-based wallet detection integration is not very flexible. Only being able + to show/hide some element when the wallet is detected / not detected might not be + the optimal thing to do when we now have mobile wallets. + + +Requirements +============ + +* The new browser integration should require as few permissions as possible. + In particular, the wallet may not require "broad host" permissions. +* Fingerprinting via this API should be minimized. +* It must be possible for Websites to interact with the wallet without using JavaScript. +* Single Page Apps (using JavaScript) should be able to interact the wallet without + requiring a browser navigation. + + +Proposed Solution +================= + +We first have to accept the fundamental limitation that a WebExtension is not +able to read a page's HTTP request headers without intrusive permissions. +Instead, we need to rely on the content and/or URL of the fallback page that is +being rendered by the merchant backend. + +To be compatible with mobile wallets, merchants and banks **must** always render a fallback +page that includes the same ``taler://`` URI. + +Manual Triggering +----------------- + +Using the only the ``activeTab`` permission, we can access a page's content +*while and only while* the user is opening the popup (or a page action). +The extension should look at the DOM and search for ``taler://`` links. +If such a link as been found, the popup should display an appropriate +dialog to the user (e.g. "Pay with GNU Taler on the current page."). + +Using manual triggering is not the best user experience, but works on every Website +that displays a ``taler://`` link. + +.. note:: + + Using additional permissions, we could also offer: + + * A context ("right click") menu for ``taler://pay`` links + * A declarative pageAction, i.e. an additional clickable icon that shows up + on the right side of the address bar. Clicking it would lead to directly + processing the ``taler://`` link. + + It's not clear if this improves the user experience though. + + +Fragment-based Triggering +------------------------- + +This mechanism improves the user experience, but requires extra support from merchants +and broader permissions, namely the ``tabs`` permission. This permission +is shown as "can read your history", which sounds relatively intrusive. +We might decide to make this mechanism opt-in. + +The extension uses the ``tabs`` permission to listen to changes to the +URL displayed in the currently active tab. It then parses the fragment, +which can contain a ``taler://`` URI, such as: + +.. code:: none + + https://shop.taler.net/checkout#taler://pay/backend.shop.taler.net/-/-/2020.099-03C5F644XCNMR + +The fragment is processed the same way a "Taler: " header is processed. +For examle, a ``taler://pay/...`` fragment navigates to an in-wallet page +and shows a payment request to the user. + + +Fragment-based detection +------------------------ + +To support fragment-based detection of the wallet, a special +``taler://check-presence/${redir}`` URL can be used to cause a navigation to +``${redir}`` if the wallet is installed. The redirect URL can be absolute or +relative to the current page and can contain a fragment. + +For example: + +.. code:: none + + https://shop.taler.net/checkout#taler://check-presence/taler-installed + + -> (when wallet installed) + + https://shop.taler.net/taler-installed + + +To preserve correct browser history navigation, the wallet does not initiate the redirect if +the tab's URL changes from ``${redir}`` back to the page with the ``check-presence`` fragment. + + +Asynchronous API +---------------- + +The fragment-based triggering does not work well on single-page apps: It +interferes with the SPA's routing, as it requires a change to the navigation +location's fragment. + +The only way to communicate with a WebExtension is by knowing its extension ID. +However, we want to allow users to build their own version of the WebExtension, +and extensions are assigned different IDs in different browsers. We thus need +a mechanism to obtain the wallet extension ID in order to asynchronously communicate +with it. + +To allow the Website to obtain this extension ID, we can extend the redirection URL +of the ``taler://check-presence`` fragment to allow a placeholder for the extension ID. + +.. code:: none + + https://shop.taler.net/checkout#taler://check-presence/#taler-installed-${extid} + + -> (when wallet installed) + + https://shop.taler.net/checkout#taler-installed-12345ASDFG + +.. warning:: + + This allows fingerprinting, and thus should be an opt-in feature. + The wallet could also ask the user every time to allow a page to obtain the + +.. note:: + + To avoid navigating away from an SPA to find out the extension ID, the SPA + can open a new tab/window and communicate the updated extension ID back to + original SPA page. + + +Alternatives +============ + +* manual copy&paste of ``taler://`` URIs :-) +* integration of GNU Taler into all major browsers :-) +* convincing Google and/or Mozilla to provide better support + for reacting to a limited subset of request headers in + a declarative way +* convince Google and/or Mozilla to implement a general mechanism + where extensions can offer a "service" that websites can then + connect to without knowing some particular extension ID. diff --git a/design-documents/index.rst b/design-documents/index.rst new file mode 100644 index 00000000..3dc229ba --- /dev/null +++ b/design-documents/index.rst @@ -0,0 +1,13 @@ +Design Documents +################ + +This is a collection of design documents related to GNU Taler. +The goal of these documents is to discuss facilitate discussion around +new features while keeping track of the evolution of the whole system +and protocol. + +.. toctree:: + :glob: + + 000-template + 001-new-browser-integration diff --git a/index.rst b/index.rst index ee3c8b8c..2ead8f27 100644 --- a/index.rst +++ b/index.rst @@ -61,6 +61,7 @@ Documentation Overview taler-backoffice-manual taler-auditor-manual developers-manual.rst + design-documents/index anastasis libeufin/index global-licensing -- cgit v1.2.3 From 078d8a11daec59f2df58b38c36f2616b51d2df77 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 8 Apr 2020 22:31:48 +0530 Subject: elaborate on async API --- design-documents/001-new-browser-integration.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/design-documents/001-new-browser-integration.rst b/design-documents/001-new-browser-integration.rst index 1601f716..c53ae857 100644 --- a/design-documents/001-new-browser-integration.rst +++ b/design-documents/001-new-browser-integration.rst @@ -165,6 +165,9 @@ of the ``taler://check-presence`` fragment to allow a placeholder for the extens can open a new tab/window and communicate the updated extension ID back to original SPA page. +Once the Website has obtained the extension ID, it can use the ``runtime.connect()`` function +to establish a communication channel to the extension. + Alternatives ============ @@ -177,3 +180,10 @@ Alternatives * convince Google and/or Mozilla to implement a general mechanism where extensions can offer a "service" that websites can then connect to without knowing some particular extension ID. + +Drawbacks +========= + +* Firefox currently does not support messages from a website to an extension, and currently + cannot support the asynchronous wallet API. + There is a bug open for this issue: https://bugzilla.mozilla.org/show_bug.cgi?id=1319168 -- cgit v1.2.3 From fc756b9d67fa5c87ce40d565d12b9f4ddd981e89 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 8 Apr 2020 23:08:33 +0530 Subject: URI handler --- design-documents/001-new-browser-integration.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/design-documents/001-new-browser-integration.rst b/design-documents/001-new-browser-integration.rst index c53ae857..420d67d9 100644 --- a/design-documents/001-new-browser-integration.rst +++ b/design-documents/001-new-browser-integration.rst @@ -180,6 +180,8 @@ Alternatives * convince Google and/or Mozilla to implement a general mechanism where extensions can offer a "service" that websites can then connect to without knowing some particular extension ID. +* convince Google and/or Mozilla to add better support for + registering URI schemes from a WebExtension Drawbacks ========= -- cgit v1.2.3 From 8b790eb4356a8b70f00a37f160c9a8bcfc7d4dfd Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 8 Apr 2020 23:10:37 +0530 Subject: comment --- design-documents/001-new-browser-integration.rst | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/design-documents/001-new-browser-integration.rst b/design-documents/001-new-browser-integration.rst index 420d67d9..f436a4f7 100644 --- a/design-documents/001-new-browser-integration.rst +++ b/design-documents/001-new-browser-integration.rst @@ -172,16 +172,19 @@ to establish a communication channel to the extension. Alternatives ============ -* manual copy&paste of ``taler://`` URIs :-) -* integration of GNU Taler into all major browsers :-) -* convincing Google and/or Mozilla to provide better support +* Manual copy&paste of ``taler://`` URIs :-) +* Integration of GNU Taler into all major browsers :-) +* Convincing Google and/or Mozilla to provide better support for reacting to a limited subset of request headers in a declarative way -* convince Google and/or Mozilla to implement a general mechanism +* Convince Google and/or Mozilla to implement a general mechanism where extensions can offer a "service" that websites can then connect to without knowing some particular extension ID. -* convince Google and/or Mozilla to add better support for - registering URI schemes from a WebExtension +* Convince Google and/or Mozilla to add better support for + registering URI schemes from a WebExtension, so that + we can register a handler for ``taler://``. For a better user experience, + there should also be some way to check whether some particular URI scheme + has a handler. Drawbacks ========= -- cgit v1.2.3 From a8f063a61ebb23ae7a58156e79c81646dddfb936 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Thu, 9 Apr 2020 14:27:36 +0530 Subject: wallet exchange management --- .../002-wallet-exchange-management.rst | 359 +++++++++++++++++++++ design-documents/index.rst | 1 + 2 files changed, 360 insertions(+) create mode 100644 design-documents/002-wallet-exchange-management.rst diff --git a/design-documents/002-wallet-exchange-management.rst b/design-documents/002-wallet-exchange-management.rst new file mode 100644 index 00000000..86d56e56 --- /dev/null +++ b/design-documents/002-wallet-exchange-management.rst @@ -0,0 +1,359 @@ +Design Doc 002: Wallet Exchange Management +########################################## + +.. note:: + + This design document is currently a draft, it + does not reflect any implementation decisions yet. + +Summary +======= + +This document presents the requirements and proposed interface for an API that +wallet-core exposes (to clients such as the CLI, WebExtension, Android Wallet) +to manage exchanges known to and used by the wallet. + + +Motivation +========== + +There currently is no documented API for this functionality. The API that the +WebExtension API uses doesn't support all required functionality and exposes +the internal DB storage format. + + +Background and Requirements +=========================== + +The wallet maintains a list of known exchanges. For each exchange in this +list, the wallet regularly makes network queries to fetch updated information +about the exchange's cryptographic key material and fee structure. + +Additionally, the wallet maintains a list of *trusted auditors*. Auditors +certify that they audit a (sub)set of denominations offered by the exchange. + +When an exchange is marked as *directly trusted*, the wallet can use it +for withdrawals independent of how the exchange is audited. Otherwise, +a withdrawal can only proceed if an adequate set of denominations is +audited by a trusted auditor. + +An exchange might only be known the wallet temporarily. For example, +the wallet UI may allow the user to review the fee structure of an +exchange before the wallet is permanently added to the wallet. +Once a an exchange is either (a) marked as trusted or (b) used for a +withdrawal operation, it is marked as permanent. + +Exchanges that are not permanent will be automatically be removed +("garbage-collected") by the wallet after some time. + +Exchanges also expose their terms of service (ToS) document. +Before withdrawing, the wallet must ensure that the user +has reviewed and accepted the current version of this ToS document. + +Exchange Management During Withdrawal +------------------------------------- + +The functions to list / view exchanges can either be used in the context of +some exchange management activity or in the context of a withdrawal. In the +context of a withdrawal, additional filtering must be applied, as not every +exchange is compatible with every withdrawal process. Additionally, the list +of exchanges might contain additional details pertaining to this particular +withdrawal process. + +An exchange is considered *compatible* if it accepts wire transfers with a wire +method that matches the one of the withdrawal *and* the current exchange +protocol version of the exchange is compatible with the exchange protocol +version of the wallet. + +During the withdrawal process, the bank can also suggest an exchange. Unless +the exchange is already known to the wallet, this exchange will be added +non-permanently to the wallet. The bank-suggested will only be selected by +default if no other trusted exchange compatible with the withdrawal process is +known to the wallet. + +Otherwise, the exchange selected by default will be the exchange that has most +recently been used for a withdrawal and is compatible with the current withdrawal. + + +Open Questions +-------------- + +If the user reviews a **new** exchange during withdrawal +but then does not decide to use it, will this exchange be permanent? + +Pro: + +* Staying permanently in the list might help when comparing multiple exchanges + +Con: + +* It clutters the list of exchanges, especially as we're not planning + to have a mechanism to remove exchanges. + +=> Maybe non-permanent exchanges can be "sticky" to some particular +withdrawal session? + + +Proposed Solution +================= + +We will add the following functions (invoked over IPC with wallet-core). + +queryExchangeInfo +----------------- + +This function will query information about an exchange based on the base URL +of the exchange. If the exchange is not known yet to the wallet, it will be +added non-permanently. + +Request: + +.. code:: ts + + interface QueryExchangeInfoRequest { + // If given, return error description if the exchange is + // not compatible with this withdrawal operation. + talerWithdrawUri?: string; + + // Exchange base URL to use for the query. + exchangeBaseUrl: string; + + // If true, the query already returns a result even if + // /wire and denomination signatures weren't processed yet + partial: boolean; + } + +Response: + +.. code:: ts + + interface QueryExchangeInfoResponse { + exchangeBaseUrl: string; + + // Master public key + exchangePub: string; + + trustedDirectly: boolean; + + // The "reasonable-ness" of the exchange's fees. + feeStructureSummary: FeeStructureSummary | undefined; + + // Detailled info for each individual denomination + denominations: ExchangeDenomination[]; + + // Currency of the exchange. + currency: string; + + // Last observed protocol version range of the exchange + protocolVersionRange: string; + + // Is this exchange either trusted directly or in use? + permanent: boolean; + + // Only present if the last exchange information update + // failed. Same error as the corresponding pending operation. + lastError?: OperationError; + + wireInfo: ExchangeWireInfo; + + // Auditing state for each auditor. + auditingState: ExchangeAuditingState[]; + + // Do we trust an auditor that sufficiently audits + // this exchange's denominations? + trustedViaAuditor: boolean; + + currentTosVersion: string; + acceptedTosVersion: string; + + withdrawalRelatedInfo?: { + // Can the user accept the withdrawal directly? + // This field is redundant and derivable from other fields. + acceptable: boolean; + + recommendedByBank: boolean; + + // Is this exchange the default exchange for this withdrawal? + isDefault: boolean; + + // The "reasonable-ness" of the exchange's fees, in context + // of the withdrawn amount. + feeStructureSummaryForAmount: FeeStructureSummaryForAmount; + }; + } + + export interface ExchangeWireInfo { + feesForType: { [wireMethod: string]: WireFee[] }; + accounts: { paytoUri: string }[]; + } + + interface ExchangeAuditingState { + auditorName: string; + auditorBaseUrl: string; + auditorPub: string; + + // Is the auditor already trusted by the wallet? + trustedByWallet: boolean; + + // Does the auditor audit some reasonable set of + // denominations of the exchange? + // If this is false, at least some warning should be shown. + auditedDenominationsReasonable: boolean; + } + + + interface FeeStructureSummary { + // Does the fee structure fulfill our basic reasonableness + // requirements? + reasonable: boolean; + + // Lower range of amounts that this exchange can + // deal with efficiently. + smallAmount: Amount; + + // Upper range of amounts that this exchange can deal + // with efficiently. + bigAmount: Amount; + + // Rest to be specified later + // [ ... ] + } + + +getExchangeTos +-------------- + +Request: + +.. code:: ts + + interface GetExchangeTosRequest { + exchangeBaseUrl: string; + } + + +Response: + +.. code:: ts + + interface GetTosResponse { + // Version of the exchange ToS (corresponds to tos ETag) + version: string; + + // Text of the exchange ToS, with (optional) markdown markup. + tosMarkdownText: string; + } + +listExchanges +------------- + +List exchanges known to the wallet. Either lists all exchanges, or exchanges +related to a withdrawal process. + +Request: + +.. code:: ts + + interface ExchangeListRequest { + // If given, only return exchanges that + // match the currency of this withdrawal + // process. + talerWithdrawUri?: string; + } + +Response: + +.. code:: ts + + interface ExchangeListRespose { + // Only returned in the context of withdrawals. + // The base URL of the exchange that should + // be considered the default for the withdrawal. + withdrawalDefaultExchangeBaseUrl?: string; + + exchanges: { + exchangeBaseUrl: string; + + // Incompatible exchanges are also returned, + // as otherwise users might wonder why their expected + // exchange is not there. + compatibility: "compatible" | + "incompatible-version" | "incompatible-wire"; + + // Currency of the exchange. + currency: string; + + // Does the wallet directly trust this exchange? + trustedDirectly: boolean; + + // Is this exchange either trusted directly or in use? + permanent: boolean; + + // This information is only returned if it's + // already available to us, as the list query + // must be fast! + trustedViaAuditor: boolean | undefined; + + // The "reasonable-ness" of the exchange's fees. + // Only provided if available (if we've already queried + // and checked this exchange before). + feeStructureSummary: FeeStructureSummary | undefined; + + // Did the user accept the current version of the exchange's ToS? + currentTosAccepted: boolean; + + withdrawalRelatedInfo?: { + // Can the user accept the withdrawal directly? + // This field is redundant and derivable from other fields. + acceptable: boolean; + + recommendedByBank: boolean; + + // Is this exchange the default exchange for this withdrawal? + isDefault: boolean; + + // The "reasonable-ness" of the exchange's fees, in context + // of the withdrawn amount. + // Only provided if available (if we've already queried + // and checked this exchange before). + feeStructureSummaryForAmount: FeeStructureSummaryForAmount | undefined; + }; + }[]; + } + + +setExchangeTrust +---------------- + +Request: + +.. code:: ts + + interface SetExchangeTrustRequest { + exchangeBaseUrl: string; + + trusted: boolean; + } + +The response is an empty object or an error response. + +setExchangeTosAccepted +---------------------- + +Request: + +.. code:: ts + + interface SetExchangeTosAccepted { + exchangeBaseUrl: string; + } + +The response is an empty object or an error response. + + +Alternatives +============ + +* The UI could directly access the wallet's DB for more flexible access to the + required data. But this would make the UI less robust against changes in wallet-core. + diff --git a/design-documents/index.rst b/design-documents/index.rst index 3dc229ba..609cc2d0 100644 --- a/design-documents/index.rst +++ b/design-documents/index.rst @@ -11,3 +11,4 @@ and protocol. 000-template 001-new-browser-integration + 002-wallet-exchange-management -- cgit v1.2.3 From 874e88f0601d3b41205c62ab009e370b33dfdc80 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Thu, 9 Apr 2020 14:30:43 +0530 Subject: fees --- design-documents/002-wallet-exchange-management.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/design-documents/002-wallet-exchange-management.rst b/design-documents/002-wallet-exchange-management.rst index 86d56e56..dd8b3c27 100644 --- a/design-documents/002-wallet-exchange-management.rst +++ b/design-documents/002-wallet-exchange-management.rst @@ -176,9 +176,10 @@ Response: // Is this exchange the default exchange for this withdrawal? isDefault: boolean; - // The "reasonable-ness" of the exchange's fees, in context - // of the withdrawn amount. - feeStructureSummaryForAmount: FeeStructureSummaryForAmount; + withdrawalWithdrawnAmount: Amount; + withdrawalCreditAmount: Amount; + withdrawalFeeAmount: Amount; + withdrawalOverheadAmount: Amount; }; } @@ -312,11 +313,10 @@ Response: // Is this exchange the default exchange for this withdrawal? isDefault: boolean; - // The "reasonable-ness" of the exchange's fees, in context - // of the withdrawn amount. - // Only provided if available (if we've already queried - // and checked this exchange before). - feeStructureSummaryForAmount: FeeStructureSummaryForAmount | undefined; + withdrawalWithdrawnAmount: Amount; + withdrawalCreditAmount: Amount; + withdrawalFeeAmount: Amount; + withdrawalOverheadAmount: Amount; }; }[]; } -- cgit v1.2.3 From ff0d9a363abfcaab8d4f0f83085c6d0d92dcfcf4 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Thu, 9 Apr 2020 14:36:11 +0530 Subject: add last withdrawal timestamp --- design-documents/002-wallet-exchange-management.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/design-documents/002-wallet-exchange-management.rst b/design-documents/002-wallet-exchange-management.rst index dd8b3c27..b3deee06 100644 --- a/design-documents/002-wallet-exchange-management.rst +++ b/design-documents/002-wallet-exchange-management.rst @@ -166,6 +166,9 @@ Response: currentTosVersion: string; acceptedTosVersion: string; + // When (if so) was this exchange last used for withdrawal? + lastUsedForWithdrawal: Timestamp | undefined; + withdrawalRelatedInfo?: { // Can the user accept the withdrawal directly? // This field is redundant and derivable from other fields. @@ -303,6 +306,9 @@ Response: // Did the user accept the current version of the exchange's ToS? currentTosAccepted: boolean; + // When (if so) was this exchange last used for withdrawal? + lastUsedForWithdrawal: Timestamp | undefined; + withdrawalRelatedInfo?: { // Can the user accept the withdrawal directly? // This field is redundant and derivable from other fields. -- cgit v1.2.3 From 822136314dce1c663a403bca04f6a027f7812dc8 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 9 Apr 2020 11:46:36 +0200 Subject: document auditor failure mode related to #6164 --- taler-auditor-manual.rst | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/taler-auditor-manual.rst b/taler-auditor-manual.rst index ec6eba25..82b206ec 100644 --- a/taler-auditor-manual.rst +++ b/taler-auditor-manual.rst @@ -509,7 +509,7 @@ historic transactions. Hence this should not be done in a production system. .. _Revocations: Revocations -~~~~~~~~~~~ +----------- When an auditor detects that the private key of a denomination key pair has been compromised, one important step is to revoke the denomination key. The @@ -524,6 +524,36 @@ additional information to demonstrate that these coins were not forged from the compromised private key but obtained via a legitimate withdraw operation. +Failures +-------- + +Most audit failures are handled by the auditor's regular reporting functionality, +creating a (hopefully descriptive) PDF report detailing the problems found. + +However, there is one category of errors where this is not possible, which evolves +around arithmetic overflows for amounts. Taler's specification limits amount +values to at most 2^52. If, during the auditor's calculations, amounts are +encountered that exceed this threshold, the auditor will not generate a regular +report, but instead write a log statement explaining where the problem happened +and exit with a status code of *42*. + +The most common expected case when this happens is a corrupted database. This +could be because the exchange is actively malicious, or more likely due to +some data corruption. The audit cannot continue until the corruption has been +addressed. If it is not possible to restore a fully 'correct' version of the +database, the suggestion is to replace the corrupted (and likely very large) +amounts with zero (Note: this does not apply to the value of denominations or +fees, here it is crucial that the correct amounts are restored). While an +amount of zero would be incorrect, the auditing logic should be able to do its +calculations with zero instead. After patching the database, the audit can +be restarted. A full reset is not required, as the audit transaction is aborted +when the auditor exits with code *42*. After restarting, the resulting audit +report is likely to indicates errors relating to the corrupted fields (such as +invalid signatures, arithmetic errors by the exchange, etc.), but at least the +loss/gain calculations will be meaningful and actually indicative of the scope +of the error created by the corrupted data. + + Auditor implementation guide ============================ -- cgit v1.2.3 From b93b0b34ffaae3e30d13b0a134b7b2d958d97288 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 9 Apr 2020 23:42:57 +0200 Subject: specify refund API for wallets as per #5299 --- core/api-merchant.rst | 95 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 83 insertions(+), 12 deletions(-) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index 46c5dcc4..80d3b4f6 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -215,17 +215,17 @@ Giving Customer Tips the instance was never configured for tipping. :status 424 Failed Dependency: We are unable to process the request because of a problem with the exchange. - Likely returned with an "exchange-code" in addition to a "code" and - an "exchange-http-status" in addition to our own HTTP status. Also may - include the full exchange reply to our request under "exchange-reply". + Likely returned with an "exchange_code" in addition to a "code" and + an "exchange_http_status" in addition to our own HTTP status. Also may + include the full exchange reply to our request under "exchange_reply". Naturally, those diagnostics may be omitted if the exchange did not reply at all, or send a completely malformed response. :status 503 Service Unavailable: We are unable to process the request, possibly due to misconfiguration or disagreement with the exchange (it is unclear which party is to blame). - Likely returned with an "exchange-code" in addition to a "code" and - an "exchange-http-status" in addition to our own HTTP status. Also may - include the full exchange reply to our request under "exchange-reply". + Likely returned with an "exchange_code" in addition to a "code" and + an "exchange_http_status" in addition to our own HTTP status. Also may + include the full exchange reply to our request under "exchange_reply". .. ts:def:: TipCreateRequest @@ -269,17 +269,17 @@ Giving Customer Tips The merchant backend instance does not have a tipping reserve configured. :status 424 Failed Dependency: We are unable to process the request because of a problem with the exchange. - Likely returned with an "exchange-code" in addition to a "code" and - an "exchange-http-status" in addition to our own HTTP status. Also may - include the full exchange reply to our request under "exchange-reply". + Likely returned with an "exchange_code" in addition to a "code" and + an "exchange_http_status" in addition to our own HTTP status. Also may + include the full exchange reply to our request under "exchange_reply". Naturally, those diagnostics may be omitted if the exchange did not reply at all, or send a completely malformed response. :status 503 Service Unavailable: We are unable to process the request, possibly due to misconfiguration or disagreement with the exchange (it is unclear which party is to blame). - Likely returned with an "exchange-code" in addition to a "code" and - an "exchange-http-status" in addition to our own HTTP status. Also may - include the full exchange reply to our request under "exchange-reply". + Likely returned with an "exchange_code" in addition to a "code" and + an "exchange_http_status" in addition to our own HTTP status. Also may + include the full exchange reply to our request under "exchange_reply". .. ts:def:: TipQueryResponse @@ -1163,6 +1163,77 @@ both by the user's browser and their wallet. The frontend used the same order ID with different content in the order. +.. http:get:: /public/[$INSTANCE]/$ORDER/refund + + Obtain a refund issued by the merchant. + + **Response:** + + :status 200 OK: + The merchant processed the approved refund. The body is a `RefundResponse`. + Note that a successful response from the merchant does not imply that the + exchange successfully processed the refund. Clients must inspect the + body to check which coins were successfully refunded. It is possible for + only a subset of the refund request to have been processed successfully. + Re-issuing the request will cause the merchant to re-try such unsuccessful + sub-requests. + + .. ts:def:: RefundResponse + + interface RefundResponse { + // hash of the contract terms + h_contract_terms: HashCode; + + // merchant's public key + merchant_pub: EddsaPublicKey; + + // array with information about the refunds obtained + refunds: RefundDetail[]; + } + + .. ts:def:: RefundDetail + + interface RefundDetail { + + // public key of the coin to be refunded + coin_pub: EddsaPublicKey; + + // Amount approved for refund for this coin + refund_amount: Amount; + + // Refund fee the exchange will charge for the refund + refund_fee: Amount; + + // HTTP status from the exchange. 200 if successful. + exchange_http_status: integer; + + // Refund transaction ID. + rtransaction_id: integer; + + // Taler error code from the exchange. Only given if the + // exchange_http_status is not 200. + exchange_code?: integer; + + // Full exchange response. Only given if the + // exchange_http_status is not 200 and the exchange + // did return JSON. + exchange_reply?: integer; + + // Public key of the exchange used for the exchange_sig. + // Only given if the exchange_http_status is 200. + exchange_pub?: EddsaPublicKey; + + // Signature the exchange confirming the refund. + // Only given if the exchange_http_status is 200. + exchange_sig?: EddsaSignature; + + } + + :status 404 Not found: + The merchant is unaware of having granted a refund, or even of + the order specified. + + .. http:post:: /public/tip-pickup Handle request from wallet to pick up a tip. -- cgit v1.2.3 From 0271c2adf9a989d96fca2993f7185d6d68d19a25 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Fri, 10 Apr 2020 14:20:16 +0530 Subject: remove caution block, as underlying issue is fixed --- developers-manual.rst | 4 ---- 1 file changed, 4 deletions(-) diff --git a/developers-manual.rst b/developers-manual.rst index 4799dbd0..42e52d36 100644 --- a/developers-manual.rst +++ b/developers-manual.rst @@ -286,10 +286,6 @@ Bootstrapping an Environment $ taler-deployment-start $ taler-deployment-arm -I # check everything works - Caution: there is currently a known bug in the part that sets up the bank - account password of the exchange might either not exist or be broken. - Thus, that must currently still be done manually! (#6099). - Upgrading an Existing Environment --------------------------------- -- cgit v1.2.3 From 7ab712d49ccadf3d8d0695e9a4deb68f1136634a Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 10 Apr 2020 23:19:59 +0200 Subject: specify long polling for refunds (#5985) --- core/api-merchant.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index 80d3b4f6..002b37be 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -1297,6 +1297,7 @@ both by the user's browser and their wallet. :query h_contract: hash of the contract (used to authenticate customer) :query session_id: *Optional*. Session ID that the payment must be bound to. If not specified, the payment is not session-bound. :query timeout: *Optional*. Timeout in seconds to wait for a payment if the answer would otherwise be negative (long polling). + :query refund=AMOUNT: *Optional*. Indicates that we are polling for a refund above the given AMOUNT. Only useful in combination with timeout. **Response:** -- cgit v1.2.3 From 2bcfbab7c826c3563c063ddea19b9dcea2582023 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 11 Apr 2020 18:38:33 +0200 Subject: expand /order API to allow payment target selection when creating orders (#4939) --- core/api-merchant.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index 002b37be..35e3a1a9 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -50,6 +50,8 @@ Receiving Payments The request must be a `PostOrderRequest`. + :query payment_target: optional query that specifies the payment target preferred by the client. Can be used to select among the various (active) wire methods supported by the instance. + **Response** :status 200 OK: -- cgit v1.2.3 From 0c235b70616c2f456814e4fd2c2558f5ee6f3870 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 11 Apr 2020 18:47:18 +0200 Subject: specify how to expose payment targets in /config for #4939 --- core/api-merchant.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index 35e3a1a9..4fc736a8 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -991,6 +991,11 @@ both by the user's browser and their wallet. // Public key of the merchant/instance, in Crockford Base32 encoding. merchant_pub: EddsaPublicKey; + // List of the payment targets supported by this instance. Clients can + // specify the desired payment target in /order requests. Note that + // front-ends do not have to support wallets selecting payment targets. + payment_targets: string[]; + // Base URL of the exchange this instance uses for tipping. // Optional, only present if the instance supports tipping. tipping_exchange_baseurl?: string; -- cgit v1.2.3 From 505c40867519ede39a3087b60e86de2004275a10 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 12 Apr 2020 20:46:50 +0200 Subject: API updates for merchant implementation of #6173 --- core/api-merchant.rst | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index 4fc736a8..22c090f9 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -1,6 +1,6 @@ .. This file is part of GNU TALER. - Copyright (C) 2014, 2015, 2016, 2017 Taler Systems SA + Copyright (C) 2014-2020 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 @@ -1286,11 +1286,16 @@ both by the user's browser and their wallet. .. ts:def:: TipResponse interface TipResponse { - // Public key of the reserve - reserve_pub: EddsaPublicKey; + // Blind RSA signatures over the planchets. // The order of the signatures matches the planchets list. - reserve_sigs: EddsaSignature[]; + blind_sigs: BlindSignature[]; + } + + interface BlindSignature { + + // The (blind) RSA signature. Still needs to be unblinded. + blind_sig: RsaSignature; } -- cgit v1.2.3 From 95f5214432d6f58ac374db481cc13e5542b2572c Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 13 Apr 2020 16:27:10 +0200 Subject: spec v1 of merchant protocol --- core/api-merchant.rst | 1862 +++++++++++++++++++++++++++---------------------- 1 file changed, 1016 insertions(+), 846 deletions(-) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index 22c090f9..43eed036 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -23,9 +23,74 @@ Merchant Backend API ==================== +WARNING: This document describes the version 1 of the merchant backend +API, which is NOT yet implemented at all! + +The ``*/public/*`` endpoints are publicly exposed on the Internet and accessed +both by the user's browser and their wallet. + +Most endpoints given here can be prefixed by a base URL that includes the +specific instance selected (BASE_URL/instances/$INSTANCE/). If +``/instances/`` is missing, the default instance is to be used. + .. contents:: Table of Contents +------------------------- +Getting the configuration +------------------------- + +.. http:get:: /public/config + + Return the protocol version and currency supported by this merchant backend. + + **Response:** + + :status 200 OK: + The exchange accepted all of the coins. The body is a `VersionResponse`. + + .. ts:def:: VersionResponse + + interface VersionResponse { + // libtool-style representation of the Merchant protocol version, see + // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning + // The format is "current:revision:age". + version: string; + + // Currency supported by this backend. + currency: string; + + // optional array with information about the instances running at this backend + // FIXME: remove, use/provide http:get:: /instances instead! + instances: InstanceInformation[]; + } + + .. ts:def:: InstanceInformation + + interface InstanceInformation { + + // Human-readable legal business name served by this instance + name: string; + + // Base URL of the instance. Can be of the form "/PizzaShop/" or + // a fully qualified URL (i.e. "https://backend.example.com/PizzaShop/"). + instance_baseurl: string; + + // Public key of the merchant/instance, in Crockford Base32 encoding. + merchant_pub: EddsaPublicKey; + + // List of the payment targets supported by this instance. Clients can + // specify the desired payment target in /order requests. Note that + // front-ends do not have to support wallets selecting payment targets. + payment_targets: string[]; + + // Base URL of the exchange this instance uses for tipping. + // Optional, only present if the instance supports tipping. + // FIXME: obsolete with current tipping API! + tipping_exchange_baseurl?: string; + + } + ------------------ Receiving Payments @@ -33,7 +98,7 @@ Receiving Payments .. _post-order: -.. http:post:: /order +.. http:post:: /create-order Create a new order that a customer can pay for. @@ -41,10 +106,10 @@ Receiving Payments .. note:: - This endpoint does not return a URL to redirect your user to confirm the payment. - In order to get this URL use :http:get:`/check-payment`. The API is structured this way - since the payment redirect URL is not unique for every order, there might be varying parameters - such as the session id. + This endpoint does not return a URL to redirect your user to confirm the + payment. In order to get this URL use :http:get:`/orders/$ORDER_ID`. The + API is structured this way since the payment redirect URL is not unique + for every order, there might be varying parameters such as the session id. **Request:** @@ -79,8 +144,8 @@ Receiving Payments summary: string; // URL that will show that the order was successful after - // it has been paid for. The wallet will always automatically append - // the order_id as a query parameter. + // it has been paid for. The wallet must always automatically append + // the order_id as a query parameter to this URL when using it. fulfillment_url: string; } @@ -92,363 +157,291 @@ Receiving Payments } -.. http:get:: /check-payment - Check the payment status of an order. If the order exists but is not payed yet, - the response provides a redirect URL. - When the user goes to this URL, they will be prompted for payment. +.. http:get:: /orders - **Request:** - - :query order_id: order id that should be used for the payment - :query session_id: *Optional*. Session ID that the payment must be bound to. If not specified, the payment is not session-bound. - :query timeout: *Optional*. Timeout in seconds to wait for a payment if the answer would otherwise be negative (long polling). + Returns known orders up to some point in the past - **Response:** + **Request** - Returns a `CheckPaymentResponse`, whose format can differ based on the status of the payment. + :query paid: *Optional*. If set to yes, only return paid orders, if no only unpaid orders. Do not give (or use "all") to see all orders regardless of payment status. + :query aborted: *Optional*. If set to yes, only return aborted orders, if no only unaborted orders. Do not give (or use "all") to see all orders regardless of abort status. + :query refunded: *Optional*. If set to yes, only return refunded orders, if no only unrefunded orders. Do not give (or use "all") to see all orders regardless of refund status. + :query wired: *Optional*. If set to yes, only return wired orders, if no only orders with missing wire transfers. Do not give (or use "all") to see all orders regardless of wire transfer status. + :query date: *Optional.* Time threshold, see ``delta`` for its interpretation. Defaults to the oldest or most recent entry, depending on ``delta``. + :query start: *Optional*. Row number threshold, see ``delta`` for its interpretation. Defaults to ``UINT64_MAX``, namely the biggest row id possible in the database. + :query delta: *Optional*. takes value of the form ``N (-N)``, so that at most ``N`` values strictly younger (older) than ``start`` and ``date`` are returned. Defaults to ``-20``. + :query timeout_ms: *Optional*. Timeout in milli-seconds to wait for additional orders if the answer would otherwise be negative (long polling). Only useful if delta is positive. Note that the merchant MAY still return a response that contains fewer than delta orders. - .. ts:def:: CheckPaymentResponse + **Response** - type CheckPaymentResponse = CheckPaymentPaidResponse | CheckPaymentUnpaidResponse + :status 200 OK: + The response is a JSON ``array`` of `OrderHistory`. The array is + sorted such that entry ``i`` is younger than entry ``i+1``. - .. ts:def:: CheckPaymentPaidResponse + .. ts:def:: OrderHistory - interface CheckPaymentPaidResponse { - paid: true; + interface OrderHistory { + // The serial number this entry has in the merchant's DB. + row_id: number; - // Was the payment refunded (even partially) - refunded: boolean; + // order ID of the transaction related to this entry. + order_id: string; - // Amount that was refunded, only present if refunded is true. - refund_amount?: Amount; + // Transaction's timestamp + timestamp: Timestamp; - // Contract terms - contract_terms: ContractTerms; - } + // Total amount the customer should pay for this order. + total: Amount; - .. ts:def:: CheckPaymentUnpaidResponse + // Total amount the customer did pay for this order. + paid: Amount; - interface CheckPaymentUnpaidResponse { - paid: false; + // Total amount the customer was refunded for this order. + // (includes abort-refund and refunds, boolean flag + // below can help determine which case it is). + refunded: Amount; - // URI that the wallet must process to complete the payment. - taler_pay_uri: string; + // Was the order ever fully paid? + is_paid: boolean; - // Alternative order ID which was paid for already in the same session. - // Only given if the same product was purchased before in the same session. - already_paid_order_id?: string; } --------------- -Giving Refunds --------------- -.. http:post:: /refund +.. http:post:: /public/orders/$ORDER_ID/claim - Increase the refund amount associated with a given order. The user should be - redirected to the ``taler_refund_url`` to trigger refund processing in the wallet. + Wallet claims ownership (via nonce) over an order. By claiming + an order, the wallet obtains the full contract terms, and thereby + implicitly also the hash of the contract terms it needs for the + other ``/public/`` APIs to authenticate itself as the wallet that + is indeed eligible to inspect this particular order's status. **Request** - The request body is a `RefundRequest` object. + The request must be a `ClaimRequest` + + .. ts:def:: ClaimRequest + + interface ClaimRequest { + // Nonce to identify the wallet that claimed the order. + nonce: string; + } **Response** :status 200 OK: - The refund amount has been increased, the backend responds with a `MerchantRefundResponse` + The client has successfully claimed the order. + The response contains the :ref:`contract terms `. :status 404 Not found: - The order is unknown to the merchant + The backend is unaware of the instance or order. :status 409 Conflict: - The refund amount exceeds the amount originally paid - - .. ts:def:: RefundRequest + The someone else claimed the same order ID with different nonce before. - interface RefundRequest { - // Order id of the transaction to be refunded - order_id: string; - // Amount to be refunded - refund: Amount; +.. http:post:: /public/orders/$ORDER_ID/pay - // Human-readable refund justification - reason: string; - } + Pay for an order by giving a deposit permission for coins. Typically used by + the customer's wallet. Note that this request does not include the + usual ``h_contract`` argument to authenticate the wallet, as the hash of + the contract is implied by the signatures of the coins. Furthermore, this + API doesn't really return useful information about the order. - .. ts:def:: MerchantRefundResponse + **Request:** - interface MerchantRefundResponse { + The request must be a `pay request `. - // Hash of the contract terms of the contract that is being refunded. - h_contract_terms: HashCode; + **Response:** - // URL (handled by the backend) that the wallet should access to - // trigger refund processing. - taler_refund_url: string; - } + :status 200 OK: + The exchange accepted all of the coins. + The body is a `payment response `. + The ``frontend`` should now fullfill the contract. + :status 400 Bad request: + Either the client request is malformed or some specific processing error + happened that may be the fault of the client as detailed in the JSON body + of the response. + :status 403 Forbidden: + One of the coin signatures was not valid. + :status 404 Not found: + The merchant backend could not find the order or the instance + and thus cannot process the payment. + :status 409 Conflict: + The exchange rejected the payment because a coin was already spent before. + The response will include the ``coin_pub`` for which the payment failed, + in addition to the response from the exchange to the ``/deposit`` request. + :status 412 Precondition Failed: + The given exchange is not acceptable for this merchant, as it is not in the + list of accepted exchanges and not audited by an approved auditor. + :status 424 Failed Dependency: + The merchant's interaction with the exchange failed in some way. + The client might want to try later again. + This includes failures like the denomination key of a coin not being + known to the exchange as far as the merchant can tell. + The backend will return verbatim the error codes received from the exchange's + :ref:`deposit ` API. If the wallet made a mistake, like by + double-spending for example, the frontend should pass the reply verbatim to + the browser/wallet. If the payment was successful, the frontend MAY use + this to trigger some business logic. --------------------- -Giving Customer Tips --------------------- + .. ts:def:: PaymentResponse + interface PaymentResponse { + // Signature on ``TALER_PaymentResponsePS`` with the public + // key of the merchant instance. + sig: EddsaSignature; -.. http:post:: /tip-authorize + } - Authorize a tip that can be picked up by the customer's wallet by POSTing to - ``/tip-pickup``. Note that this is simply the authorization step the back - office has to trigger first. The user should be navigated to the ``tip_redirect_url`` - to trigger tip processing in the wallet. + .. ts:def:: PayRequest - **Request** + interface PayRequest { + coins: CoinPaySig[]; + } - The request body is a `TipCreateRequest` object. + .. ts:def:: CoinPaySig - **Response** + export interface CoinPaySig { + // Signature by the coin. + coin_sig: string; - :status 200 OK: - A tip has been created. The backend responds with a `TipCreateConfirmation` - :status 404 Not Found: - The instance is unknown to the backend. - :status 412 Precondition Failed: - The tip amount requested exceeds the available reserve balance for tipping, or - the instance was never configured for tipping. - :status 424 Failed Dependency: - We are unable to process the request because of a problem with the exchange. - Likely returned with an "exchange_code" in addition to a "code" and - an "exchange_http_status" in addition to our own HTTP status. Also may - include the full exchange reply to our request under "exchange_reply". - Naturally, those diagnostics may be omitted if the exchange did not reply - at all, or send a completely malformed response. - :status 503 Service Unavailable: - We are unable to process the request, possibly due to misconfiguration or - disagreement with the exchange (it is unclear which party is to blame). - Likely returned with an "exchange_code" in addition to a "code" and - an "exchange_http_status" in addition to our own HTTP status. Also may - include the full exchange reply to our request under "exchange_reply". + // Public key of the coin being spend. + coin_pub: string; - .. ts:def:: TipCreateRequest + // Signature made by the denomination public key. + ub_sig: string; - interface TipCreateRequest { - // Amount that the customer should be tipped - amount: Amount; + // The denomination public key associated with this coin. + denom_pub: string; - // Justification for giving the tip - justification: string; + // The amount that is subtracted from this coin with this payment. + contribution: Amount; - // URL that the user should be directed to after tipping, - // will be included in the tip_token. - next_url: string; + // URL of the exchange this coin was withdrawn from. + exchange_url: string; } - .. ts:def:: TipCreateConfirmation - interface TipCreateConfirmation { - // Token that will be handed to the wallet, - // contains all relevant information to accept - // a tip. - tip_token: string; +.. http:post:: /public/orders/$ORDER_ID/abort - // URL that will directly trigger procesing - // the tip when the browser is redirected to it - tip_redirect_url: string; - } + Abort paying for an order and obtain a refund for coins that + were already deposited as part of a failed payment. + **Request:** -.. http:post:: /tip-query + The request must be an `abort request `. - Query the status of a tipping reserve. + :query h_contract: hash of the order's contract terms (this is used to authenticate the wallet/customer in case $ORDER_ID is guessable). *Mandatory!* - **Response** + **Response:** :status 200 OK: - A tip has been created. The backend responds with a `TipQueryResponse` - :status 404 Not Found: - The instance is unknown to the backend. + The exchange accepted all of the coins. The body is a + a `merchant refund response `. + :status 400 Bad request: + Either the client request is malformed or some specific processing error + happened that may be the fault of the client as detailed in the JSON body + of the response. + :status 403 Forbidden: + The ``h_contract`` does not match the order. + :status 404 Not found: + The merchant backend could not find the order or the instance + and thus cannot process the abort request. :status 412 Precondition Failed: - The merchant backend instance does not have a tipping reserve configured. + Aborting the payment is not allowed, as the original payment did succeed. :status 424 Failed Dependency: - We are unable to process the request because of a problem with the exchange. - Likely returned with an "exchange_code" in addition to a "code" and - an "exchange_http_status" in addition to our own HTTP status. Also may - include the full exchange reply to our request under "exchange_reply". - Naturally, those diagnostics may be omitted if the exchange did not reply - at all, or send a completely malformed response. - :status 503 Service Unavailable: - We are unable to process the request, possibly due to misconfiguration or - disagreement with the exchange (it is unclear which party is to blame). - Likely returned with an "exchange_code" in addition to a "code" and - an "exchange_http_status" in addition to our own HTTP status. Also may - include the full exchange reply to our request under "exchange_reply". - - .. ts:def:: TipQueryResponse - - interface TipQueryResponse { - // Amount still available - amount_available: Amount; + The merchant's interaction with the exchange failed in some way. + The error from the exchange is included. - // Amount that we authorized for tips - amount_authorized: Amount; + The backend will return verbatim the error codes received from the exchange's + :ref:`refund ` API. The frontend should pass the replies verbatim to + the browser/wallet. - // Amount that was picked up by users already - amount_picked_up: Amount; + .. ts:def:: AbortRequest - // Timestamp indicating when the tipping reserve will expire - expiration: Timestamp; + interface AbortRequest { + // List of coins the wallet would like to see refunds for. + // (Should be limited to the coins for which the original + // payment succeeded, as far as the wallet knows.) + coins: AbortedCoin[]; + } - // Reserve public key of the tipping reserve - reserve_pub: EddsaPublicKey; + interface AbortedCoin { + // Public key of a coin for which the wallet is requesting an abort-related refund. + coin_pub: EddsaPublicKey; } ------------------------- -Tracking Wire Transfers ------------------------- -.. http:get:: /track/transfer +.. http:get:: /orders/$ORDER_ID/ - Provides deposits associated with a given wire transfer. + Merchant checks the payment status of an order. If the order exists but is not payed + yet, the response provides a redirect URL. When the user goes to this URL, + they will be prompted for payment. Differs from the ``/public/`` API both + in terms of what information is returned and in that the wallet must provide + the contract hash to authenticate, while for this API we assume that the + merchant is authenticated (as the endpoint is not ``/public/``). - **Request** + **Request:** - :query wtid: raw wire transfer identifier identifying the wire transfer (a base32-encoded value) - :query wire_method: name of the wire transfer method used for the wire transfer - :query exchange: base URL of the exchange that made the wire transfer + :query session_id: *Optional*. Session ID that the payment must be bound to. If not specified, the payment is not session-bound. + :query transfer: *Optional*. If set to "YES", try to obtain the wire transfer status for this order from the exchange. Otherwise, the wire transfer status MAY be returned if it is available. + :query timeout_ms: *Optional*. Timeout in milli-seconds to wait for a payment if the answer would otherwise be negative (long polling). **Response:** :status 200 OK: - The wire transfer is known to the exchange, details about it follow in the body. - The body of the response is a `TrackTransferResponse`. Note that - the similarity to the response given by the exchange for a /track/transfer - is completely intended. - + Returns a `MerchantOrderStatusResponse`, whose format can differ based on the status of the payment. :status 404 Not Found: - The wire transfer identifier is unknown to the exchange. + The order or instance is unknown to the backend. + :status 409 Conflict: + The exchange previously claimed that a deposit was not included in a wire + transfer, and now claims that it is. This means that the exchange is + dishonest. The response contains the cryptographic proof that the exchange + is misbehaving in the form of a `TransactionConflictProof`. + :status 424 Failed dependency: + We failed to obtain a response from the exchange about the + wire transfer status. - :status 424 Failed Dependency: The exchange provided conflicting information about the transfer. Namely, - there is at least one deposit among the deposits aggregated by ``wtid`` that accounts for a coin whose - details don't match the details stored in merchant's database about the same keyed coin. - The response body contains the `TrackTransferConflictDetails`. + .. ts:def:: MerchantOrderStatusResponse - .. ts:def:: TrackTransferResponse + type MerchantOrderStatusResponse = CheckPaymentPaidResponse | CheckPaymentUnpaidResponse - interface TrackTransferResponse { - // Total amount transferred - total: Amount; + .. ts:def:: CheckPaymentPaidResponse - // Applicable wire fee that was charged - wire_fee: Amount; + interface CheckPaymentPaidResponse { + paid: true; - // public key of the merchant (identical for all deposits) - merchant_pub: EddsaPublicKey; + // Was the payment refunded (even partially) + refunded: boolean; - // hash of the wire details (identical for all deposits) - h_wire: HashCode; - - // Time of the execution of the wire transfer by the exchange - execution_time: Timestamp; - - // details about the deposits - deposits_sums: TrackTransferDetail[]; - - // signature from the exchange made with purpose - // ``TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT`` - exchange_sig: EddsaSignature; - - // public EdDSA key of the exchange that was used to generate the signature. - // Should match one of the exchange's signing keys from /keys. Again given - // explicitly as the client might otherwise be confused by clock skew as to - // which signing key was used. - exchange_pub: EddsaSignature; - } - - .. ts:def:: TrackTransferDetail - - interface TrackTransferDetail { - // Business activity associated with the wire transferred amount - // ``deposit_value``. - order_id: string; + // Amount that was refunded, only present if refunded is true. + refund_amount?: Amount; - // The total amount the exchange paid back for ``order_id``. - deposit_value: Amount; + // Contract terms + contract_terms: ContractTerms; - // applicable fees for the deposit - deposit_fee: Amount; + // If available, the wire transfer status from the exchange for this order + wire_details?: TransactionWireTransfer; } + .. ts:def:: CheckPaymentUnpaidResponse - **Details:** - - .. ts:def:: TrackTransferConflictDetails - - interface TrackTransferConflictDetails { - // Numerical `error code ` - code: number; - - // Text describing the issue for humans. - hint: string; - - // A /deposit response matching ``coin_pub`` showing that the - // exchange accepted ``coin_pub`` for ``amount_with_fee``. - exchange_deposit_proof: DepositSuccess; - - // Offset in the ``exchange_transfer_proof`` where the - // exchange's response fails to match the ``exchange_deposit_proof``. - conflict_offset: number; - - // The response from the exchange which tells us when the - // coin was returned to us, except that it does not match - // the expected value of the coin. - exchange_transfer_proof: TrackTransferResponse; - - // Public key of the coin for which we have conflicting information. - coin_pub: EddsaPublicKey; - - // Merchant transaction in which ``coin_pub`` was involved for which - // we have conflicting information. - transaction_id: number; + interface CheckPaymentUnpaidResponse { + paid: false; - // Expected value of the coin. - amount_with_fee: Amount; + // URI that the wallet must process to complete the payment. + taler_pay_uri: string; - // Expected deposit fee of the coin. - deposit_fee: Amount; + // Alternative order ID which was paid for already in the same session. + // Only given if the same product was purchased before in the same session. + already_paid_order_id?: string; + // FIXME: why do we NOT return the contract terms here? } - -.. http:get:: /track/transaction - - Provide the wire transfer identifier associated with an (existing) deposit operation. - - **Request:** - - :query id: ID of the transaction we want to trace (an integer) - - **Response:** - - :status 200 OK: - The deposit has been executed by the exchange and we have a wire transfer identifier. - The response body is a JSON array of `TransactionWireTransfer` objects. - :status 202 Accepted: - The deposit request has been accepted for processing, but was not yet - executed. Hence the exchange does not yet have a wire transfer identifier. - The merchant should come back later and ask again. - The response body is a `TrackTransactionAcceptedResponse `. Note that - the similarity to the response given by the exchange for a /track/order - is completely intended. - :status 404 Not Found: The transaction is unknown to the backend. - :status 424 Failed Dependency: - The exchange previously claimed that a deposit was not included in a wire - transfer, and now claims that it is. This means that the exchange is - dishonest. The response contains the cryptographic proof that the exchange - is misbehaving in the form of a `TransactionConflictProof`. - - **Details:** - .. ts:def:: TransactionWireTransfer interface TransactionWireTransfer { @@ -467,19 +460,6 @@ Tracking Wire Transfers amount: Amount; } - .. ts:def:: CoinWireTransfer - - interface CoinWireTransfer { - // public key of the coin that was deposited - coin_pub: EddsaPublicKey; - - // Amount the coin was worth (including deposit fee) - amount_with_fee: Amount; - - // Deposit fee retained by the exchange for the coin - deposit_fee: Amount; - } - .. ts:def:: TransactionConflictProof interface TransactionConflictProof { @@ -507,843 +487,1033 @@ Tracking Wire Transfers } -------------------- -Transaction history -------------------- +.. http:get:: /public/orders/$ORDER_ID/ -.. http:get:: /history + Query the payment status of an order. This endpoint is for the wallet. + When the wallet goes to this URL and it is unpaid, + they will be prompted for payment. - Returns transactions up to some point in the past + // FIXME: note that this combines the previous APIs + // to check-payment and to obtain refunds. **Request** - :query date: time threshold, see ``delta`` for its interpretation. - :query start: row number threshold, see ``delta`` for its interpretation. Defaults to ``UINT64_MAX``, namely the biggest row id possible in the database. - :query delta: takes value of the form ``N (-N)``, so that at most ``N`` values strictly younger (older) than ``start`` and ``date`` are returned. Defaults to ``-20``. - :query ordering: takes value ``"descending"`` or ``"ascending"`` according to the results wanted from younger to older or vice versa. Defaults to ``"descending"``. + :query h_contract: hash of the order's contract terms (this is used to authenticate the wallet/customer in case $ORDER_ID is guessable). *Mandatory!* + :query session_id: *Optional*. Session ID that the payment must be bound to. If not specified, the payment is not session-bound. + :query timeout_ms: *Optional.* If specified, the merchant backend will + wait up to ``timeout_ms`` milliseconds for completion of the payment before + sending the HTTP response. A client must never rely on this behavior, as the + merchant backend may return a response immediately. + :query refund=AMOUNT: *Optional*. Indicates that we are polling for a refund above the given AMOUNT. Only useful in combination with timeout. **Response** :status 200 OK: - The response is a JSON ``array`` of `TransactionHistory`. The array is - sorted such that entry ``i`` is younger than entry ``i+1``. - - .. ts:def:: TransactionHistory + The response is a `PublicPayStatusResponse`, with ``paid`` true. + FIXME: what about refunded? + :status 402 Payment required: + The response is a `PublicPayStatusResponse`, with ``paid`` false. + FIXME: what about refunded? + :status 403 Forbidden: + The ``h_contract`` does not match the order. + :status 404 Not found: + The merchant backend is unaware of the order. - interface TransactionHistory { - // The serial number this entry has in the merchant's DB. - row_id: number; + .. ts:def:: PublicPayStatusResponse - // order ID of the transaction related to this entry. - order_id: string; + interface PublicPayStatusResponse { + // Has the payment for this order (ever) been completed? + paid: boolean; - // Transaction's timestamp - timestamp: Timestamp; + // Was the payment refunded (even partially, via refund or abort)? + refunded: boolean; - // Total amount associated to this transaction. - amount: Amount; - } + // Amount that was refunded in total. + refund_amount: Amount; -.. _proposal: + // Refunds for this payment, empty array for none. + refunds: RefundDetail[]; + // URI that the wallet must process to complete the payment. + taler_pay_uri: string; -------------------------- -Dynamic Merchant Instance -------------------------- + // Alternative order ID which was paid for already in the same session. + // Only given if the same product was purchased before in the same session. + already_paid_order_id?: string; -.. note:: + } - The endpoints to dynamically manage merchant instances has not been - implemented yet. The bug id for this refernce is 5349. -.. http:get:: /instances +.. http:delete:: /orders/$ORDER_ID - This is used to return the list of all the merchant instances + Delete information about an order. Fails if the order was paid in the + last 10 years (or whatever TAX_RECORD_EXPIRATION is set to) or was + claimed but is unpaid and thus still a valid offer. **Response** - :status 200 OK: - The backend has successfully returned the list of instances stored. Returns - a `InstancesResponse`. - - .. ts:def:: InstancesResponse - - interface InstancesResponse { - // List of instances that are present in the backend (see `Instance`) - instances: Instance[]; - } - - The `Instance` object describes the instance registered with the backend. It has the following structure: - - .. ts:def:: Instance - - interface Instance { - // Merchant name corresponding to this instance. - name: string; - - // The URL where the wallet will send coins. - payto: string; + :status 204 No content: + The backend has successfully deleted the order. + :status 404 Not found: + The backend does not know the instance or the order. + :status 409 Conflict: + The backend refuses to delete the order. - // Merchant instance of the response to create - instance: string; - //unique key for each merchant - merchant_id: string; - } +-------------- +Giving Refunds +-------------- -.. http:put:: /instances/ +.. http:post:: /orders/$ORDER_ID/refund - This request will be used to create a new merchant instance in the backend. + Increase the refund amount associated with a given order. The user should be + redirected to the ``taler_refund_url`` to trigger refund processing in the wallet. **Request** - The request must be a `CreateInstanceRequest`. + The request body is a `RefundRequest` object. **Response** :status 200 OK: - The backend has successfully created the instance. The response is a - `CreateInstanceResponse`. - - .. ts:def:: CreateInstanceRequest - - interface CreateInstanceRequest { - // The URL where the wallet has to send coins. - // payto://-URL of the merchant's bank account. Required. - payto: string; + The refund amount has been increased, the backend responds with a `MerchantRefundResponse` + :status 404 Not found: + The order is unknown to the merchant + :status 409 Conflict: + The refund amount exceeds the amount originally paid - // Merchant instance of the response to create - // This field is optional. If it is not specified - // then it will automatically be created. - instance?: string; + .. ts:def:: RefundRequest - // Merchant name corresponding to this instance. - name: string; + interface RefundRequest { + // Amount to be refunded + refund: Amount; + // Human-readable refund justification + reason: string; } - .. ts:def:: CreateInstanceResponse + .. ts:def:: MerchantRefundResponse - interface CreateInstanceResponse { - // Merchant instance of the response that was created - instance: string; + interface MerchantRefundResponse { - //unique key for each merchant - merchant_id: string; + // Hash of the contract terms of the contract that is being refunded. + // FIXME: why do we return this? + h_contract_terms: HashCode; + + // URL (handled by the backend) that the wallet should access to + // trigger refund processing. + // FIXME: isn't this basically now always ``/public/orders/$ORDER_ID/``? + // If so, why return this? + taler_refund_url: string; } -.. http:get:: /instances/ - This is used to query a specific merchant instance. +------------------------ +Tracking Wire Transfers +------------------------ + +.. http:post:: /check-transfer + + Inform the backend over an incoming wire transfer. The backend should inquire about the details with the exchange and mark the respective orders as wired. **Request:** - :query instance_id: instance id that should be used for the instance + The request must provide `transfer information `. - **Response** + **Response:** :status 200 OK: - The backend has successfully returned the list of instances stored. Returns - a `QueryInstancesResponse`. - - .. ts:def:: QueryInstancesResponse + The wire transfer is known to the exchange, details about it follow in the body. + The body of the response is a `TrackTransferResponse`. Note that + the similarity to the response given by the exchange for a /track/transfer + is completely intended. - interface QueryInstancesResponse { - // The URL where the wallet has to send coins. - // payto://-URL of the merchant's bank account. Required. - payto: string; + :status 404 Not Found: + The wire transfer identifier is unknown to the exchange. - // Merchant instance of the response to create - // This field is optional. If it is not specified - // then it will automatically be created. - instance?: string; + :status 424 Failed Dependency: The exchange provided conflicting information about the transfer. Namely, + there is at least one deposit among the deposits aggregated by ``wtid`` that accounts for a coin whose + details don't match the details stored in merchant's database about the same keyed coin. + The response body contains the `TrackTransferConflictDetails`. - // Merchant name corresponding to this instance. - name: string; + .. ts:def:: TransferInformation - } + interface TransferInformation { + // how much was wired to the merchant (minus fees) + credit_amount: Amount; + // raw wire transfer identifier identifying the wire transfer (a base32-encoded value) + wtid: FIXME; -.. http:post:: /instances/ + // name of the wire transfer method used for the wire transfer + // FIXME: why not a payto URI? + wire_method; - This request will be used to update merchant instance in the backend. + // base URL of the exchange that made the wire transfer + exchange: string; + } + .. ts:def:: TrackTransferResponse - **Request** + interface TrackTransferResponse { + // Total amount transferred + total: Amount; - The request must be a `PostInstanceUpdateRequest`. + // Applicable wire fee that was charged + wire_fee: Amount; - **Response** + // public key of the merchant (identical for all deposits) + // FIXME: why return this? + merchant_pub: EddsaPublicKey; - :status 200 OK: - The backend has successfully updated the instance. The response is a - `PostInstanceUpdateResponse`. + // hash of the wire details (identical for all deposits) + // FIXME: why return this? Isn't this the WTID!? + h_wire: HashCode; - .. ts:def:: PostInstanceUpdateRequest + // Time of the execution of the wire transfer by the exchange, according to the exchange + execution_time: Timestamp; - interface PostInstanceUpdateRequest { - // Merchant instance that is to be updaated. Required. - instance: string; + // details about the deposits + deposits_sums: TrackTransferDetail[]; - // New URL where the wallet has to send coins. - // payto://-URL of the merchant's bank account. Required. - payto: string; + // signature from the exchange made with purpose + // ``TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT`` + // FIXME: why return this? + exchange_sig: EddsaSignature; - // Merchant name coreesponding to this instance. - name: string; + // public EdDSA key of the exchange that was used to generate the signature. + // Should match one of the exchange's signing keys from /keys. Again given + // explicitly as the client might otherwise be confused by clock skew as to + // which signing key was used. + // FIXME: why return this? + exchange_pub: EddsaSignature; + } + .. ts:def:: TrackTransferDetail + + interface TrackTransferDetail { + // Business activity associated with the wire transferred amount + // ``deposit_value``. + order_id: string; + + // The total amount the exchange paid back for ``order_id``. + deposit_value: Amount; + + // applicable fees for the deposit + deposit_fee: Amount; } - .. ts:def:: PostInstanceUpdateResponse - interface PostInstanceUpdateResponse { - // Merchant instance of the response that was updated - instance: string; + **Details:** + + .. ts:def:: TrackTransferConflictDetails + + interface TrackTransferConflictDetails { + // Numerical `error code ` + code: number; + + // Text describing the issue for humans. + hint: string; + + // A /deposit response matching ``coin_pub`` showing that the + // exchange accepted ``coin_pub`` for ``amount_with_fee``. + exchange_deposit_proof: DepositSuccess; + + // Offset in the ``exchange_transfer_proof`` where the + // exchange's response fails to match the ``exchange_deposit_proof``. + conflict_offset: number; + + // The response from the exchange which tells us when the + // coin was returned to us, except that it does not match + // the expected value of the coin. + exchange_transfer_proof: TrackTransferResponse; + + // Public key of the coin for which we have conflicting information. + coin_pub: EddsaPublicKey; + + // Merchant transaction in which ``coin_pub`` was involved for which + // we have conflicting information. + transaction_id: number; + + // Expected value of the coin. + amount_with_fee: Amount; + + // Expected deposit fee of the coin. + deposit_fee: Amount; - //unique key for each merchant - merchant_id: string; } -.. http:delete:: /instances/ +.. http:get:: /transfers - This request will be used to delete merchant instance in the backend. + Obtain a list of all wire transfers the backend has checked. **Request:** - :query instance_id: instance id that should be used for the instance + :query filter: FIXME: should have a way to filter, maybe even long-poll? - **Response** + **Response:** + + FIXME: to be specified. + + + +-------------------- +Giving Customer Tips +-------------------- + + +.. http:post:: /create-reserve + + Create a reserve for tipping. + + **Request:** + + The request body is a `ReserveCreateRequest` object. + + **Response:** :status 200 OK: - The backend has successfully removed the instance. The response is a - `PostInstanceRemoveResponse`. + The backend is waiting for the reserve to be established. The merchant + must now perform the wire transfer indicated in the `ReserveCreateConfirmation`. + :status 424 Failed Depencency: + We could not obtain /wire details from the specified exchange base URL. - .. ts:def:: PostInstanceRemoveResponse + .. ts:def:: ReserveCreateRequest + + interface ReserveCreateRequest { + // Amount that the merchant promises to put into the reserve + initial_amount: Amount; + + // Exchange the merchant intends to use for tipping + exchange_base_url: string; - interface PostInstanceRemoveResponse { - deleted: true; } + .. ts:def:: ReserveCreateConfirmation ------------------- -The Contract Terms ------------------- + interface ReserveCreateConfirmation { + // Public key identifying the reserve + reserve_pub: EddsaPublicKey; -The contract terms must have the following structure: + // Wire account of the exchange where to transfer the funds + payto_url: string; - .. ts:def:: ContractTerms + } - interface ContractTerms { - // Human-readable description of the whole purchase - summary: string; +.. http:get:: /reserves - // Map from IETF BCP 47 language tags to localized summaries - summary_i18n?: { [lang_tag: string]: string }; + Obtain list of reserves that have been created for tipping. - // Unique, free-form identifier for the proposal. - // Must be unique within a merchant instance. - // For merchants that do not store proposals in their DB - // before the customer paid for them, the order_id can be used - // by the frontend to restore a proposal from the information - // encoded in it (such as a short product identifier and timestamp). - order_id: string; + **Request:** - // Total price for the transaction. - // The exchange will subtract deposit fees from that amount - // before transferring it to the merchant. + :query after: *Optional*. Only return reserves created after the given timestamp [FIXME: unit?] + + **Response:** + + :status 200 OK: + Returns a list of known tipping reserves. + The body is a `TippingReserveStatus`. + + .. ts:def:: TippingReserveStatus + + interface TippingReserveStatus { + + // Array of all known reserves (possibly empty!) + reserves: ReserveStatusEntry[]; + + } + + .. ts:def:: ReserveStatusEntry + + interface ReserveStatusEntry { + + // Public key of the reserve + reserve_pub: EddsaPublicKey; + + // Timestamp when it was established + creation_time: Timestamp; + + // Timestamp when it expires + expiration_time: Timestamp; + + // Initial amount as per reserve creation call + merchant_initial_amount: Amount; + + // Initial amount as per exchange, 0 if exchange did + // not confirm reserve creation yet. + exchange_initial_amount: Amount; + + // Amount picked up so far. + pickup_amount: Amount; + + // Amount approved for tips that exceeds the pickup_amount. + committed_amount: Amount; + + } + + +.. http:get:: /reserves/$RESERVE_PUB + + Obtain information about a specific reserve that have been created for tipping. + + **Request:** + + :query tips: *Optional*. If set to "yes", returns also information about all of the tips created + + **Response:** + + :status 200 OK: + Returns the `ReserveDetail`. + :status 404 Not found: + The tipping reserve is not known. + :status 424 Failed Dependency: + We are having trouble with the request because of a problem with the exchange. + Likely returned with an "exchange_code" in addition to a "code" and + an "exchange_http_status" in addition to our own HTTP status. Also usually + includes the full exchange reply to our request under "exchange_reply". + This is only returned if there was actual trouble with the exchange, not + if the exchange merely did not respond yet or if it responded that the + reserve was not yet filled. + + .. ts:def:: ReserveDetail + + interface ReserveDetail { + + // Timestamp when it was established + creation_time: Timestamp; + + // Timestamp when it expires + expiration_time: Timestamp; + + // Initial amount as per reserve creation call + merchant_initial_amount: Amount; + + // Initial amount as per exchange, 0 if exchange did + // not confirm reserve creation yet. + exchange_initial_amount: Amount; + + // Amount picked up so far. + pickup_amount: Amount; + + // Amount approved for tips that exceeds the pickup_amount. + committed_amount: Amount; + + // Array of all tips created by this reserves (possibly empty!). + // Only present if asked for explicitly. + tips?: TipStatusEntry[]; + + } + + .. ts:def:: TipStatusEntry + + interface TipStatusEntry { + + // Unique identifier for the tip + tip_id: HashCode; + + // Total amount of the tip that can be withdrawn. + total_amount: Amount; + + // Human-readable reason for why the tip was granted. + reason: String; + + } + + +.. http:post:: /reserves/$RESERVE_PUB/authorize-tip + + Authorize creation of a tip from the given reserve. + + **Request:** + + The request body is a `TipCreateRequest` object. + + **Response** + + :status 200 OK: + A tip has been created. The backend responds with a `TipCreateConfirmation` + :status 404 Not Found: + The instance or the reserve is unknown to the backend. + :status 412 Precondition Failed: + The tip amount requested exceeds the available reserve balance for tipping. + + .. ts:def:: TipCreateRequest + + interface TipCreateRequest { + // Amount that the customer should be tipped amount: Amount; - // The URL for this purchase. Every time is is visited, the merchant - // will send back to the customer the same proposal. Clearly, this URL - // can be bookmarked and shared by users. - fulfillment_url: string; + // Justification for giving the tip + justification: string; - // Maximum total deposit fee accepted by the merchant for this contract - max_fee: Amount; + // URL that the user should be directed to after tipping, + // will be included in the tip_token. + next_url: string; + } - // Maximum wire fee accepted by the merchant (customer share to be - // divided by the 'wire_fee_amortization' factor, and further reduced - // if deposit fees are below 'max_fee'). Default if missing is zero. - max_wire_fee: Amount; + .. ts:def:: TipCreateConfirmation - // Over how many customer transactions does the merchant expect to - // amortize wire fees on average? If the exchange's wire fee is - // above 'max_wire_fee', the difference is divided by this number - // to compute the expected customer's contribution to the wire fee. - // The customer's contribution may further be reduced by the difference - // between the 'max_fee' and the sum of the actual deposit fees. - // Optional, default value if missing is 1. 0 and negative values are - // invalid and also interpreted as 1. - wire_fee_amortization: number; + interface TipCreateConfirmation { + // Unique tip identifier for the tip that was created. + tip_id: HashCode; - // List of products that are part of the purchase (see `Product`). - products: Product[]; + // Token that will be handed to the wallet, + // contains all relevant information to accept + // a tip. + tip_token: string; - // Time when this contract was generated - timestamp: Timestamp; + // URL that will directly trigger processing + // the tip when the browser is redirected to it + tip_redirect_url: string; - // After this deadline has passed, no refunds will be accepted. - refund_deadline: Timestamp; + } - // After this deadline, the merchant won't accept payments for the contact - pay_deadline: Timestamp; - // Transfer deadline for the exchange. Must be in the - // deposit permissions of coins used to pay for this order. - wire_transfer_deadline: Timestamp; +.. http:delete:: /reserves/$RESERVE_PUB - // Merchant's public key used to sign this proposal; this information - // is typically added by the backend Note that this can be an ephemeral key. - merchant_pub: EddsaPublicKey; + Delete information about a reserve. Fails if the reserve still has + committed to tips that were not yet picked up and that have not yet + expired. - // Base URL of the (public!) merchant backend API. - // Must be an absolute URL that ends with a slash. - merchant_base_url: string; + **Response** - // More info about the merchant, see below - merchant: Merchant; + :status 204 No content: + The backend has successfully deleted the reserve. + :status 404 Not found: + The backend does not know the instance or the reserve. + :status 409 Conflict: + The backend refuses to delete the reserve (committed tips). - // The hash of the merchant instance's wire details. - h_wire: HashCode; - // Wire transfer method identifier for the wire method associated with h_wire. - // The wallet may only select exchanges via a matching auditor if the - // exchange also supports this wire method. - // The wire transfer fees must be added based on this wire transfer method. - wire_method: string; - // Any exchanges audited by these auditors are accepted by the merchant. - auditors: Auditor[]; +.. http:get:: /tips/$TIP_ID - // Exchanges that the merchant accepts even if it does not accept any auditors that audit them. - exchanges: Exchange[]; + Obtain information about a particular tip. - // Map from labels to locations - locations: { [label: string]: [location: Location], ... }; + **Request:** - // Nonce generated by the wallet and echoed by the merchant - // in this field when the proposal is generated. - nonce: string; + :query pickups: if set to "yes", returns also information about all of the pickups - // Specifies for how long the wallet should try to get an - // automatic refund for the purchase. If this field is - // present, the wallet should wait for a few seconds after - // the purchase and then automatically attempt to obtain - // a refund. The wallet should probe until "delay" - // after the payment was successful (i.e. via long polling - // or via explicit requests with exponential back-off). - // - // In particular, if the wallet is offline - // at that time, it MUST repeat the request until it gets - // one response from the merchant after the delay has expired. - // If the refund is granted, the wallet MUST automatically - // recover the payment. This is used in case a merchant - // knows that it might be unable to satisfy the contract and - // desires for the wallet to attempt to get the refund without any - // customer interaction. Note that it is NOT an error if the - // merchant does not grant a refund. - auto_refund?: RelativeTime; + **Response** - // Extra data that is only interpreted by the merchant frontend. - // Useful when the merchant needs to store extra information on a - // contract without storing it separately in their database. - extra?: any; + :status 200 OK: + The tip is known. The backend responds with a `TipDetails` message + :status 404 Not Found: + The tip is unknown to the backend. + + .. ts:def:: TipDetails + + interface TipDetails { + + // Amount that we authorized for this tip. + total_authorized: Amount; + + // Amount that was picked up by the user already. + total_picked_up: Amount; + + // Human-readable reason given when authorizing the tip. + reason: String; + + // Timestamp indicating when the tip is set to expire (may be in the past). + expiration: Timestamp; + + // Reserve public key from which the tip is funded + reserve_pub: EddsaPublicKey; + + // Array showing the pickup operations of the wallet (possibly empty!). + // Only present if asked for explicitly. + pickups?: PickupDetail[]; } - The wallet must select a exchange that either the merchant accepts directly by - listing it in the exchanges array, or for which the merchant accepts an auditor - that audits that exchange by listing it in the auditors array. + .. ts:def:: PickupDetail - The `Product` object describes the product being purchased from the merchant. It has the following structure: + interface PickupDetail { - .. ts:def:: Product + // Unique identifier for the pickup operation. + pickup_id: HashCode; - interface Product { - // Human-readable product description. - description: string; + // Number of planchets involved. + num_planchets: integer; - // Map from IETF BCP 47 language tags to localized descriptions - description_i18n?: { [lang_tag: string]: string }; + // Total amount requested for this pickup_id. + requested_amount: Amount; - // The quantity of the product to deliver to the customer (optional, if applicable) - quantity?: string; + // Total amount processed by the exchange for this pickup. + exchange_amount: Amount; - // The price of the product; this is the total price for the amount specified by 'quantity' - price: Amount; + } + + +.. http:post:: /public/tips/$TIP_ID/pickup + + Handle request from wallet to pick up a tip. + + **Request** + + The request body is a `TipPickupRequest` object. + + **Response** - // merchant-internal identifier for the product - product_id?: string; + :status 200 OK: + A tip is being returned. The backend responds with a `TipResponse` + :status 401 Unauthorized: + The tip amount requested exceeds the tip. + :status 404 Not Found: + The tip identifier is unknown. + :status 409 Conflict: + Some of the denomination key hashes of the request do not match those currently available from the exchange (hence there is a conflict between what the wallet requests and what the merchant believes the exchange can provide). - // An optional base64-encoded product image - image?: ImageDataUrl; + .. ts:def:: TipPickupRequest - // a list of objects indicating a 'taxname' and its amount. Again, italics denotes the object field's name. - taxes?: any[]; + interface TipPickupRequest { - // time indicating when this product should be delivered - delivery_date: Timestamp; + // Identifier of the tip. + tip_id: HashCode; - // where to deliver this product. This may be an URL for online delivery - // (i.e. 'http://example.com/download' or 'mailto:customer@example.com'), - // or a location label defined inside the proposition's 'locations'. - // The presence of a colon (':') indicates the use of an URL. - delivery_location: string; + // List of planches the wallet wants to use for the tip + planchets: PlanchetDetail[]; } - .. ts:def:: Merchant + .. ts:def:: PlanchetDetail - interface Merchant { - // label for a location with the business address of the merchant - address: string; + interface PlanchetDetail { + // Hash of the denomination's public key (hashed to reduce + // bandwidth consumption) + denom_pub_hash: HashCode; - // the merchant's legal name of business - name: string; + // coin's blinded public key + coin_ev: CoinEnvelope; - // label for a location that denotes the jurisdiction for disputes. - // Some of the typical fields for a location (such as a street address) may be absent. - jurisdiction: string; } + .. ts:def:: TipResponse - .. ts:def:: Location + interface TipResponse { - interface Location { - country?: string; - city?: string; - state?: string; - region?: string; - province?: string; - zip_code?: string; - street?: string; - street_number?: string; + // Blind RSA signatures over the planchets. + // The order of the signatures matches the planchets list. + blind_sigs: BlindSignature[]; } - .. ts:def:: Auditor - - interface Auditor { - // official name - name: string; - - // Auditor's public key - auditor_pub: EddsaPublicKey; + interface BlindSignature { - // Base URL of the auditor - url: string; + // The (blind) RSA signature. Still needs to be unblinded. + blind_sig: RsaSignature; } - .. ts:def:: Exchange - interface Exchange { - // the exchange's base URL - url: string; - // master public key of the exchange - master_pub: EddsaPublicKey; - } -------------------- -Customer-facing API -------------------- +------------------------- +Dynamic Merchant Instance +------------------------- -The ``/public/*`` endpoints are publicly exposed on the internet and accessed -both by the user's browser and their wallet. +.. note:: + The endpoints to dynamically manage merchant instances has not been + implemented yet. The bug id for this reference is #5349. -.. http:get:: /public/config +.. http:get:: /instances - Return the protocol version and currency supported by this merchant backend. + This is used to return the list of all the merchant instances - **Response:** + **Response** :status 200 OK: - The exchange accepted all of the coins. The body is a `VersionResponse`. - - .. ts:def:: VersionResponse - - interface VersionResponse { - // libtool-style representation of the Merchant protocol version, see - // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning - // The format is "current:revision:age". - version: string; + The backend has successfully returned the list of instances stored. Returns + a `InstancesResponse`. - // Currency supported by this backend. - currency: string; + .. ts:def:: InstancesResponse - // optional array with information about the instances running at this backend - instances: InstanceInformation[]; + interface InstancesResponse { + // List of instances that are present in the backend (see `Instance`) + instances: Instance[]; } - .. ts:def:: InstanceInformation + The `Instance` object describes the instance registered with the backend. It has the following structure: - interface InstanceInformation { + .. ts:def:: Instance - // Human-readable legal business name served by this instance + interface Instance { + // Merchant name corresponding to this instance. name: string; - // Base URL of the instance. Can be of the form "/PizzaShop/" or - // a fully qualified URL (i.e. "https://backend.example.com/PizzaShop/"). - instance_baseurl: string; - - // Public key of the merchant/instance, in Crockford Base32 encoding. - merchant_pub: EddsaPublicKey; - - // List of the payment targets supported by this instance. Clients can - // specify the desired payment target in /order requests. Note that - // front-ends do not have to support wallets selecting payment targets. - payment_targets: string[]; + // The URL where the wallet will send coins. + payto: string; - // Base URL of the exchange this instance uses for tipping. - // Optional, only present if the instance supports tipping. - tipping_exchange_baseurl?: string; + // Merchant instance of the response to create + instance: string; + //unique key for each merchant + merchant_id: string; } -.. http:post:: /public/pay +.. http:put:: /instances/$INSTANCE - Pay for a proposal by giving a deposit permission for coins. Typically used by - the customer's wallet. Can also be used in ``abort-refund`` mode to refund coins - that were already deposited as part of a failed payment. + This request will be used to create a new merchant instance in the backend. - **Request:** + **Request** - The request must be a `pay request `. + The request must be a `CreateInstanceRequest`. - **Response:** + **Response** :status 200 OK: - The exchange accepted all of the coins. The body is a `PaymentResponse` if - the request used the mode "pay", or a `MerchantRefundResponse` if the - request used was the mode "abort-refund". - The ``frontend`` should now fullfill the contract. - :status 400 Bad request: - Either the client request is malformed or some specific processing error - happened that may be the fault of the client as detailed in the JSON body - of the response. - :status 401 Unauthorized: - One of the coin signatures was not valid. - :status 403 Forbidden: - The exchange rejected the payment because a coin was already spent before. - The response will include the 'coin_pub' for which the payment failed, - in addition to the response from the exchange to the ``/deposit`` request. - :status 404 Not found: - The merchant backend could not find the proposal or the instance - and thus cannot process the payment. - :status 412 Precondition Failed: - The given exchange is not acceptable for this merchant, as it is not in the - list of accepted exchanges and not audited by an approved auditor. - :status 424 Failed Dependency: - The merchant's interaction with the exchange failed in some way. - The client might want to try later again. - This includes failures like the denomination key of a coin not being - known to the exchange as far as the merchant can tell. + The backend has successfully created the instance. The response is a + `CreateInstanceResponse`. - The backend will return verbatim the error codes received from the exchange's - :ref:`deposit ` API. If the wallet made a mistake, like by - double-spending for example, the frontend should pass the reply verbatim to - the browser/wallet. This should be the expected case, as the ``frontend`` - cannot really make mistakes; the only reasonable exception is if the - ``backend`` is unavailable, in which case the customer might appreciate some - reassurance that the merchant is working on getting his systems back online. + .. ts:def:: CreateInstanceRequest - .. ts:def:: PaymentResponse + interface CreateInstanceRequest { + // The URL where the wallet has to send coins. + // payto://-URL of the merchant's bank account. Required. + // FIXME: need an array, and to distinguish between + // supported and active (see taler.conf options on accounts!) + payto: string; - interface PaymentResponse { - // Signature on `TALER_PaymentResponsePS` with the public - // key of the merchant instance. - sig: EddsaSignature; + // Merchant instance of the response to create + // This field is optional. If it is not specified + // then it will automatically be created. + // FIXME: I do not understand this argument. -CG + instance?: string; + + // Merchant name corresponding to this instance. + name: string; - // Contract terms hash being signed over. - h_contract_terms: HashCode; } - .. ts:def:: PayRequest + .. ts:def:: CreateInstanceResponse - interface PayRequest { - coins: CoinPaySig[]; + interface CreateInstanceResponse { + // Merchant instance of the response that was created + // FIXME: I do not understand this value, isn't it implied? + instance: string; - // The merchant public key, used to uniquely - // identify the merchant instance. - merchant_pub: string; + //unique key for each merchant + // FIXME: I do not understand this value. + merchant_id: string; + } - // Order ID that's being payed for. - order_id: string; - // Mode for /pay ("pay" or "abort-refund") - mode: "pay" | "abort-refund"; - } +.. http:get:: /instances/ - .. ts:def:: CoinPaySig + This is used to query a specific merchant instance. - export interface CoinPaySig { - // Signature by the coin. - coin_sig: string; + **Request:** - // Public key of the coin being spend. - coin_pub: string; + :query instance_id: instance id that should be used for the instance - // Signature made by the denomination public key. - ub_sig: string; + **Response** - // The denomination public key associated with this coin. - denom_pub: string; + :status 200 OK: + The backend has successfully returned the list of instances stored. Returns + a `QueryInstancesResponse`. - // The amount that is subtracted from this coin with this payment. - contribution: Amount; + .. ts:def:: QueryInstancesResponse - // URL of the exchange this coin was withdrawn from. - exchange_url: string; - } + interface QueryInstancesResponse { + // The URL where the wallet has to send coins. + // payto://-URL of the merchant's bank account. Required. + payto: string; + // Merchant instance of the response to create + // This field is optional. If it is not specified + // then it will automatically be created. + instance?: string; -.. http:get:: /public/pay + // Merchant name corresponding to this instance. + name: string; - Query the payment status of an order. + // Public key of the merchant/instance, in Crockford Base32 encoding. + merchant_pub: EddsaPublicKey; - **Request** + // List of the payment targets supported by this instance. Clients can + // specify the desired payment target in /order requests. Note that + // front-ends do not have to support wallets selecting payment targets. + payment_targets: string[]; - :query hc: hash of the order's contract terms - :query long_poll_ms: *Optional.* If specified, the merchant backend will - wait up to ``long_poll_ms`` milliseconds for completion of the payment before - sending the HTTP response. A client must never rely on this behavior, as the - merchant backend may return a response immediately. + } - **Response** - :status 200 OK: - The response is a `PublicPayStatusResponse`. +.. http:post:: /instances/ - .. ts:def:: PublicPayStatusResponse + This request will be used to update merchant instance in the backend. - interface PublicPayStatusResponse { - // Has the payment for this order been completed? - paid: boolean; - // Refunds for this payment, if any. - refunds: RefundInfo[]; - } + **Request** + + The request must be a `PostInstanceUpdateRequest`. + **Response** + + :status 200 OK: + The backend has successfully updated the instance. The response is a + `PostInstanceUpdateResponse`. - .. ts:def:: RefundInfo + .. ts:def:: PostInstanceUpdateRequest - interface RefundInfo { + interface PostInstanceUpdateRequest { + // Merchant instance that is to be updaated. Required. + instance: string; - // Coin from which the refund is going to be taken - coin_pub: EddsaPublicKey; + // New URL where the wallet has to send coins. + // payto://-URL of the merchant's bank account. Required. + payto: string; - // Refund amount taken from coin_pub - refund_amount: Amount; + // Merchant name coreesponding to this instance. + name: string; - // Refund fee - refund_fee: Amount; + } - // Identificator of the refund - rtransaction_id: number; + .. ts:def:: PostInstanceUpdateResponse - // Merchant public key - merchant_pub: EddsaPublicKey + interface PostInstanceUpdateResponse { + // Merchant instance of the response that was updated + instance: string; - // Merchant signature of a TALER_RefundRequestPS object - merchant_sig: EddsaSignature; + //unique key for each merchant + merchant_id: string; } -.. http:get:: /public/proposal +.. http:delete:: /instances/ - Retrieve and take ownership (via nonce) over a proposal. + This request will be used to delete merchant instance in the backend. - **Request** + **Request:** - :query order_id: the order id whose refund situation is being queried - :query nonce: the nonce for the proposal + :query instance_id: instance id that should be used for the instance **Response** :status 200 OK: - The backend has successfully retrieved the proposal. It responds with a :ref:`proposal `. - - :status 403 Forbidden: - The frontend used the same order ID with different content in the order. - + The backend has successfully removed the instance. The response is a + `PostInstanceRemoveResponse`. -.. http:get:: /public/[$INSTANCE]/$ORDER/refund + .. ts:def:: PostInstanceRemoveResponse - Obtain a refund issued by the merchant. + interface PostInstanceRemoveResponse { + deleted: true; + } - **Response:** - :status 200 OK: - The merchant processed the approved refund. The body is a `RefundResponse`. - Note that a successful response from the merchant does not imply that the - exchange successfully processed the refund. Clients must inspect the - body to check which coins were successfully refunded. It is possible for - only a subset of the refund request to have been processed successfully. - Re-issuing the request will cause the merchant to re-try such unsuccessful - sub-requests. - - .. ts:def:: RefundResponse - - interface RefundResponse { - // hash of the contract terms - h_contract_terms: HashCode; +------------------ +The Contract Terms +------------------ - // merchant's public key - merchant_pub: EddsaPublicKey; +The contract terms must have the following structure: - // array with information about the refunds obtained - refunds: RefundDetail[]; - } + .. ts:def:: ContractTerms - .. ts:def:: RefundDetail + interface ContractTerms { + // Human-readable description of the whole purchase + summary: string; - interface RefundDetail { + // Map from IETF BCP 47 language tags to localized summaries + summary_i18n?: { [lang_tag: string]: string }; - // public key of the coin to be refunded - coin_pub: EddsaPublicKey; + // Unique, free-form identifier for the proposal. + // Must be unique within a merchant instance. + // For merchants that do not store proposals in their DB + // before the customer paid for them, the order_id can be used + // by the frontend to restore a proposal from the information + // encoded in it (such as a short product identifier and timestamp). + order_id: string; - // Amount approved for refund for this coin - refund_amount: Amount; + // Total price for the transaction. + // The exchange will subtract deposit fees from that amount + // before transferring it to the merchant. + amount: Amount; - // Refund fee the exchange will charge for the refund - refund_fee: Amount; + // The URL for this purchase. Every time is is visited, the merchant + // will send back to the customer the same proposal. Clearly, this URL + // can be bookmarked and shared by users. + fulfillment_url: string; - // HTTP status from the exchange. 200 if successful. - exchange_http_status: integer; + // Maximum total deposit fee accepted by the merchant for this contract + max_fee: Amount; - // Refund transaction ID. - rtransaction_id: integer; + // Maximum wire fee accepted by the merchant (customer share to be + // divided by the 'wire_fee_amortization' factor, and further reduced + // if deposit fees are below 'max_fee'). Default if missing is zero. + max_wire_fee: Amount; - // Taler error code from the exchange. Only given if the - // exchange_http_status is not 200. - exchange_code?: integer; + // Over how many customer transactions does the merchant expect to + // amortize wire fees on average? If the exchange's wire fee is + // above 'max_wire_fee', the difference is divided by this number + // to compute the expected customer's contribution to the wire fee. + // The customer's contribution may further be reduced by the difference + // between the 'max_fee' and the sum of the actual deposit fees. + // Optional, default value if missing is 1. 0 and negative values are + // invalid and also interpreted as 1. + wire_fee_amortization: number; - // Full exchange response. Only given if the - // exchange_http_status is not 200 and the exchange - // did return JSON. - exchange_reply?: integer; + // List of products that are part of the purchase (see `Product`). + products: Product[]; - // Public key of the exchange used for the exchange_sig. - // Only given if the exchange_http_status is 200. - exchange_pub?: EddsaPublicKey; + // Time when this contract was generated + timestamp: Timestamp; - // Signature the exchange confirming the refund. - // Only given if the exchange_http_status is 200. - exchange_sig?: EddsaSignature; + // After this deadline has passed, no refunds will be accepted. + refund_deadline: Timestamp; - } + // After this deadline, the merchant won't accept payments for the contact + pay_deadline: Timestamp; - :status 404 Not found: - The merchant is unaware of having granted a refund, or even of - the order specified. + // Transfer deadline for the exchange. Must be in the + // deposit permissions of coins used to pay for this order. + wire_transfer_deadline: Timestamp; + // Merchant's public key used to sign this proposal; this information + // is typically added by the backend Note that this can be an ephemeral key. + merchant_pub: EddsaPublicKey; -.. http:post:: /public/tip-pickup + // Base URL of the (public!) merchant backend API. + // Must be an absolute URL that ends with a slash. + merchant_base_url: string; - Handle request from wallet to pick up a tip. + // More info about the merchant, see below + merchant: Merchant; - **Request** + // The hash of the merchant instance's wire details. + h_wire: HashCode; - The request body is a `TipPickupRequest` object. + // Wire transfer method identifier for the wire method associated with h_wire. + // The wallet may only select exchanges via a matching auditor if the + // exchange also supports this wire method. + // The wire transfer fees must be added based on this wire transfer method. + wire_method: string; - **Response** + // Any exchanges audited by these auditors are accepted by the merchant. + auditors: Auditor[]; - :status 200 OK: - A tip is being returned. The backend responds with a `TipResponse` - :status 401 Unauthorized: - The tip amount requested exceeds the tip. - :status 404 Not Found: - The tip identifier is unknown. - :status 409 Conflict: - Some of the denomination key hashes of the request do not match those currently available from the exchange (hence there is a conflict between what the wallet requests and what the merchant believes the exchange can provide). + // Exchanges that the merchant accepts even if it does not accept any auditors that audit them. + exchanges: Exchange[]; - .. ts:def:: TipPickupRequest + // Map from labels to locations + locations: { [label: string]: [location: Location], ... }; - interface TipPickupRequest { + // Nonce generated by the wallet and echoed by the merchant + // in this field when the proposal is generated. + nonce: string; - // Identifier of the tip. - tip_id: HashCode; + // Specifies for how long the wallet should try to get an + // automatic refund for the purchase. If this field is + // present, the wallet should wait for a few seconds after + // the purchase and then automatically attempt to obtain + // a refund. The wallet should probe until "delay" + // after the payment was successful (i.e. via long polling + // or via explicit requests with exponential back-off). + // + // In particular, if the wallet is offline + // at that time, it MUST repeat the request until it gets + // one response from the merchant after the delay has expired. + // If the refund is granted, the wallet MUST automatically + // recover the payment. This is used in case a merchant + // knows that it might be unable to satisfy the contract and + // desires for the wallet to attempt to get the refund without any + // customer interaction. Note that it is NOT an error if the + // merchant does not grant a refund. + auto_refund?: RelativeTime; - // List of planches the wallet wants to use for the tip - planchets: PlanchetDetail[]; + // Extra data that is only interpreted by the merchant frontend. + // Useful when the merchant needs to store extra information on a + // contract without storing it separately in their database. + extra?: any; } - .. ts:def:: PlanchetDetail + The wallet must select a exchange that either the merchant accepts directly by + listing it in the exchanges array, or for which the merchant accepts an auditor + that audits that exchange by listing it in the auditors array. - interface PlanchetDetail { - // Hash of the denomination's public key (hashed to reduce - // bandwidth consumption) - denom_pub_hash: HashCode; + The `Product` object describes the product being purchased from the merchant. It has the following structure: - // coin's blinded public key - coin_ev: CoinEnvelope; + .. ts:def:: Product - } + interface Product { + // Human-readable product description. + description: string; - .. ts:def:: TipResponse + // Map from IETF BCP 47 language tags to localized descriptions + description_i18n?: { [lang_tag: string]: string }; - interface TipResponse { + // The quantity of the product to deliver to the customer (optional, if applicable) + quantity?: string; - // Blind RSA signatures over the planchets. - // The order of the signatures matches the planchets list. - blind_sigs: BlindSignature[]; - } + // The price of the product; this is the total price for the amount specified by 'quantity' + price: Amount; - interface BlindSignature { + // merchant-internal identifier for the product + product_id?: string; - // The (blind) RSA signature. Still needs to be unblinded. - blind_sig: RsaSignature; - } + // An optional base64-encoded product image + image?: ImageDataUrl; + // a list of objects indicating a 'taxname' and its amount. Again, italics denotes the object field's name. + taxes?: any[]; -.. http:get:: /public/poll-payment + // time indicating when this product should be delivered + delivery_date: Timestamp; - Check the payment status of an order. + // where to deliver this product. This may be an URL for online delivery + // (i.e. 'http://example.com/download' or 'mailto:customer@example.com'), + // or a location label defined inside the proposition's 'locations'. + // The presence of a colon (':') indicates the use of an URL. + delivery_location: string; + } - **Request:** + .. ts:def:: Merchant - :query order_id: order id that should be used for the payment - :query h_contract: hash of the contract (used to authenticate customer) - :query session_id: *Optional*. Session ID that the payment must be bound to. If not specified, the payment is not session-bound. - :query timeout: *Optional*. Timeout in seconds to wait for a payment if the answer would otherwise be negative (long polling). - :query refund=AMOUNT: *Optional*. Indicates that we are polling for a refund above the given AMOUNT. Only useful in combination with timeout. + interface Merchant { + // label for a location with the business address of the merchant + address: string; - **Response:** + // the merchant's legal name of business + name: string; - Returns a `PollPaymentResponse`, whose format can differ based on the status of the payment. + // label for a location that denotes the jurisdiction for disputes. + // Some of the typical fields for a location (such as a street address) may be absent. + jurisdiction: string; + } - .. ts:def:: PollPaymentResponse - type CheckPaymentResponse = PollPaymentPaidResponse | PollPaymentUnpaidResponse + .. ts:def:: Location - .. ts:def:: PollPaymentPaidResponse + interface Location { + country?: string; + city?: string; + state?: string; + region?: string; + province?: string; + zip_code?: string; + street?: string; + street_number?: string; + } - interface PollPaymentPaidResponse { - // value is always true; - paid: boolean; + .. ts:def:: Auditor - // Was the payment refunded (even partially) - refunded: boolean; + interface Auditor { + // official name + name: string; - // Amount that was refunded, only present if refunded is true. - refund_amount?: Amount; + // Auditor's public key + auditor_pub: EddsaPublicKey; + // Base URL of the auditor + url: string; } - .. ts:def:: PollPaymentUnpaidResponse - - interface PollPaymentUnpaidResponse { - // value is always false; - paid: boolean; - - // URI that the wallet must process to complete the payment. - taler_pay_uri: string; + .. ts:def:: Exchange - // Alternative order ID which was paid for already in the same session. - // Only given if the same product was purchased before in the same session. - already_paid_order_id?: string; + interface Exchange { + // the exchange's base URL + url: string; + // master public key of the exchange + master_pub: EddsaPublicKey; } -- cgit v1.2.3 From 4e05ec8010ff4b93c5aeadd39f43f9d166d8028a Mon Sep 17 00:00:00 2001 From: Dennis Neufeld Date: Mon, 13 Apr 2020 16:35:23 +0000 Subject: correction anastasis spec --- anastasis.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/anastasis.rst b/anastasis.rst index 73a2eeda..0140e336 100644 --- a/anastasis.rst +++ b/anastasis.rst @@ -691,7 +691,7 @@ charge per truth operation using GNU Taler. interface TruthUploadRequest { // Contains the information of an interface `EncryptedKeyShare`, but simply // as one binary block (in Crockford Base32 encoding for JSON). - key_share_data: []; //bytearray of undefined length + key_share_data: []; //bytearray // Key share method, i.e. "security question", "SMS", "e-mail", ... method: string; @@ -710,7 +710,7 @@ charge per truth operation using GNU Taler. // // The nonce of the HKDF for this encryption must include the // string "ECT". - encrypted_truth: []; //bytearray of undefined length + encrypted_truth: [80]; //bytearray // mime type of truth, i.e. text/ascii, image/jpeg, etc. truth_mime: string; @@ -772,7 +772,7 @@ charge per truth operation using GNU Taler. // the HKDF may additionally include // bits from the response (i.e. some hash over the // answer to the security question) - encrypted_key_share_i: []; //bytearray of undefined length + encrypted_key_share_i: [32]; //bytearray } -- cgit v1.2.3 From c92d24dfe7d65f8801d30b834780498eb642839a Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 13 Apr 2020 21:23:19 +0200 Subject: more work on merchant API spec --- core/api-merchant.rst | 583 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 479 insertions(+), 104 deletions(-) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index 43eed036..40ee320f 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -98,11 +98,13 @@ Receiving Payments .. _post-order: -.. http:post:: /create-order +.. http:post:: /orders Create a new order that a customer can pay for. This request is **not** idempotent unless an ``order_id`` is explicitly specified. + However, while repeating without an ``order_id`` will create another order, that is + generally pretty harmless (as long as only one of the orders is returned to the wallet). .. note:: @@ -115,22 +117,62 @@ Receiving Payments The request must be a `PostOrderRequest`. - :query payment_target: optional query that specifies the payment target preferred by the client. Can be used to select among the various (active) wire methods supported by the instance. - - **Response** + **Response:** :status 200 OK: The backend has successfully created the proposal. The response is a :ts:type:`PostOrderResponse`. + :status 404 Not found: + The order given used products from the inventory, but those were not found + in the inventory. Or the merchant instance is unknown. Details in the + error code. NOTE: no good way to find out which product is not in the + inventory, we MAY want to specify that in the reply. + :status 410 Gone: + The order given used products from the inventory that are out of stock. + The reponse is a :ts:type:`OutOfStockResponse`. + .. ts:def:: PostOrderRequest interface PostOrderRequest { // The order must at least contain the minimal // order detail, but can override all - order: MinimalOrderDetail | ContractTerms; + order: Order; + + // specifies the payment target preferred by the client. Can be used + // to select among the various (active) wire methods supported by the instance. + payment_target: string; + + // specifies that inventory management is desired. If not given, + // the backend does NOT check for the availability of stocks and + // ignores the ``product_id`` (except to possibly fill in details + // about the product, if ``auto_complete`` is requested). + manage_inventory: boolean; + + // specifies that automatically completing fields based on the + // inventory data is desired. If given, + // the backend tries to expand the products-list with additional + // information and -- if missing -- will also compute the + // total amount (as the sum of the product of price times + // quantity for all items in the order). Frontends can still override + // individual product prices or the total simply by providing them, + // for example to provide discounts. + auto_complete: boolean; + + // Specifies a lock identifier that was used to + // lock a product in the inventory. Only useful if + // ``manage_inventory`` is set. Used in case a frontend + // reserved quantities of the individual products while + // the shopping card was being built. Multiple UUIDs can + // be used in case different UUIDs were used for different + // products (i.e. in case the user started with multiple + // shopping sessions that were combined during checkout). + lock_uuids?: UUID[]; + } + type Order : MinimalOrderDetail | InventoryOrderDetail | ContractTerms; + The following fields must be specified in the ``order`` field of the request. Other fields from `ContractTerms` are optional, and will override the defaults in the merchant configuration. @@ -138,7 +180,7 @@ Receiving Payments interface MinimalOrderDetail { // Amount to be paid by the customer - amount: Amount + amount: Amount; // Short summary of the order summary: string; @@ -149,6 +191,40 @@ Receiving Payments fulfillment_url: string; } + The following fields can be specified if the order is inventory-based. + In this case, the backend can compute the amounts from the prices given + in the inventory. Note that if the frontend does give more details + (towards the ContractTerms), this will override those details + (including total price) that would otherwise computed based on information + from the inventory. + + .. ts:def:: InventoryOrderDetail + + interface InventoryOrderDetail { + + // List of products that are part of the purchase (see `Product`), + // possibly incomplete as details can be filled from the inventory detail. + products: ProductSpecification[]; + } + + type ProductSpecification : (MinimalInventoryProduct | Product); + + + .. ts:def:: MinimalInventoryProduct + + Note that if the frontend does give details beyond these, + it will override those details (including price or taxes) + that the backend would otherwise fill in via the inventory. + + interface MinimalInventoryProduct { + // Which product is requested (here mandatory!) + product_id: string; + + // How many units of the product are requested + quantity: integer; + } + + .. ts:def:: PostOrderResponse interface PostOrderResponse { @@ -157,12 +233,35 @@ Receiving Payments } + .. ts:def:: OutOfStockResponse + + interface OutOfStockResponse { + // Which items are out of stock? + missing_products: OutOfStockEntry; + } + + interface OutOfStockEntry { + // Product ID of an out-of-stock item + product_id: string; + + // Requested quantity + requested_quantity: integer; + + // Available quantity (must be below ``requested_quanitity``) + available_quantity: integer; + + // When do we expect the product to be again in stock? + // Optional, not given if unknown. + restock_expected?: timestamp; + } + + .. http:get:: /orders - Returns known orders up to some point in the past + Returns known orders up to some point in the past. - **Request** + **Request:** :query paid: *Optional*. If set to yes, only return paid orders, if no only unpaid orders. Do not give (or use "all") to see all orders regardless of payment status. :query aborted: *Optional*. If set to yes, only return aborted orders, if no only unaborted orders. Do not give (or use "all") to see all orders regardless of abort status. @@ -173,15 +272,23 @@ Receiving Payments :query delta: *Optional*. takes value of the form ``N (-N)``, so that at most ``N`` values strictly younger (older) than ``start`` and ``date`` are returned. Defaults to ``-20``. :query timeout_ms: *Optional*. Timeout in milli-seconds to wait for additional orders if the answer would otherwise be negative (long polling). Only useful if delta is positive. Note that the merchant MAY still return a response that contains fewer than delta orders. - **Response** + **Response:** :status 200 OK: - The response is a JSON ``array`` of `OrderHistory`. The array is - sorted such that entry ``i`` is younger than entry ``i+1``. + The response is an `OrderHistory`. .. ts:def:: OrderHistory interface OrderHistory { + // timestamp-sorted array of all orders matching the query. + // The order of the sorting depends on the sign of ``delta``. + orders : OrderHistory[]; + } + + + .. ts:def:: OrderHistoryEntry + + interface OrderHistoryEntry { // The serial number this entry has in the merchant's DB. row_id: number; @@ -218,7 +325,7 @@ Receiving Payments other ``/public/`` APIs to authenticate itself as the wallet that is indeed eligible to inspect this particular order's status. - **Request** + **Request:** The request must be a `ClaimRequest` @@ -229,7 +336,7 @@ Receiving Payments nonce: string; } - **Response** + **Response:** :status 200 OK: The client has successfully claimed the order. @@ -493,10 +600,7 @@ Receiving Payments When the wallet goes to this URL and it is unpaid, they will be prompted for payment. - // FIXME: note that this combines the previous APIs - // to check-payment and to obtain refunds. - - **Request** + **Request:** :query h_contract: hash of the order's contract terms (this is used to authenticate the wallet/customer in case $ORDER_ID is guessable). *Mandatory!* :query session_id: *Optional*. Session ID that the payment must be bound to. If not specified, the payment is not session-bound. @@ -506,7 +610,7 @@ Receiving Payments merchant backend may return a response immediately. :query refund=AMOUNT: *Optional*. Indicates that we are polling for a refund above the given AMOUNT. Only useful in combination with timeout. - **Response** + **Response:** :status 200 OK: The response is a `PublicPayStatusResponse`, with ``paid`` true. @@ -550,7 +654,7 @@ Receiving Payments last 10 years (or whatever TAX_RECORD_EXPIRATION is set to) or was claimed but is unpaid and thus still a valid offer. - **Response** + **Response:** :status 204 No content: The backend has successfully deleted the order. @@ -570,11 +674,11 @@ Giving Refunds Increase the refund amount associated with a given order. The user should be redirected to the ``taler_refund_url`` to trigger refund processing in the wallet. - **Request** + **Request:** The request body is a `RefundRequest` object. - **Response** + **Response:** :status 200 OK: The refund amount has been increased, the backend responds with a `MerchantRefundResponse` @@ -614,9 +718,9 @@ Giving Refunds Tracking Wire Transfers ------------------------ -.. http:post:: /check-transfer +.. http:post:: /transfers - Inform the backend over an incoming wire transfer. The backend should inquire about the details with the exchange and mark the respective orders as wired. + Inform the backend over an incoming wire transfer. The backend should inquire about the details with the exchange and mark the respective orders as wired. Note that the request will fail if the WTID is not unique (which should be guaranteed by a correct exchange). **Request:** @@ -633,6 +737,10 @@ Tracking Wire Transfers :status 404 Not Found: The wire transfer identifier is unknown to the exchange. + :status 409 Conflict: + The wire transfer identifier is already known to us, but for a different amount, + wire method or exchange. + :status 424 Failed Dependency: The exchange provided conflicting information about the transfer. Namely, there is at least one deposit among the deposits aggregated by ``wtid`` that accounts for a coin whose details don't match the details stored in merchant's database about the same keyed coin. @@ -765,10 +873,16 @@ Giving Customer Tips -------------------- -.. http:post:: /create-reserve +.. http:post:: /reserves Create a reserve for tipping. + This request is **not** idempotent. However, while repeating + it will create another reserve, that is generally pretty harmless + (assuming only one of the reserves is filled with a wire transfer). + Clients may want to eventually delete the unused reserves to + avoid clutter. + **Request:** The request body is a `ReserveCreateRequest` object. @@ -931,7 +1045,7 @@ Giving Customer Tips The request body is a `TipCreateRequest` object. - **Response** + **Response:** :status 200 OK: A tip has been created. The backend responds with a `TipCreateConfirmation` @@ -978,7 +1092,7 @@ Giving Customer Tips committed to tips that were not yet picked up and that have not yet expired. - **Response** + **Response:** :status 204 No content: The backend has successfully deleted the reserve. @@ -997,7 +1111,7 @@ Giving Customer Tips :query pickups: if set to "yes", returns also information about all of the pickups - **Response** + **Response:** :status 200 OK: The tip is known. The backend responds with a `TipDetails` message @@ -1051,11 +1165,11 @@ Giving Customer Tips Handle request from wallet to pick up a tip. - **Request** + **Request:** The request body is a `TipPickupRequest` object. - **Response** + **Response:** :status 200 OK: A tip is being returned. The backend responds with a `TipResponse` @@ -1106,11 +1220,9 @@ Giving Customer Tips - - -------------------------- -Dynamic Merchant Instance -------------------------- +-------------------------- +Dynamic Merchant Instances +-------------------------- .. note:: @@ -1121,7 +1233,7 @@ Dynamic Merchant Instance This is used to return the list of all the merchant instances - **Response** + **Response:** :status 200 OK: The backend has successfully returned the list of instances stored. Returns @@ -1143,6 +1255,7 @@ Dynamic Merchant Instance name: string; // The URL where the wallet will send coins. + // FIXME: add multi-account support here! payto: string; // Merchant instance of the response to create @@ -1150,65 +1263,67 @@ Dynamic Merchant Instance //unique key for each merchant merchant_id: string; - } + // FIXME: add locations (merchant address, jurisdiction) + } -.. http:put:: /instances/$INSTANCE + +.. http:post:: /instances This request will be used to create a new merchant instance in the backend. - **Request** + **Request:** - The request must be a `CreateInstanceRequest`. + The request must be a `InstanceConfigurationMessage`. - **Response** + **Response:** - :status 200 OK: - The backend has successfully created the instance. The response is a - `CreateInstanceResponse`. + :status 204 No content: + The backend has successfully created the instance. + :status 409 Conflict: + This instance already exists, but with other configuration options. + Use "PATCH" to update an instance configuration. - .. ts:def:: CreateInstanceRequest + .. ts:def:: InstanceConfigurationMessage - interface CreateInstanceRequest { + interface InstanceConfigurationMessage { // The URL where the wallet has to send coins. // payto://-URL of the merchant's bank account. Required. // FIXME: need an array, and to distinguish between // supported and active (see taler.conf options on accounts!) payto: string; - // Merchant instance of the response to create - // This field is optional. If it is not specified - // then it will automatically be created. - // FIXME: I do not understand this argument. -CG - instance?: string; + // Name of the merchant instance to create (will become $INSTANCE). + instance: string; // Merchant name corresponding to this instance. name: string; + // FIXME: add locations (merchant address, jurisdiction) } - .. ts:def:: CreateInstanceResponse - interface CreateInstanceResponse { - // Merchant instance of the response that was created - // FIXME: I do not understand this value, isn't it implied? - instance: string; +.. http:patch:: /instances/$INSTANCE - //unique key for each merchant - // FIXME: I do not understand this value. - merchant_id: string; - } + Update the configuration of a merchant instance. + + **Request** + The request must be a `InstanceConfigurationMessage`. -.. http:get:: /instances/ + **Response:** - This is used to query a specific merchant instance. + :status 204 No content: + The backend has successfully created the instance. + :status 404 Not found: + This instance is unknown and thus cannot be reconfigured. - **Request:** - :query instance_id: instance id that should be used for the instance +.. http:get:: /instances/$INSTANCE - **Response** + This is used to query a specific merchant instance. + + **Response:** :status 200 OK: The backend has successfully returned the list of instances stored. Returns @@ -1237,68 +1352,314 @@ Dynamic Merchant Instance // front-ends do not have to support wallets selecting payment targets. payment_targets: string[]; - } + // FIXME: add locations (merchant address, jurisdiction) + } -.. http:post:: /instances/ - This request will be used to update merchant instance in the backend. +.. http:delete:: /instances/$INSTANCE + This request will be used to delete (permanently disable) + or purge merchant instance in the backend. Purging will + delete all offers and payments associated with the instance, + while disabling (the default) only deletes the private key + and makes the instance unusuable for new orders or payments. - **Request** + **Request:** - The request must be a `PostInstanceUpdateRequest`. + :query purge: *Optional*. If set to YES, the instance will be fully + deleted. Otherwise only the private key would be deleted. **Response** + :status 204 NoContent: + The backend has successfully removed the instance. The response is a + `PostInstanceRemoveResponse`. + :status 404 Not found: + The instance is unknown to the backend. + :status 409 Conflict: + The instance cannot be deleted because it has pending offers, or + the instance cannot be purged because it has successfully processed + payments that have not passed the TAX_RECORD_EXPIRATION time. + The latter case only applies if ``purge`` was set. + + + +-------------------- +Inventory management +-------------------- + +Inventory management is an *optional* backend feature that can be used to +manage limited stocks of products and to auto-complete product descriptions +in contracts (such that the frontends have to do less work). + +.. http:get:: /products + + This is used to return the list of all items in the inventory. + + **Response:** + :status 200 OK: - The backend has successfully updated the instance. The response is a - `PostInstanceUpdateResponse`. + The backend has successfully returned the inventory. Returns + a `InventorySummaryResponse`. - .. ts:def:: PostInstanceUpdateRequest + .. ts:def:: InventorySummaryResponse - interface PostInstanceUpdateRequest { - // Merchant instance that is to be updaated. Required. - instance: string; + interface InventorySummaryResponse { + // List of items that are present in the inventory + items: InventoryEntry[]; + } - // New URL where the wallet has to send coins. - // payto://-URL of the merchant's bank account. Required. - payto: string; + The `InventoryEntry` object describes an item in the inventory. It has the following structure: - // Merchant name coreesponding to this instance. - name: string; + .. ts:def:: InventoryEntry + interface InventoryEntry { + // Product identifier, as found in the product. + product_id: string; + + // Amount of the product in stock. Given in product-specific units. + // Set to -1 for "infinite" (i.e. for "electronic" books). + stock: integer; + + // unit in which the product is metered (liters, kilograms, packages, etc.) + unit: string; } - .. ts:def:: PostInstanceUpdateResponse - interface PostInstanceUpdateResponse { - // Merchant instance of the response that was updated - instance: string; +.. http:get:: /products/$PRODUCT_ID + + This is used to obtain detailed information about a product in the inventory. + + **Response:** + + :status 200 OK: + The backend has successfully returned the inventory. Returns + a `ProductDetail`. + + .. ts:def:: ProductDetail + + interface ProductDetail { + + // Human-readable product description. + description: string; + + // Map from IETF BCP 47 language tags to localized descriptions + description_i18n?: { [lang_tag: string]: string }; + + // unit in which the product is measured (liters, kilograms, packages, etc.) + unit: string; + + // The price for one ``unit`` of the product. Zero is used + // to imply that this product is not sold separately, or + // that the price is not fixed, and must be supplied by the + // front-end. If non-zero, this price MUST include applicable + // taxes. + price: Amount; + + // An optional base64-encoded product image + image?: ImageDataUrl; + + // a list of taxes paid by the merchant for one unit of this product + taxes: Tax[]; + + // Number of units of the product in stock in sum in total, + // including all existing sales ever. Given in product-specific + // units. + // A value of -1 indicates "infinite" (i.e. for "electronic" books). + total_stocked: integer; + + // Number of units of the product that have already been sold. + total_sold: integer; + + // Number of units of the product that were lost (spoiled, stolen, etc.) + total_lost: integer; + + // Number of units of the product that are currently locked by some + // shopping cart. + total_locked: integer; + + // Identifies where the product is in stock. + location?: Location; + + // Identifies when we expect the next restocking to happen. + next_restock?: timestamp; - //unique key for each merchant - merchant_id: string; } -.. http:delete:: /instances/ +.. http:post:: /products - This request will be used to delete merchant instance in the backend. + This is used to add a product to the inventory. **Request:** - :query instance_id: instance id that should be used for the instance + The request must be a `ProductAddDetail`. - **Response** + **Response:** - :status 200 OK: - The backend has successfully removed the instance. The response is a - `PostInstanceRemoveResponse`. + :status 204 No content: + The backend has successfully expanded the inventory. + :status 409 Conflict: + The backend already knows a product with this product ID, but with different details. + + + .. ts:def:: ProductAddDetail + + interface ProductAddDetail { + + // product ID to use. + product_id: string; + + // Human-readable product description. + description: string; + + // Map from IETF BCP 47 language tags to localized descriptions + description_i18n?: { [lang_tag: string]: string }; + + // unit in which the product is measured (liters, kilograms, packages, etc.) + unit: string; + + // The price for one ``unit`` of the product. Zero is used + // to imply that this product is not sold separately, or + // that the price is not fixed, and must be supplied by the + // front-end. If non-zero, this price MUST include applicable + // taxes. + price: Amount; + + // An optional base64-encoded product image + image?: ImageDataUrl; + + // a list of taxes paid by the merchant for one unit of this product + taxes: Tax[]; + + // Number of units of the product in stock in sum in total, + // including all existing sales ever. Given in product-specific + // units. + // A value of -1 indicates "infinite" (i.e. for "electronic" books). + total_stocked: integer; + + // Identifies where the product is in stock. + location?: Location; - .. ts:def:: PostInstanceRemoveResponse + // Identifies when we expect the next restocking to happen. + next_restock?: timestamp; + + } + + + +.. http:patch:: /products/$PRODUCT_ID + + This is used to update product details in the inventory. Note that + the ``total_stocked`` and ``total_lost`` numbers + MUST be greater or equal than previous values (this design ensures idempotency). + In case stocks were lost but not sold, increment the ``total_lost`` number. + All fields in the request are optional, those that are not given are + simply preserved (not modified). Note that the ``description_i18n`` and ``taxes`` + can only be modified in bulk: if it is given, all translations must be provided, not + only those that changed. Limitations: you cannot remove a ``location`` from + a product that used to have a location. "never" should be used for the ``next_restock`` + timestamp to indicate "unknown" (this conflates the cases of truly unknown and actually + no intention/possibility of restocking). + + **Request:** + + The request must be a `ProductPatchDetail`. + + **Response:** + + :status 204 No content: + The backend has successfully expanded the inventory. + + + interface ProductPatchDetail { + + // Human-readable product description. + description?: string; + + // Map from IETF BCP 47 language tags to localized descriptions + description_i18n?: { [lang_tag: string]: string }; + + // unit in which the product is measured (liters, kilograms, packages, etc.) + unit?: string; + + // The price for one ``unit`` of the product. Zero is used + // to imply that this product is not sold separately, or + // that the price is not fixed, and must be supplied by the + // front-end. If non-zero, this price MUST include applicable + // taxes. + price?: Amount; + + // An optional base64-encoded product image + image?: ImageDataUrl; + + // a list of taxes paid by the merchant for one unit of this product + taxes?: Tax[]; + + // Number of units of the product in stock in sum in total, + // including all existing sales ever. Given in product-specific + // units. + // A value of -1 indicates "infinite" (i.e. for "electronic" books). + total_stocked?: integer; + + // Number of units of the product that were lost (spoiled, stolen, etc.) + total_lost?: integer; + + // Identifies where the product is in stock. + location?: Location; + + // Identifies when we expect the next restocking to happen. + next_restock?: timestamp; + + } + + + +.. http:post:: /products/$PRODUCT_ID/lock + + This is used to lock a certain quantity of the product for a limited + duration while the customer assembles a complete order. Note that + frontends do not have to "unlock", they may rely on the timeout as + given in the ``duration`` field. Re-posting a lock with a different + ``duration`` or ``quantity`` updates the existing lock for the same UUID + and does not result in a conflict. + + Unlocking by using a ``quantity`` of zero is is + optional but recommended if customers remove products from the + shopping cart. Note that actually POSTing to ``/orders`` with set + ``manage_inventory`` and using ``lock_uuid`` will **transition** the + lock to the newly created order (which may have a different ``duration`` + and ``quantity`` than what was requested in the lock operation). + If an order is for fewer items than originally locked, the difference + is automatically unlocked. + + **Request:** + + The request must be a `LockRequest`. + + **Response:** + + :status 204 No content: + The backend has successfully locked (or unlocked) the requested ``quantity``. + :status 404 Not found: + The backend has does not know this product. + :status 410 Gone: + The backend does not have enough of product in stock. + + .. ts:def::LockRequest + + interface LockRequest { + + // UUID that identifies the frontend performing the lock + lock_uuid: UUID; + + // How long does the frontend intend to hold the lock + duration: time; + + // How many units should be locked? + quantity: integer; - interface PostInstanceRemoveResponse { - deleted: true; } @@ -1436,26 +1797,30 @@ The contract terms must have the following structure: .. ts:def:: Product interface Product { + // merchant-internal identifier for the product. + // FIXME: do we require the use of the /inventory API if this is present? + product_id?: string; + // Human-readable product description. description: string; // Map from IETF BCP 47 language tags to localized descriptions description_i18n?: { [lang_tag: string]: string }; - // The quantity of the product to deliver to the customer (optional, if applicable) - quantity?: string; + // The number of units of the product to deliver to the customer. + quantity: integer; - // The price of the product; this is the total price for the amount specified by 'quantity' - price: Amount; + // The unit in which the product is measured (liters, kilograms, packages, etc.) + unit: string; - // merchant-internal identifier for the product - product_id?: string; + // The price of the product; this is the total price for ``quantity`` times ``unit`` of this product. + price: Amount; // An optional base64-encoded product image image?: ImageDataUrl; - // a list of objects indicating a 'taxname' and its amount. Again, italics denotes the object field's name. - taxes?: any[]; + // a list of taxes paid by the merchant for this product. Can be empty. + taxes: Tax[]; // time indicating when this product should be delivered delivery_date: Timestamp; @@ -1467,6 +1832,16 @@ The contract terms must have the following structure: delivery_location: string; } + .. ts:def:: Tax + + interface Tax { + // the name of the tax + name: string; + + // amount paid in tax + tax: Amount; + } + .. ts:def:: Merchant interface Merchant { -- cgit v1.2.3 From 24a772d0b6e7fca0635aca2d808e36a62a43e825 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 13 Apr 2020 22:02:47 +0200 Subject: more work on merchant API spec --- core/api-merchant.rst | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index 40ee320f..6feefd88 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -26,6 +26,8 @@ Merchant Backend API WARNING: This document describes the version 1 of the merchant backend API, which is NOT yet implemented at all! +TODO: #5210 is not addressed by this specification! + The ``*/public/*`` endpoints are publicly exposed on the Internet and accessed both by the user's browser and their wallet. @@ -1086,6 +1088,28 @@ Giving Customer Tips } +.. http:post:: /tips + + Authorize creation of a tip from the given reserve, except with + automatic selection of a working reserve of the instance by the + backend. Intentionally otherwise identical to the /authorize-tip + endpoint given above. + + **Request:** + + The request body is a `TipCreateRequest` object. + + **Response:** + + :status 200 OK: + A tip has been created. The backend responds with a `TipCreateConfirmation` + :status 404 Not Found: + The instance is unknown to the backend. + :status 412 Precondition Failed: + The tip amount requested exceeds the available reserve balance for tipping + in all of the reserves of the instance. + + .. http:delete:: /reserves/$RESERVE_PUB Delete information about a reserve. Fails if the reserve still has -- cgit v1.2.3 From a89c552e7713d4ca01a21c8e8aa3d858e3aa1d81 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 14 Apr 2020 13:50:36 +0200 Subject: update spec --- core/api-merchant.rst | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index 6feefd88..0754aa46 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -968,6 +968,8 @@ Giving Customer Tips // Amount approved for tips that exceeds the pickup_amount. committed_amount: Amount; + // Is this reserve active (false if it was deleted but not purged) + active: boolean; } @@ -1116,6 +1118,12 @@ Giving Customer Tips committed to tips that were not yet picked up and that have not yet expired. + **Request:** + + :query purge: *Optional*. If set to YES, the reserve and all information + about tips it issued will be fully deleted. + Otherwise only the private key would be deleted. + **Response:** :status 204 No content: @@ -1123,7 +1131,7 @@ Giving Customer Tips :status 404 Not found: The backend does not know the instance or the reserve. :status 409 Conflict: - The backend refuses to delete the reserve (committed tips). + The backend refuses to delete the reserve (committed tips awaiting pickup). @@ -1575,17 +1583,19 @@ in contracts (such that the frontends have to do less work). .. http:patch:: /products/$PRODUCT_ID - This is used to update product details in the inventory. Note that - the ``total_stocked`` and ``total_lost`` numbers - MUST be greater or equal than previous values (this design ensures idempotency). - In case stocks were lost but not sold, increment the ``total_lost`` number. - All fields in the request are optional, those that are not given are - simply preserved (not modified). Note that the ``description_i18n`` and ``taxes`` - can only be modified in bulk: if it is given, all translations must be provided, not - only those that changed. Limitations: you cannot remove a ``location`` from - a product that used to have a location. "never" should be used for the ``next_restock`` - timestamp to indicate "unknown" (this conflates the cases of truly unknown and actually - no intention/possibility of restocking). + This is used to update product details in the inventory. Note that the + ``total_stocked`` and ``total_lost`` numbers MUST be greater or equal than + previous values (this design ensures idempotency). In case stocks were lost + but not sold, increment the ``total_lost`` number. All fields in the + request are optional, those that are not given are simply preserved (not + modified). Note that the ``description_i18n`` and ``taxes`` can only be + modified in bulk: if it is given, all translations must be provided, not + only those that changed. "never" should be used for the ``next_restock`` + timestamp to indicate no intention/possibility of restocking, while a time + of zero is used to indicate "unknown". + + Limitations: you cannot remove a ``location`` from a product that used to + have a location. **Request:** -- cgit v1.2.3 From 70a6cd835580166f03b2d24be4189cf2cc8fde05 Mon Sep 17 00:00:00 2001 From: Stefan Kügel Date: Wed, 15 Apr 2020 15:08:31 +0200 Subject: Extended the URI list for the documentation website --- core/taler-uri.rst | 88 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 73 insertions(+), 15 deletions(-) diff --git a/core/taler-uri.rst b/core/taler-uri.rst index a8930634..6d59bda7 100644 --- a/core/taler-uri.rst +++ b/core/taler-uri.rst @@ -19,35 +19,37 @@ Payments are requested with the ``pay`` action. The parameters are a hierarchic .. code:: none - 'taler://pay/' merchant-host '/' merchant-public-prefix '/' merchant-instance '/' order-id [ '/' session-id ] + 'taler://pay/' merchant-host '/' merchant-public-prefix '/' merchant-instance '/' orderId [ '/' sessionId ] -The components ``merchant-host``, ``merchant-prefix`` and ``order-id`` identify the URL that is used to claim the contract -for this payment request. +The components ``merchant-host``, ``merchant-public-prefix`` and ``orderId`` identify the URL that is used to claim the contract +for the payment request. -To make the URI shorter (which is important for QR code payments), ``-`` (minus) can be substituted to get a default value -for some components: +To make the URI shorter (which is important for QR code payments), ``merchant-public-prefix`` and/or ``merchant-instance`` can be substituted by ``-`` (minus) to get a default value +for these components: -* the default for ``merchant-instance`` is ``default`` * the default for ``merchant-public-prefix`` is ``public`` +* the default for ``merchant-instance`` is ``default`` The following is a minimal example for a payment request from the demo merchant, using the default instance and no session-bound payment: .. code:: none - taler://pay/backend.demo.taler.net/-/-/2019.08.26-ABCED + 'taler://pay/backend.demo.taler.net/-/-/2019.08.26-ABCED ------------------------ Withdrawing (Initiation) ------------------------ +The action ``withdraw`` is invoked when a wallet urges a bank to declench the withdrawal operation by parsing its statusUrl (e.g. "https://bank.example.com/api/withdraw-operation/12345"). + .. code:: none 'taler://withdraw/' bank-host '/' bank-query '/' withdraw-uid -When ``bank-query`` is ``-``, the default ``withdraw-operation`` will be used. +When the component ``bank-query`` is substituted by ``-`` (minus), the default ``withdraw-operation`` will be used. -Example: +Example for a withdrawal request from the Taler demo bank using the default instance: .. code:: none @@ -61,22 +63,78 @@ Withdrawing (Confirmation) 'taler://notify-reserve/' [ reserve-pub ] -Notify the wallet that the status of a reserve has changed. Used -by the bank to indicate that the withdrawal has been confirmed by the -user (e.g. via 2FA / mTAN / ...). The wallet the re-checks the -status of all unconfirmed reserves. +This action notifies the wallet that the status of a reserve has changed. It is used +by the bank to indicate that the withdrawal has been confirmed by the user (e.g. via 2FA / mTAN / ...). +The wallet the re-checks the status of all unconfirmed reserves. Optionally, ``reserve-pub`` can be specified to also indicate the reserve that has been updated. +--------- +Refunding +--------- + +Refunding is an action which is applied when merchants decide to recline from contracts or to reduce the sum to be paid by the customer. +The refund URI can be parsed with or without the component ``merchant-instance``. + +.. code:: none + + 'taler://refund/' merchant-host '/' merchant-public-prefix '/' merchant-instance '/' orderId + +To make the URI shorter, ``merchant-public-prefix`` and/or ``merchant-instance`` can be substituted by ``-`` (minus) to get a default value +for these components: + +* the default for ``merchant-public-prefix`` is ``public`` +* the default for ``merchant-instance`` is ``default`` + +The following is a minimal example for a refunding request by the Taler demo merchant using the default instance: + +.. code:: none + + taler://refund/merchant.example.com/-/-/1234 + +And this is an example for a refunding request by the Taler demo merchant parsing with a specified instance: + +.. code:: none + + 'taler://refund/merchant.example.com/-/myinst/1234 + + ------- -Refunds +Tipping ------- +Tipping is an action declenched by merchants' website servers to transfer to their visitors little values as a recompensation for bearing ads or committing services to the website (leaving comments on bought products or submitting data into forms...). The URI is named "taler tip pickup uri". + +.. code:: none + + 'taler://tip/' merchant-host '' merchant-public-prefix '/' merchant-instance '/' tipid + +The tipping URI can be parsed without an instance, with an instance or with the instances AND prefixes specified, which means either the component ``merchant-instance`` OR the components ``merchant-public-prefix`` and ``merchant-instance`` can be left out to make the URI shorter. + + +* the default for ``merchant-public-prefix`` is ``public`` +* the default for ``merchant-instance`` is ``default`` + +The following is a minimal example for a tipping request by the Taler demo merchant using the default instance: + .. code:: none - 'taler://refund/' merchant-host '/' merchant-public-prefix '/' merchant-instance '/' order-id + 'taler://tip/merchant.example.com/-/-/tipid + +This is an example for a tipping request by the Taler demo merchant parsing with a specified instance: + +.. code:: none + + 'taler://tip/merchant.example.com/-/tipm/tipid + +And this is an example for a tipping request by the Taler demo merchant parsing with specified prefix and instance: + +.. code:: none + + 'taler://tip/merchant.example.com/my%2fpfx/tipm/tipid + ------------------------- Low-level Reserve Actions -- cgit v1.2.3 From 2e8de1b7de3130d6554d86aa449588f8a49c4379 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 15 Apr 2020 23:30:37 +0200 Subject: repurchase --- core/api-merchant.rst | 2204 ++++++++++++++++++++------------------- taler-merchant-api-tutorial.rst | 51 +- 2 files changed, 1171 insertions(+), 1084 deletions(-) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index 0754aa46..7885dd4d 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -26,7 +26,8 @@ Merchant Backend API WARNING: This document describes the version 1 of the merchant backend API, which is NOT yet implemented at all! -TODO: #5210 is not addressed by this specification! +TODO: https://bugs.gnunet.org/view.php?id=5987#c15127 + is not yet addressed by this specification! The ``*/public/*`` endpoints are publicly exposed on the Internet and accessed both by the user's browser and their wallet. @@ -62,21 +63,43 @@ Getting the configuration // Currency supported by this backend. currency: string; - // optional array with information about the instances running at this backend - // FIXME: remove, use/provide http:get:: /instances instead! - instances: InstanceInformation[]; } - .. ts:def:: InstanceInformation - interface InstanceInformation { +-------------------------- +Dynamic Merchant Instances +-------------------------- + +.. _instances: +.. http:get:: /instances + + This is used to return the list of all the merchant instances + + **Response:** + + :status 200 OK: + The backend has successfully returned the list of instances stored. Returns + a `InstancesResponse`. + + .. ts:def:: InstancesResponse + + interface InstancesResponse { + // List of instances that are present in the backend (see `Instance`) + instances: Instance[]; + } - // Human-readable legal business name served by this instance + The `Instance` object describes the instance registered with the backend. + It does not include the full details, only those that usually concern the frontend. + It has the following structure: + + .. ts:def:: Instance + + interface Instance { + // Merchant name corresponding to this instance. name: string; - // Base URL of the instance. Can be of the form "/PizzaShop/" or - // a fully qualified URL (i.e. "https://backend.example.com/PizzaShop/"). - instance_baseurl: string; + // Merchant instance of the response to create + instance: string; // Public key of the merchant/instance, in Crockford Base32 encoding. merchant_pub: EddsaPublicKey; @@ -86,1621 +109,1649 @@ Getting the configuration // front-ends do not have to support wallets selecting payment targets. payment_targets: string[]; - // Base URL of the exchange this instance uses for tipping. - // Optional, only present if the instance supports tipping. - // FIXME: obsolete with current tipping API! - tipping_exchange_baseurl?: string; + } - } +.. http:post:: /instances ------------------- -Receiving Payments ------------------- + This request will be used to create a new merchant instance in the backend. -.. _post-order: + **Request:** -.. http:post:: /orders + The request must be a `InstanceConfigurationMessage`. - Create a new order that a customer can pay for. + **Response:** - This request is **not** idempotent unless an ``order_id`` is explicitly specified. - However, while repeating without an ``order_id`` will create another order, that is - generally pretty harmless (as long as only one of the orders is returned to the wallet). + :status 204 No content: + The backend has successfully created the instance. + :status 409 Conflict: + This instance already exists, but with other configuration options. + Use "PATCH" to update an instance configuration. - .. note:: + .. ts:def:: InstanceConfigurationMessage - This endpoint does not return a URL to redirect your user to confirm the - payment. In order to get this URL use :http:get:`/orders/$ORDER_ID`. The - API is structured this way since the payment redirect URL is not unique - for every order, there might be varying parameters such as the session id. + interface InstanceConfigurationMessage { + // The URI where the wallet will send coins. A merchant may have + // multiple accounts, thus this is an array. Note that by + // removing URIs from this list + payto_uris: string[]; - **Request:** + // Name of the merchant instance to create (will become $INSTANCE). + instance: string; - The request must be a `PostOrderRequest`. + // Merchant name corresponding to this instance. + name: string; - **Response:** + // The merchant's physical address (to be put into contracts). + address: Location; - :status 200 OK: - The backend has successfully created the proposal. The response is a - :ts:type:`PostOrderResponse`. - :status 404 Not found: - The order given used products from the inventory, but those were not found - in the inventory. Or the merchant instance is unknown. Details in the - error code. NOTE: no good way to find out which product is not in the - inventory, we MAY want to specify that in the reply. - :status 410 Gone: - The order given used products from the inventory that are out of stock. - The reponse is a :ts:type:`OutOfStockResponse`. + // The jurisdiction under which the merchant conducts its business + // (to be put into contracts). + jurisdiction: Location; + } - .. ts:def:: PostOrderRequest +.. http:patch:: /instances/$INSTANCE - interface PostOrderRequest { - // The order must at least contain the minimal - // order detail, but can override all - order: Order; + Update the configuration of a merchant instance. - // specifies the payment target preferred by the client. Can be used - // to select among the various (active) wire methods supported by the instance. - payment_target: string; - - // specifies that inventory management is desired. If not given, - // the backend does NOT check for the availability of stocks and - // ignores the ``product_id`` (except to possibly fill in details - // about the product, if ``auto_complete`` is requested). - manage_inventory: boolean; - - // specifies that automatically completing fields based on the - // inventory data is desired. If given, - // the backend tries to expand the products-list with additional - // information and -- if missing -- will also compute the - // total amount (as the sum of the product of price times - // quantity for all items in the order). Frontends can still override - // individual product prices or the total simply by providing them, - // for example to provide discounts. - auto_complete: boolean; + **Request** - // Specifies a lock identifier that was used to - // lock a product in the inventory. Only useful if - // ``manage_inventory`` is set. Used in case a frontend - // reserved quantities of the individual products while - // the shopping card was being built. Multiple UUIDs can - // be used in case different UUIDs were used for different - // products (i.e. in case the user started with multiple - // shopping sessions that were combined during checkout). - lock_uuids?: UUID[]; + The request must be a `InstanceUpdateMessage`. Fields that are not + provided are not modified. Removing an existing payto_uri deactivates + the account (it will no longer be used for future contracts). - } + **Response:** - type Order : MinimalOrderDetail | InventoryOrderDetail | ContractTerms; + :status 204 No content: + The backend has successfully created the instance. + :status 404 Not found: + This instance is unknown and thus cannot be reconfigured. - The following fields must be specified in the ``order`` field of the request. Other fields from - `ContractTerms` are optional, and will override the defaults in the merchant configuration. + .. ts:def:: InstanceUpdateMessage - .. ts:def:: MinimalOrderDetail + interface InstanceUpdateMessage { + // The URI where the wallet will send coins. A merchant may have + // multiple accounts, thus this is an array. Note that by + // removing URIs from this list + payto_uris?: string[]; - interface MinimalOrderDetail { - // Amount to be paid by the customer - amount: Amount; + // Merchant name corresponding to this instance. + name?: string; - // Short summary of the order - summary: string; + // The merchant's physical address (to be put into contracts). + address?: Location; - // URL that will show that the order was successful after - // it has been paid for. The wallet must always automatically append - // the order_id as a query parameter to this URL when using it. - fulfillment_url: string; + // The jurisdiction under which the merchant conducts its business + // (to be put into contracts). + jurisdiction?: Location; } - The following fields can be specified if the order is inventory-based. - In this case, the backend can compute the amounts from the prices given - in the inventory. Note that if the frontend does give more details - (towards the ContractTerms), this will override those details - (including total price) that would otherwise computed based on information - from the inventory. +.. http:get:: /instances/$INSTANCE + + This is used to query a specific merchant instance. - .. ts:def:: InventoryOrderDetail + **Response:** - interface InventoryOrderDetail { + :status 200 OK: + The backend has successfully returned the list of instances stored. Returns + a `QueryInstancesResponse`. - // List of products that are part of the purchase (see `Product`), - // possibly incomplete as details can be filled from the inventory detail. - products: ProductSpecification[]; - } + .. ts:def:: QueryInstancesResponse - type ProductSpecification : (MinimalInventoryProduct | Product); + interface QueryInstancesResponse { + // The URI where the wallet will send coins. A merchant may have + // multiple accounts, thus this is an array. + accounts: MerchantAccount[]; + // Merchant name corresponding to this instance. + name: string; - .. ts:def:: MinimalInventoryProduct + // Public key of the merchant/instance, in Crockford Base32 encoding. + merchant_pub: EddsaPublicKey; - Note that if the frontend does give details beyond these, - it will override those details (including price or taxes) - that the backend would otherwise fill in via the inventory. + // The merchant's physical address (to be put into contracts). + address: Location; - interface MinimalInventoryProduct { - // Which product is requested (here mandatory!) - product_id: string; + // The jurisdiction under which the merchant conducts its business + // (to be put into contracts). + jurisdiction: Location; - // How many units of the product are requested - quantity: integer; } + .. ts:def:: MerchantAccount - .. ts:def:: PostOrderResponse + interface MerchantAccount { - interface PostOrderResponse { - // Order ID of the response that was just created - order_id: string; - } + // payto:// URI of the account. + payto_uri: string; + // Hash over the wire details (including over the salt) + h_wire: HashCode; - .. ts:def:: OutOfStockResponse + // salt used to compute h_wire + salt: string; - interface OutOfStockResponse { - // Which items are out of stock? - missing_products: OutOfStockEntry; + // true if this account is active, + // false if it is historic. + active: boolean; } - interface OutOfStockEntry { - // Product ID of an out-of-stock item - product_id: string; - // Requested quantity - requested_quantity: integer; - // Available quantity (must be below ``requested_quanitity``) - available_quantity: integer; +.. http:delete:: /instances/$INSTANCE - // When do we expect the product to be again in stock? - // Optional, not given if unknown. - restock_expected?: timestamp; - } + This request will be used to delete (permanently disable) + or purge merchant instance in the backend. Purging will + delete all offers and payments associated with the instance, + while disabling (the default) only deletes the private key + and makes the instance unusuable for new orders or payments. + **Request:** + :query purge: *Optional*. If set to YES, the instance will be fully + deleted. Otherwise only the private key would be deleted. -.. http:get:: /orders + **Response** - Returns known orders up to some point in the past. + :status 204 NoContent: + The backend has successfully removed the instance. The response is a + `PostInstanceRemoveResponse`. + :status 404 Not found: + The instance is unknown to the backend. + :status 409 Conflict: + The instance cannot be deleted because it has pending offers, or + the instance cannot be purged because it has successfully processed + payments that have not passed the TAX_RECORD_EXPIRATION time. + The latter case only applies if ``purge`` was set. - **Request:** - :query paid: *Optional*. If set to yes, only return paid orders, if no only unpaid orders. Do not give (or use "all") to see all orders regardless of payment status. - :query aborted: *Optional*. If set to yes, only return aborted orders, if no only unaborted orders. Do not give (or use "all") to see all orders regardless of abort status. - :query refunded: *Optional*. If set to yes, only return refunded orders, if no only unrefunded orders. Do not give (or use "all") to see all orders regardless of refund status. - :query wired: *Optional*. If set to yes, only return wired orders, if no only orders with missing wire transfers. Do not give (or use "all") to see all orders regardless of wire transfer status. - :query date: *Optional.* Time threshold, see ``delta`` for its interpretation. Defaults to the oldest or most recent entry, depending on ``delta``. - :query start: *Optional*. Row number threshold, see ``delta`` for its interpretation. Defaults to ``UINT64_MAX``, namely the biggest row id possible in the database. - :query delta: *Optional*. takes value of the form ``N (-N)``, so that at most ``N`` values strictly younger (older) than ``start`` and ``date`` are returned. Defaults to ``-20``. - :query timeout_ms: *Optional*. Timeout in milli-seconds to wait for additional orders if the answer would otherwise be negative (long polling). Only useful if delta is positive. Note that the merchant MAY still return a response that contains fewer than delta orders. +-------------------- +Inventory management +-------------------- - **Response:** +.. _inventory: - :status 200 OK: - The response is an `OrderHistory`. +Inventory management is an *optional* backend feature that can be used to +manage limited stocks of products and to auto-complete product descriptions in +contracts (such that the frontends have to do less work). You can use the +Taler merchant backend to process payments *without* using its inventory +management. - .. ts:def:: OrderHistory - interface OrderHistory { - // timestamp-sorted array of all orders matching the query. - // The order of the sorting depends on the sign of ``delta``. - orders : OrderHistory[]; - } +.. http:get:: /products + This is used to return the list of all items in the inventory. - .. ts:def:: OrderHistoryEntry + **Response:** - interface OrderHistoryEntry { - // The serial number this entry has in the merchant's DB. - row_id: number; + :status 200 OK: + The backend has successfully returned the inventory. Returns + a `InventorySummaryResponse`. - // order ID of the transaction related to this entry. - order_id: string; + .. ts:def:: InventorySummaryResponse - // Transaction's timestamp - timestamp: Timestamp; + interface InventorySummaryResponse { + // List of items that are present in the inventory + items: InventoryEntry[]; + } - // Total amount the customer should pay for this order. - total: Amount; + The `InventoryEntry` object describes an item in the inventory. It has the following structure: - // Total amount the customer did pay for this order. - paid: Amount; + .. ts:def:: InventoryEntry - // Total amount the customer was refunded for this order. - // (includes abort-refund and refunds, boolean flag - // below can help determine which case it is). - refunded: Amount; + interface InventoryEntry { + // Product identifier, as found in the product. + product_id: string; - // Was the order ever fully paid? - is_paid: boolean; + // Amount of the product in stock. Given in product-specific units. + // Set to -1 for "infinite" (i.e. for "electronic" books). + stock: integer; + // unit in which the product is metered (liters, kilograms, packages, etc.) + unit: string; } +.. http:get:: /products/$PRODUCT_ID + This is used to obtain detailed information about a product in the inventory. -.. http:post:: /public/orders/$ORDER_ID/claim + **Response:** - Wallet claims ownership (via nonce) over an order. By claiming - an order, the wallet obtains the full contract terms, and thereby - implicitly also the hash of the contract terms it needs for the - other ``/public/`` APIs to authenticate itself as the wallet that - is indeed eligible to inspect this particular order's status. + :status 200 OK: + The backend has successfully returned the inventory. Returns + a `ProductDetail`. - **Request:** + .. ts:def:: ProductDetail - The request must be a `ClaimRequest` - - .. ts:def:: ClaimRequest - - interface ClaimRequest { - // Nonce to identify the wallet that claimed the order. - nonce: string; - } + interface ProductDetail { - **Response:** + // Human-readable product description. + description: string; - :status 200 OK: - The client has successfully claimed the order. - The response contains the :ref:`contract terms `. - :status 404 Not found: - The backend is unaware of the instance or order. - :status 409 Conflict: - The someone else claimed the same order ID with different nonce before. + // Map from IETF BCP 47 language tags to localized descriptions + description_i18n?: { [lang_tag: string]: string }; + // unit in which the product is measured (liters, kilograms, packages, etc.) + unit: string; -.. http:post:: /public/orders/$ORDER_ID/pay + // The price for one ``unit`` of the product. Zero is used + // to imply that this product is not sold separately, or + // that the price is not fixed, and must be supplied by the + // front-end. If non-zero, this price MUST include applicable + // taxes. + price: Amount; - Pay for an order by giving a deposit permission for coins. Typically used by - the customer's wallet. Note that this request does not include the - usual ``h_contract`` argument to authenticate the wallet, as the hash of - the contract is implied by the signatures of the coins. Furthermore, this - API doesn't really return useful information about the order. + // An optional base64-encoded product image + image?: ImageDataUrl; - **Request:** + // a list of taxes paid by the merchant for one unit of this product + taxes: Tax[]; - The request must be a `pay request `. + // Number of units of the product in stock in sum in total, + // including all existing sales ever. Given in product-specific + // units. + // A value of -1 indicates "infinite" (i.e. for "electronic" books). + total_stocked: integer; - **Response:** + // Number of units of the product that have already been sold. + total_sold: integer; - :status 200 OK: - The exchange accepted all of the coins. - The body is a `payment response `. - The ``frontend`` should now fullfill the contract. - :status 400 Bad request: - Either the client request is malformed or some specific processing error - happened that may be the fault of the client as detailed in the JSON body - of the response. - :status 403 Forbidden: - One of the coin signatures was not valid. - :status 404 Not found: - The merchant backend could not find the order or the instance - and thus cannot process the payment. - :status 409 Conflict: - The exchange rejected the payment because a coin was already spent before. - The response will include the ``coin_pub`` for which the payment failed, - in addition to the response from the exchange to the ``/deposit`` request. - :status 412 Precondition Failed: - The given exchange is not acceptable for this merchant, as it is not in the - list of accepted exchanges and not audited by an approved auditor. - :status 424 Failed Dependency: - The merchant's interaction with the exchange failed in some way. - The client might want to try later again. - This includes failures like the denomination key of a coin not being - known to the exchange as far as the merchant can tell. + // Number of units of the product that were lost (spoiled, stolen, etc.) + total_lost: integer; - The backend will return verbatim the error codes received from the exchange's - :ref:`deposit ` API. If the wallet made a mistake, like by - double-spending for example, the frontend should pass the reply verbatim to - the browser/wallet. If the payment was successful, the frontend MAY use - this to trigger some business logic. + // Number of units of the product that are currently locked by some + // shopping cart. + total_locked: integer; - .. ts:def:: PaymentResponse + // Identifies where the product is in stock. + location?: Location; - interface PaymentResponse { - // Signature on ``TALER_PaymentResponsePS`` with the public - // key of the merchant instance. - sig: EddsaSignature; + // Identifies when we expect the next restocking to happen. + next_restock?: timestamp; } - .. ts:def:: PayRequest - interface PayRequest { - coins: CoinPaySig[]; - } +.. http:post:: /products - .. ts:def:: CoinPaySig + This is used to add a product to the inventory. - export interface CoinPaySig { - // Signature by the coin. - coin_sig: string; + **Request:** - // Public key of the coin being spend. - coin_pub: string; + The request must be a `ProductAddDetail`. - // Signature made by the denomination public key. - ub_sig: string; + **Response:** - // The denomination public key associated with this coin. - denom_pub: string; + :status 204 No content: + The backend has successfully expanded the inventory. + :status 409 Conflict: + The backend already knows a product with this product ID, but with different details. - // The amount that is subtracted from this coin with this payment. - contribution: Amount; - // URL of the exchange this coin was withdrawn from. - exchange_url: string; - } + .. ts:def:: ProductAddDetail + interface ProductAddDetail { -.. http:post:: /public/orders/$ORDER_ID/abort + // product ID to use. + product_id: string; - Abort paying for an order and obtain a refund for coins that - were already deposited as part of a failed payment. + // Human-readable product description. + description: string; - **Request:** + // Map from IETF BCP 47 language tags to localized descriptions + description_i18n?: { [lang_tag: string]: string }; - The request must be an `abort request `. + // unit in which the product is measured (liters, kilograms, packages, etc.) + unit: string; - :query h_contract: hash of the order's contract terms (this is used to authenticate the wallet/customer in case $ORDER_ID is guessable). *Mandatory!* + // The price for one ``unit`` of the product. Zero is used + // to imply that this product is not sold separately, or + // that the price is not fixed, and must be supplied by the + // front-end. If non-zero, this price MUST include applicable + // taxes. + price: Amount; - **Response:** + // An optional base64-encoded product image + image?: ImageDataUrl; - :status 200 OK: - The exchange accepted all of the coins. The body is a - a `merchant refund response `. - :status 400 Bad request: - Either the client request is malformed or some specific processing error - happened that may be the fault of the client as detailed in the JSON body - of the response. - :status 403 Forbidden: - The ``h_contract`` does not match the order. - :status 404 Not found: - The merchant backend could not find the order or the instance - and thus cannot process the abort request. - :status 412 Precondition Failed: - Aborting the payment is not allowed, as the original payment did succeed. - :status 424 Failed Dependency: - The merchant's interaction with the exchange failed in some way. - The error from the exchange is included. + // a list of taxes paid by the merchant for one unit of this product + taxes: Tax[]; - The backend will return verbatim the error codes received from the exchange's - :ref:`refund ` API. The frontend should pass the replies verbatim to - the browser/wallet. + // Number of units of the product in stock in sum in total, + // including all existing sales ever. Given in product-specific + // units. + // A value of -1 indicates "infinite" (i.e. for "electronic" books). + total_stocked: integer; - .. ts:def:: AbortRequest + // Identifies where the product is in stock. + location?: Location; - interface AbortRequest { - // List of coins the wallet would like to see refunds for. - // (Should be limited to the coins for which the original - // payment succeeded, as far as the wallet knows.) - coins: AbortedCoin[]; - } + // Identifies when we expect the next restocking to happen. + next_restock?: timestamp; - interface AbortedCoin { - // Public key of a coin for which the wallet is requesting an abort-related refund. - coin_pub: EddsaPublicKey; } -.. http:get:: /orders/$ORDER_ID/ +.. http:patch:: /products/$PRODUCT_ID - Merchant checks the payment status of an order. If the order exists but is not payed - yet, the response provides a redirect URL. When the user goes to this URL, - they will be prompted for payment. Differs from the ``/public/`` API both - in terms of what information is returned and in that the wallet must provide - the contract hash to authenticate, while for this API we assume that the - merchant is authenticated (as the endpoint is not ``/public/``). + This is used to update product details in the inventory. Note that the + ``total_stocked`` and ``total_lost`` numbers MUST be greater or equal than + previous values (this design ensures idempotency). In case stocks were lost + but not sold, increment the ``total_lost`` number. All fields in the + request are optional, those that are not given are simply preserved (not + modified). Note that the ``description_i18n`` and ``taxes`` can only be + modified in bulk: if it is given, all translations must be provided, not + only those that changed. "never" should be used for the ``next_restock`` + timestamp to indicate no intention/possibility of restocking, while a time + of zero is used to indicate "unknown". + + Limitations: you cannot remove a ``location`` from a product that used to + have a location. **Request:** - :query session_id: *Optional*. Session ID that the payment must be bound to. If not specified, the payment is not session-bound. - :query transfer: *Optional*. If set to "YES", try to obtain the wire transfer status for this order from the exchange. Otherwise, the wire transfer status MAY be returned if it is available. - :query timeout_ms: *Optional*. Timeout in milli-seconds to wait for a payment if the answer would otherwise be negative (long polling). + The request must be a `ProductPatchDetail`. **Response:** - :status 200 OK: - Returns a `MerchantOrderStatusResponse`, whose format can differ based on the status of the payment. - :status 404 Not Found: - The order or instance is unknown to the backend. - :status 409 Conflict: - The exchange previously claimed that a deposit was not included in a wire - transfer, and now claims that it is. This means that the exchange is - dishonest. The response contains the cryptographic proof that the exchange - is misbehaving in the form of a `TransactionConflictProof`. - :status 424 Failed dependency: - We failed to obtain a response from the exchange about the - wire transfer status. - - .. ts:def:: MerchantOrderStatusResponse - - type MerchantOrderStatusResponse = CheckPaymentPaidResponse | CheckPaymentUnpaidResponse - - .. ts:def:: CheckPaymentPaidResponse - - interface CheckPaymentPaidResponse { - paid: true; - - // Was the payment refunded (even partially) - refunded: boolean; - - // Amount that was refunded, only present if refunded is true. - refund_amount?: Amount; + :status 204 No content: + The backend has successfully expanded the inventory. - // Contract terms - contract_terms: ContractTerms; - // If available, the wire transfer status from the exchange for this order - wire_details?: TransactionWireTransfer; - } + interface ProductPatchDetail { - .. ts:def:: CheckPaymentUnpaidResponse + // Human-readable product description. + description?: string; - interface CheckPaymentUnpaidResponse { - paid: false; + // Map from IETF BCP 47 language tags to localized descriptions + description_i18n?: { [lang_tag: string]: string }; - // URI that the wallet must process to complete the payment. - taler_pay_uri: string; + // unit in which the product is measured (liters, kilograms, packages, etc.) + unit?: string; - // Alternative order ID which was paid for already in the same session. - // Only given if the same product was purchased before in the same session. - already_paid_order_id?: string; + // The price for one ``unit`` of the product. Zero is used + // to imply that this product is not sold separately, or + // that the price is not fixed, and must be supplied by the + // front-end. If non-zero, this price MUST include applicable + // taxes. + price?: Amount; - // FIXME: why do we NOT return the contract terms here? - } + // An optional base64-encoded product image + image?: ImageDataUrl; - .. ts:def:: TransactionWireTransfer + // a list of taxes paid by the merchant for one unit of this product + taxes?: Tax[]; - interface TransactionWireTransfer { + // Number of units of the product in stock in sum in total, + // including all existing sales ever. Given in product-specific + // units. + // A value of -1 indicates "infinite" (i.e. for "electronic" books). + total_stocked?: integer; - // Responsible exchange - exchange_uri: string; + // Number of units of the product that were lost (spoiled, stolen, etc.) + total_lost?: integer; - // 32-byte wire transfer identifier - wtid: Base32; + // Identifies where the product is in stock. + location?: Location; - // execution time of the wire transfer - execution_time: Timestamp; + // Identifies when we expect the next restocking to happen. + next_restock?: timestamp; - // Total amount that has been wire transfered - // to the merchant - amount: Amount; } - .. ts:def:: TransactionConflictProof - - interface TransactionConflictProof { - // Numerical `error code ` - code: number; - - // Human-readable error description - hint: string; - - // A claim by the exchange about the transactions associated - // with a given wire transfer; it does not list the - // transaction that ``transaction_tracking_claim`` says is part - // of the aggregate. This is - // a ``/track/transfer`` response from the exchange. - wtid_tracking_claim: TrackTransferResponse; - - // The current claim by the exchange that the given - // transaction is included in the above WTID. - // (A response from ``/track/order``). - transaction_tracking_claim: TrackTransactionResponse; - // Public key of the coin for which we got conflicting information. - coin_pub: CoinPublicKey; - - } +.. http:post:: /products/$PRODUCT_ID/lock -.. http:get:: /public/orders/$ORDER_ID/ + This is used to lock a certain quantity of the product for a limited + duration while the customer assembles a complete order. Note that + frontends do not have to "unlock", they may rely on the timeout as + given in the ``duration`` field. Re-posting a lock with a different + ``duration`` or ``quantity`` updates the existing lock for the same UUID + and does not result in a conflict. - Query the payment status of an order. This endpoint is for the wallet. - When the wallet goes to this URL and it is unpaid, - they will be prompted for payment. + Unlocking by using a ``quantity`` of zero is is + optional but recommended if customers remove products from the + shopping cart. Note that actually POSTing to ``/orders`` with set + ``manage_inventory`` and using ``lock_uuid`` will **transition** the + lock to the newly created order (which may have a different ``duration`` + and ``quantity`` than what was requested in the lock operation). + If an order is for fewer items than originally locked, the difference + is automatically unlocked. **Request:** - :query h_contract: hash of the order's contract terms (this is used to authenticate the wallet/customer in case $ORDER_ID is guessable). *Mandatory!* - :query session_id: *Optional*. Session ID that the payment must be bound to. If not specified, the payment is not session-bound. - :query timeout_ms: *Optional.* If specified, the merchant backend will - wait up to ``timeout_ms`` milliseconds for completion of the payment before - sending the HTTP response. A client must never rely on this behavior, as the - merchant backend may return a response immediately. - :query refund=AMOUNT: *Optional*. Indicates that we are polling for a refund above the given AMOUNT. Only useful in combination with timeout. + The request must be a `LockRequest`. **Response:** - :status 200 OK: - The response is a `PublicPayStatusResponse`, with ``paid`` true. - FIXME: what about refunded? - :status 402 Payment required: - The response is a `PublicPayStatusResponse`, with ``paid`` false. - FIXME: what about refunded? - :status 403 Forbidden: - The ``h_contract`` does not match the order. + :status 204 No content: + The backend has successfully locked (or unlocked) the requested ``quantity``. :status 404 Not found: - The merchant backend is unaware of the order. - - .. ts:def:: PublicPayStatusResponse - - interface PublicPayStatusResponse { - // Has the payment for this order (ever) been completed? - paid: boolean; + The backend has does not know this product. + :status 410 Gone: + The backend does not have enough of product in stock. - // Was the payment refunded (even partially, via refund or abort)? - refunded: boolean; + .. ts:def:: LockRequest - // Amount that was refunded in total. - refund_amount: Amount; + interface LockRequest { - // Refunds for this payment, empty array for none. - refunds: RefundDetail[]; + // UUID that identifies the frontend performing the lock + lock_uuid: UUID; - // URI that the wallet must process to complete the payment. - taler_pay_uri: string; + // How long does the frontend intend to hold the lock + duration: time; - // Alternative order ID which was paid for already in the same session. - // Only given if the same product was purchased before in the same session. - already_paid_order_id?: string; + // How many units should be locked? + quantity: integer; } -.. http:delete:: /orders/$ORDER_ID - Delete information about an order. Fails if the order was paid in the - last 10 years (or whatever TAX_RECORD_EXPIRATION is set to) or was - claimed but is unpaid and thus still a valid offer. - **Response:** +------------------ +Receiving Payments +------------------ - :status 204 No content: - The backend has successfully deleted the order. - :status 404 Not found: - The backend does not know the instance or the order. - :status 409 Conflict: - The backend refuses to delete the order. +.. _post-order: +.. http:post:: /orders --------------- -Giving Refunds --------------- + Create a new order that a customer can pay for. + This request is **not** idempotent unless an ``order_id`` is explicitly specified. + However, while repeating without an ``order_id`` will create another order, that is + generally pretty harmless (as long as only one of the orders is returned to the wallet). -.. http:post:: /orders/$ORDER_ID/refund + .. note:: - Increase the refund amount associated with a given order. The user should be - redirected to the ``taler_refund_url`` to trigger refund processing in the wallet. + This endpoint does not return a URL to redirect your user to confirm the + payment. In order to get this URL use :http:get:`/orders/$ORDER_ID`. The + API is structured this way since the payment redirect URL is not unique + for every order, there might be varying parameters such as the session id. **Request:** - The request body is a `RefundRequest` object. + The request must be a `PostOrderRequest`. **Response:** :status 200 OK: - The refund amount has been increased, the backend responds with a `MerchantRefundResponse` + The backend has successfully created the proposal. The response is a + :ts:type:`PostOrderResponse`. :status 404 Not found: - The order is unknown to the merchant - :status 409 Conflict: - The refund amount exceeds the amount originally paid + The order given used products from the inventory, but those were not found + in the inventory. Or the merchant instance is unknown. Details in the + error code. NOTE: no good way to find out which product is not in the + inventory, we MAY want to specify that in the reply. + :status 410 Gone: + The order given used products from the inventory that are out of stock. + The reponse is a :ts:type:`OutOfStockResponse`. - .. ts:def:: RefundRequest - interface RefundRequest { - // Amount to be refunded - refund: Amount; + .. ts:def:: PostOrderRequest - // Human-readable refund justification - reason: string; - } + interface PostOrderRequest { + // The order must at least contain the minimal + // order detail, but can override all + order: Order; - .. ts:def:: MerchantRefundResponse + // specifies the payment target preferred by the client. Can be used + // to select among the various (active) wire methods supported by the instance. + payment_target?: string; - interface MerchantRefundResponse { + // specifies that some products are to be included in the + // order from the inventory. For these inventory management + // is performed (so the products must be in stock) and + // details are completed from the product data of the backend. + inventory_products?: MinimalInventoryProduct[]; - // Hash of the contract terms of the contract that is being refunded. - // FIXME: why do we return this? - h_contract_terms: HashCode; + // Specifies a lock identifier that was used to + // lock a product in the inventory. Only useful if + // ``manage_inventory`` is set. Used in case a frontend + // reserved quantities of the individual products while + // the shopping card was being built. Multiple UUIDs can + // be used in case different UUIDs were used for different + // products (i.e. in case the user started with multiple + // shopping sessions that were combined during checkout). + lock_uuids?: UUID[]; - // URL (handled by the backend) that the wallet should access to - // trigger refund processing. - // FIXME: isn't this basically now always ``/public/orders/$ORDER_ID/``? - // If so, why return this? - taler_refund_url: string; } + type Order : MinimalOrderDetail | ContractTerms; + The following fields must be specified in the ``order`` field of the request. Other fields from + `ContractTerms` are optional, and will override the defaults in the merchant configuration. ------------------------- -Tracking Wire Transfers ------------------------- - -.. http:post:: /transfers + .. ts:def:: MinimalOrderDetail - Inform the backend over an incoming wire transfer. The backend should inquire about the details with the exchange and mark the respective orders as wired. Note that the request will fail if the WTID is not unique (which should be guaranteed by a correct exchange). + interface MinimalOrderDetail { + // Amount to be paid by the customer + amount: Amount; - **Request:** + // Short summary of the order + summary: string; - The request must provide `transfer information `. + // URL that will show that the order was successful after + // it has been paid for. The wallet must always automatically append + // the order_id as a query parameter to this URL when using it. + fulfillment_url: string; + } - **Response:** + The following fields can be specified if the order is inventory-based. + In this case, the backend can compute the amounts from the prices given + in the inventory. Note that if the frontend does give more details + (towards the ContractTerms), this will override those details + (including total price) that would otherwise computed based on information + from the inventory. - :status 200 OK: - The wire transfer is known to the exchange, details about it follow in the body. - The body of the response is a `TrackTransferResponse`. Note that - the similarity to the response given by the exchange for a /track/transfer - is completely intended. + type ProductSpecification : (MinimalInventoryProduct | Product); - :status 404 Not Found: - The wire transfer identifier is unknown to the exchange. - :status 409 Conflict: - The wire transfer identifier is already known to us, but for a different amount, - wire method or exchange. + .. ts:def:: MinimalInventoryProduct - :status 424 Failed Dependency: The exchange provided conflicting information about the transfer. Namely, - there is at least one deposit among the deposits aggregated by ``wtid`` that accounts for a coin whose - details don't match the details stored in merchant's database about the same keyed coin. - The response body contains the `TrackTransferConflictDetails`. + Note that if the frontend does give details beyond these, + it will override those details (including price or taxes) + that the backend would otherwise fill in via the inventory. - .. ts:def:: TransferInformation + interface MinimalInventoryProduct { + // Which product is requested (here mandatory!) + product_id: string; - interface TransferInformation { - // how much was wired to the merchant (minus fees) - credit_amount: Amount; + // How many units of the product are requested + quantity: integer; + } - // raw wire transfer identifier identifying the wire transfer (a base32-encoded value) - wtid: FIXME; - // name of the wire transfer method used for the wire transfer - // FIXME: why not a payto URI? - wire_method; + .. ts:def:: PostOrderResponse - // base URL of the exchange that made the wire transfer - exchange: string; + interface PostOrderResponse { + // Order ID of the response that was just created + order_id: string; } - .. ts:def:: TrackTransferResponse - interface TrackTransferResponse { - // Total amount transferred - total: Amount; + .. ts:def:: OutOfStockResponse - // Applicable wire fee that was charged - wire_fee: Amount; + interface OutOfStockResponse { + // Which items are out of stock? + missing_products: OutOfStockEntry; + } - // public key of the merchant (identical for all deposits) - // FIXME: why return this? - merchant_pub: EddsaPublicKey; + interface OutOfStockEntry { + // Product ID of an out-of-stock item + product_id: string; - // hash of the wire details (identical for all deposits) - // FIXME: why return this? Isn't this the WTID!? - h_wire: HashCode; + // Requested quantity + requested_quantity: integer; - // Time of the execution of the wire transfer by the exchange, according to the exchange - execution_time: Timestamp; + // Available quantity (must be below ``requested_quanitity``) + available_quantity: integer; - // details about the deposits - deposits_sums: TrackTransferDetail[]; + // When do we expect the product to be again in stock? + // Optional, not given if unknown. + restock_expected?: timestamp; + } - // signature from the exchange made with purpose - // ``TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT`` - // FIXME: why return this? - exchange_sig: EddsaSignature; - // public EdDSA key of the exchange that was used to generate the signature. - // Should match one of the exchange's signing keys from /keys. Again given - // explicitly as the client might otherwise be confused by clock skew as to - // which signing key was used. - // FIXME: why return this? - exchange_pub: EddsaSignature; - } - .. ts:def:: TrackTransferDetail +.. http:get:: /orders - interface TrackTransferDetail { - // Business activity associated with the wire transferred amount - // ``deposit_value``. - order_id: string; + Returns known orders up to some point in the past. - // The total amount the exchange paid back for ``order_id``. - deposit_value: Amount; + **Request:** - // applicable fees for the deposit - deposit_fee: Amount; - } + :query paid: *Optional*. If set to yes, only return paid orders, if no only unpaid orders. Do not give (or use "all") to see all orders regardless of payment status. + :query refunded: *Optional*. If set to yes, only return refunded orders, if no only unrefunded orders. Do not give (or use "all") to see all orders regardless of refund status. + :query wired: *Optional*. If set to yes, only return wired orders, if no only orders with missing wire transfers. Do not give (or use "all") to see all orders regardless of wire transfer status. + :query date: *Optional.* Time threshold, see ``delta`` for its interpretation. Defaults to the oldest or most recent entry, depending on ``delta``. + :query start: *Optional*. Row number threshold, see ``delta`` for its interpretation. Defaults to ``UINT64_MAX``, namely the biggest row id possible in the database. + :query delta: *Optional*. takes value of the form ``N (-N)``, so that at most ``N`` values strictly younger (older) than ``start`` and ``date`` are returned. Defaults to ``-20``. + :query timeout_ms: *Optional*. Timeout in milli-seconds to wait for additional orders if the answer would otherwise be negative (long polling). Only useful if delta is positive. Note that the merchant MAY still return a response that contains fewer than delta orders. + **Response:** - **Details:** + :status 200 OK: + The response is an `OrderHistory`. - .. ts:def:: TrackTransferConflictDetails + .. ts:def:: OrderHistory - interface TrackTransferConflictDetails { - // Numerical `error code ` - code: number; + interface OrderHistory { + // timestamp-sorted array of all orders matching the query. + // The order of the sorting depends on the sign of ``delta``. + orders : OrderHistory[]; + } - // Text describing the issue for humans. - hint: string; - // A /deposit response matching ``coin_pub`` showing that the - // exchange accepted ``coin_pub`` for ``amount_with_fee``. - exchange_deposit_proof: DepositSuccess; + .. ts:def:: OrderHistoryEntry - // Offset in the ``exchange_transfer_proof`` where the - // exchange's response fails to match the ``exchange_deposit_proof``. - conflict_offset: number; + interface OrderHistoryEntry { + // The serial number this entry has in the merchant's DB. + row_id: number; - // The response from the exchange which tells us when the - // coin was returned to us, except that it does not match - // the expected value of the coin. - exchange_transfer_proof: TrackTransferResponse; + // order ID of the transaction related to this entry. + order_id: string; - // Public key of the coin for which we have conflicting information. - coin_pub: EddsaPublicKey; + // Transaction's timestamp + timestamp: Timestamp; - // Merchant transaction in which ``coin_pub`` was involved for which - // we have conflicting information. - transaction_id: number; + // Total amount the customer should pay for this order. + total: Amount; - // Expected value of the coin. - amount_with_fee: Amount; + // Total amount the customer did pay for this order. Payments + // that were later aborted (/abort) are NOT included. + paid: Amount; - // Expected deposit fee of the coin. - deposit_fee: Amount; + // Total amount the customer was refunded for this order. + // (excludes refunds from aborts). + refunded: Amount; - } + // Was the order fully paid? + is_paid: boolean; + } -.. http:get:: /transfers - Obtain a list of all wire transfers the backend has checked. - **Request:** +.. http:post:: /public/orders/$ORDER_ID/claim - :query filter: FIXME: should have a way to filter, maybe even long-poll? + Wallet claims ownership (via nonce) over an order. By claiming + an order, the wallet obtains the full contract terms, and thereby + implicitly also the hash of the contract terms it needs for the + other ``/public/`` APIs to authenticate itself as the wallet that + is indeed eligible to inspect this particular order's status. - **Response:** + **Request:** - FIXME: to be specified. + The request must be a `ClaimRequest` + .. ts:def:: ClaimRequest + interface ClaimRequest { + // Nonce to identify the wallet that claimed the order. + nonce: string; + } --------------------- -Giving Customer Tips --------------------- + **Response:** + :status 200 OK: + The client has successfully claimed the order. + The response contains the :ref:`contract terms `. + :status 404 Not found: + The backend is unaware of the instance or order. + :status 409 Conflict: + The someone else claimed the same order ID with different nonce before. -.. http:post:: /reserves - Create a reserve for tipping. +.. http:post:: /public/orders/$ORDER_ID/pay - This request is **not** idempotent. However, while repeating - it will create another reserve, that is generally pretty harmless - (assuming only one of the reserves is filled with a wire transfer). - Clients may want to eventually delete the unused reserves to - avoid clutter. + Pay for an order by giving a deposit permission for coins. Typically used by + the customer's wallet. Note that this request does not include the + usual ``h_contract`` argument to authenticate the wallet, as the hash of + the contract is implied by the signatures of the coins. Furthermore, this + API doesn't really return useful information about the order. **Request:** - The request body is a `ReserveCreateRequest` object. + The request must be a `pay request `. **Response:** :status 200 OK: - The backend is waiting for the reserve to be established. The merchant - must now perform the wire transfer indicated in the `ReserveCreateConfirmation`. - :status 424 Failed Depencency: - We could not obtain /wire details from the specified exchange base URL. - - .. ts:def:: ReserveCreateRequest - - interface ReserveCreateRequest { - // Amount that the merchant promises to put into the reserve - initial_amount: Amount; + The exchange accepted all of the coins. + The body is a `payment response `. + The ``frontend`` should now fullfill the contract. + :status 400 Bad request: + Either the client request is malformed or some specific processing error + happened that may be the fault of the client as detailed in the JSON body + of the response. + :status 403 Forbidden: + One of the coin signatures was not valid. + :status 404 Not found: + The merchant backend could not find the order or the instance + and thus cannot process the payment. + :status 409 Conflict: + The exchange rejected the payment because a coin was already spent before. + The response will include the ``coin_pub`` for which the payment failed, + in addition to the response from the exchange to the ``/deposit`` request. + :status 412 Precondition Failed: + The given exchange is not acceptable for this merchant, as it is not in the + list of accepted exchanges and not audited by an approved auditor. + :status 424 Failed Dependency: + The merchant's interaction with the exchange failed in some way. + The client might want to try later again. + This includes failures like the denomination key of a coin not being + known to the exchange as far as the merchant can tell. - // Exchange the merchant intends to use for tipping - exchange_base_url: string; + The backend will return verbatim the error codes received from the exchange's + :ref:`deposit ` API. If the wallet made a mistake, like by + double-spending for example, the frontend should pass the reply verbatim to + the browser/wallet. If the payment was successful, the frontend MAY use + this to trigger some business logic. - } + .. ts:def:: PaymentResponse - .. ts:def:: ReserveCreateConfirmation + interface PaymentResponse { + // Signature on ``TALER_PaymentResponsePS`` with the public + // key of the merchant instance. + sig: EddsaSignature; - interface ReserveCreateConfirmation { - // Public key identifying the reserve - reserve_pub: EddsaPublicKey; + } - // Wire account of the exchange where to transfer the funds - payto_url: string; + .. ts:def:: PayRequest + interface PayRequest { + coins: CoinPaySig[]; } -.. http:get:: /reserves + .. ts:def:: CoinPaySig - Obtain list of reserves that have been created for tipping. + export interface CoinPaySig { + // Signature by the coin. + coin_sig: string; - **Request:** + // Public key of the coin being spend. + coin_pub: string; - :query after: *Optional*. Only return reserves created after the given timestamp [FIXME: unit?] + // Signature made by the denomination public key. + ub_sig: string; - **Response:** + // The denomination public key associated with this coin. + denom_pub: string; - :status 200 OK: - Returns a list of known tipping reserves. - The body is a `TippingReserveStatus`. + // The amount that is subtracted from this coin with this payment. + contribution: Amount; - .. ts:def:: TippingReserveStatus + // URL of the exchange this coin was withdrawn from. + exchange_url: string; + } - interface TippingReserveStatus { - // Array of all known reserves (possibly empty!) - reserves: ReserveStatusEntry[]; +.. http:post:: /public/orders/$ORDER_ID/abort - } + Abort paying for an order and obtain a refund for coins that + were already deposited as part of a failed payment. - .. ts:def:: ReserveStatusEntry + **Request:** - interface ReserveStatusEntry { + The request must be an `abort request `. - // Public key of the reserve - reserve_pub: EddsaPublicKey; + **Response:** - // Timestamp when it was established - creation_time: Timestamp; + :status 200 OK: + The exchange accepted all of the coins. The body is a + a `merchant refund response `. + :status 400 Bad request: + Either the client request is malformed or some specific processing error + happened that may be the fault of the client as detailed in the JSON body + of the response. + :status 403 Forbidden: + The ``h_contract`` does not match the $ORDER_ID. + :status 404 Not found: + The merchant backend could not find the order or the instance + and thus cannot process the abort request. + :status 412 Precondition Failed: + Aborting the payment is not allowed, as the original payment did succeed. + :status 424 Failed Dependency: + The merchant's interaction with the exchange failed in some way. + The error from the exchange is included. - // Timestamp when it expires - expiration_time: Timestamp; + The backend will return verbatim the error codes received from the exchange's + :ref:`refund <_refund>` API. The frontend should pass the replies verbatim to + the browser/wallet. - // Initial amount as per reserve creation call - merchant_initial_amount: Amount; + .. ts:def:: AbortRequest - // Initial amount as per exchange, 0 if exchange did - // not confirm reserve creation yet. - exchange_initial_amount: Amount; + interface AbortRequest { - // Amount picked up so far. - pickup_amount: Amount; + // hash of the order's contract terms (this is used to authenticate the + // wallet/customer in case $ORDER_ID is guessable). + h_contract: HashCode; - // Amount approved for tips that exceeds the pickup_amount. - committed_amount: Amount; - // Is this reserve active (false if it was deleted but not purged) - active: boolean; + // List of coins the wallet would like to see refunds for. + // (Should be limited to the coins for which the original + // payment succeeded, as far as the wallet knows.) + coins: AbortedCoin[]; } + interface AbortedCoin { + // Public key of a coin for which the wallet is requesting an abort-related refund. + coin_pub: EddsaPublicKey; + } -.. http:get:: /reserves/$RESERVE_PUB - Obtain information about a specific reserve that have been created for tipping. - **Request:** +.. http:get:: /orders/$ORDER_ID/ - :query tips: *Optional*. If set to "yes", returns also information about all of the tips created + Merchant checks the payment status of an order. If the order exists but is not payed + yet, the response provides a redirect URL. When the user goes to this URL, + they will be prompted for payment. Differs from the ``/public/`` API both + in terms of what information is returned and in that the wallet must provide + the contract hash to authenticate, while for this API we assume that the + merchant is authenticated (as the endpoint is not ``/public/``). - **Response:** + **Request:** - :status 200 OK: - Returns the `ReserveDetail`. - :status 404 Not found: - The tipping reserve is not known. - :status 424 Failed Dependency: - We are having trouble with the request because of a problem with the exchange. - Likely returned with an "exchange_code" in addition to a "code" and - an "exchange_http_status" in addition to our own HTTP status. Also usually - includes the full exchange reply to our request under "exchange_reply". - This is only returned if there was actual trouble with the exchange, not - if the exchange merely did not respond yet or if it responded that the - reserve was not yet filled. + :query session_id: *Optional*. Session ID that the payment must be bound to. If not specified, the payment is not session-bound. + :query transfer: *Optional*. If set to "YES", try to obtain the wire transfer status for this order from the exchange. Otherwise, the wire transfer status MAY be returned if it is available. + :query timeout_ms: *Optional*. Timeout in milli-seconds to wait for a payment if the answer would otherwise be negative (long polling). - .. ts:def:: ReserveDetail + **Response:** - interface ReserveDetail { + :status 200 OK: + Returns a `MerchantOrderStatusResponse`, whose format can differ based on the status of the payment. + :status 404 Not Found: + The order or instance is unknown to the backend. + :status 409 Conflict: + The exchange previously claimed that a deposit was not included in a wire + transfer, and now claims that it is. This means that the exchange is + dishonest. The response contains the cryptographic proof that the exchange + is misbehaving in the form of a `TransactionConflictProof`. + :status 424 Failed dependency: + We failed to obtain a response from the exchange about the + wire transfer status. - // Timestamp when it was established - creation_time: Timestamp; + .. ts:def:: MerchantOrderStatusResponse - // Timestamp when it expires - expiration_time: Timestamp; + type MerchantOrderStatusResponse = CheckPaymentPaidResponse | CheckPaymentUnpaidResponse - // Initial amount as per reserve creation call - merchant_initial_amount: Amount; + .. ts:def:: CheckPaymentPaidResponse - // Initial amount as per exchange, 0 if exchange did - // not confirm reserve creation yet. - exchange_initial_amount: Amount; + interface CheckPaymentPaidResponse { + paid: true; - // Amount picked up so far. - pickup_amount: Amount; + // Was the payment refunded (even partially) + refunded: boolean; - // Amount approved for tips that exceeds the pickup_amount. - committed_amount: Amount; + // Amount that was refunded, only present if refunded is true. + refund_amount?: Amount; - // Array of all tips created by this reserves (possibly empty!). - // Only present if asked for explicitly. - tips?: TipStatusEntry[]; + // Contract terms + contract_terms: ContractTerms; + // If available, the wire transfer status from the exchange for this order + wire_details?: TransactionWireTransfer; } - .. ts:def:: TipStatusEntry - - interface TipStatusEntry { + .. ts:def:: CheckPaymentUnpaidResponse - // Unique identifier for the tip - tip_id: HashCode; + interface CheckPaymentUnpaidResponse { + paid: false; - // Total amount of the tip that can be withdrawn. - total_amount: Amount; + // URI that the wallet must process to complete the payment. + taler_pay_uri: string; - // Human-readable reason for why the tip was granted. - reason: String; + // Alternative order ID which was paid for already in the same session. + // Only given if the same product was purchased before in the same session. + already_paid_order_id?: string; + // We do we NOT return the contract terms here because they may not + // exist in case the wallet did not yet claim them. } + .. ts:def:: TransactionWireTransfer -.. http:post:: /reserves/$RESERVE_PUB/authorize-tip - - Authorize creation of a tip from the given reserve. - - **Request:** - - The request body is a `TipCreateRequest` object. + interface TransactionWireTransfer { - **Response:** + // Responsible exchange + exchange_uri: string; - :status 200 OK: - A tip has been created. The backend responds with a `TipCreateConfirmation` - :status 404 Not Found: - The instance or the reserve is unknown to the backend. - :status 412 Precondition Failed: - The tip amount requested exceeds the available reserve balance for tipping. + // 32-byte wire transfer identifier + wtid: Base32; - .. ts:def:: TipCreateRequest + // execution time of the wire transfer + execution_time: Timestamp; - interface TipCreateRequest { - // Amount that the customer should be tipped + // Total amount that has been wire transfered + // to the merchant amount: Amount; - - // Justification for giving the tip - justification: string; - - // URL that the user should be directed to after tipping, - // will be included in the tip_token. - next_url: string; } - .. ts:def:: TipCreateConfirmation + .. ts:def:: TransactionConflictProof - interface TipCreateConfirmation { - // Unique tip identifier for the tip that was created. - tip_id: HashCode; + interface TransactionConflictProof { + // Numerical `error code ` + code: number; - // Token that will be handed to the wallet, - // contains all relevant information to accept - // a tip. - tip_token: string; + // Human-readable error description + hint: string; - // URL that will directly trigger processing - // the tip when the browser is redirected to it - tip_redirect_url: string; + // A claim by the exchange about the transactions associated + // with a given wire transfer; it does not list the + // transaction that ``transaction_tracking_claim`` says is part + // of the aggregate. This is + // a ``/track/transfer`` response from the exchange. + wtid_tracking_claim: TrackTransferResponse; + + // The current claim by the exchange that the given + // transaction is included in the above WTID. + // (A response from ``/track/order``). + transaction_tracking_claim: TrackTransactionResponse; + + // Public key of the coin for which we got conflicting information. + coin_pub: CoinPublicKey; } -.. http:post:: /tips +.. http:get:: /public/orders/$ORDER_ID/ - Authorize creation of a tip from the given reserve, except with - automatic selection of a working reserve of the instance by the - backend. Intentionally otherwise identical to the /authorize-tip - endpoint given above. + Query the payment status of an order. This endpoint is for the wallet. + When the wallet goes to this URL and it is unpaid, + they will be prompted for payment. **Request:** - The request body is a `TipCreateRequest` object. + :query h_contract: hash of the order's contract terms (this is used to authenticate the wallet/customer in case $ORDER_ID is guessable). *Mandatory!* + :query session_id: *Optional*. Session ID that the payment must be bound to. If not specified, the payment is not session-bound. + :query timeout_ms: *Optional.* If specified, the merchant backend will + wait up to ``timeout_ms`` milliseconds for completion of the payment before + sending the HTTP response. A client must never rely on this behavior, as the + merchant backend may return a response immediately. + :query refund=AMOUNT: *Optional*. Indicates that we are polling for a refund above the given AMOUNT. Only useful in combination with timeout. **Response:** :status 200 OK: - A tip has been created. The backend responds with a `TipCreateConfirmation` - :status 404 Not Found: - The instance is unknown to the backend. - :status 412 Precondition Failed: - The tip amount requested exceeds the available reserve balance for tipping - in all of the reserves of the instance. - + The response is a `PublicPayStatusResponse`, with ``paid`` true. + :status 403 Forbidden: + The ``h_contract`` does not match the order. + :status 404 Not found: + The merchant backend is unaware of the order. -.. http:delete:: /reserves/$RESERVE_PUB + .. ts:def:: PublicPayStatusResponse - Delete information about a reserve. Fails if the reserve still has - committed to tips that were not yet picked up and that have not yet - expired. + interface PublicPayStatusResponse { + // Has the payment for this order (ever) been completed? + paid: boolean; - **Request:** + // Was the payment refunded (even partially, via refund or abort)? + refunded: boolean; - :query purge: *Optional*. If set to YES, the reserve and all information - about tips it issued will be fully deleted. - Otherwise only the private key would be deleted. + // Amount that was refunded in total. + refund_amount: Amount; - **Response:** + // Refunds for this payment, empty array for none. + refunds: RefundDetail[]; - :status 204 No content: - The backend has successfully deleted the reserve. - :status 404 Not found: - The backend does not know the instance or the reserve. - :status 409 Conflict: - The backend refuses to delete the reserve (committed tips awaiting pickup). + // URI that the wallet must process to complete the payment. + taler_pay_uri: string; + // Alternative order ID which was paid for already in the same session. + // Only given if the same product was purchased before in the same session. + already_paid_order_id?: string; + } -.. http:get:: /tips/$TIP_ID - Obtain information about a particular tip. +.. http:delete:: /orders/$ORDER_ID - **Request:** + Delete information about an order. Fails if the order was paid in the + last 10 years (or whatever TAX_RECORD_EXPIRATION is set to) or was + claimed but is unpaid and thus still a valid offer. - :query pickups: if set to "yes", returns also information about all of the pickups + **Response:** - **Response:** + :status 204 No content: + The backend has successfully deleted the order. + :status 404 Not found: + The backend does not know the instance or the order. + :status 409 Conflict: + The backend refuses to delete the order. - :status 200 OK: - The tip is known. The backend responds with a `TipDetails` message - :status 404 Not Found: - The tip is unknown to the backend. - .. ts:def:: TipDetails +-------------- +Giving Refunds +-------------- - interface TipDetails { +.. _refund: +.. http:post:: /orders/$ORDER_ID/refund - // Amount that we authorized for this tip. - total_authorized: Amount; + Increase the refund amount associated with a given order. The user should be + redirected to the ``taler_refund_url`` to trigger refund processing in the wallet. - // Amount that was picked up by the user already. - total_picked_up: Amount; + **Request:** - // Human-readable reason given when authorizing the tip. - reason: String; + The request body is a `RefundRequest` object. - // Timestamp indicating when the tip is set to expire (may be in the past). - expiration: Timestamp; + **Response:** - // Reserve public key from which the tip is funded - reserve_pub: EddsaPublicKey; + :status 200 OK: + The refund amount has been increased, the backend responds with a `MerchantRefundResponse` + :status 404 Not found: + The order is unknown to the merchant + :status 409 Conflict: + The refund amount exceeds the amount originally paid - // Array showing the pickup operations of the wallet (possibly empty!). - // Only present if asked for explicitly. - pickups?: PickupDetail[]; - } + .. ts:def:: RefundRequest - .. ts:def:: PickupDetail + interface RefundRequest { + // Amount to be refunded + refund: Amount; - interface PickupDetail { + // Human-readable refund justification + reason: string; + } - // Unique identifier for the pickup operation. - pickup_id: HashCode; + .. ts:def:: MerchantRefundResponse - // Number of planchets involved. - num_planchets: integer; + interface MerchantRefundResponse { - // Total amount requested for this pickup_id. - requested_amount: Amount; + // URL (handled by the backend) that the wallet should access to + // trigger refund processing. + // taler://refund/[$H_CONTRACT/$AMOUNT????] + taler_refund_uri: string; + } - // Total amount processed by the exchange for this pickup. - exchange_amount: Amount; - } +------------------------ +Tracking Wire Transfers +------------------------ -.. http:post:: /public/tips/$TIP_ID/pickup +.. http:post:: /transfers - Handle request from wallet to pick up a tip. + Inform the backend over an incoming wire transfer. The backend should inquire about the details with the exchange and mark the respective orders as wired. Note that the request will fail if the WTID is not unique (which should be guaranteed by a correct exchange). + This request is idempotent and should also be used to merely re-fetch the + transfer information from the merchant's database (assuming we got a non-error + response from the exchange before). **Request:** - The request body is a `TipPickupRequest` object. + The request must provide `transfer information `. **Response:** :status 200 OK: - A tip is being returned. The backend responds with a `TipResponse` - :status 401 Unauthorized: - The tip amount requested exceeds the tip. + The wire transfer is known to the exchange, details about it follow in the body. + The body of the response is a `TrackTransferResponse`. Note that + the similarity to the response given by the exchange for a "GET /transfer" + is completely intended. + :status 202 Accepted: + The exchange provided conflicting information about the transfer. Namely, + there is at least one deposit among the deposits aggregated by ``wtid`` + that accounts for a coin whose + details don't match the details stored in merchant's database about the same keyed coin. + The response body contains the `TrackTransferConflictDetails`. + This is indicative of a malicious exchange that claims one thing, but did + something else. (With respect to the HTTP specficiation, it is not + precisely that we did not act upon the request, more that the usual + action of filing the transaction as 'finished' does not apply. In + the future, this is a case where the backend actually should report + the bad behavior to the auditor -- and then hope for the auditor to + resolve it. So in that respect, 202 is the right status code as more + work remains to be done for a final resolution.) :status 404 Not Found: - The tip identifier is unknown. + The instance is unknown to the exchange. :status 409 Conflict: - Some of the denomination key hashes of the request do not match those currently available from the exchange (hence there is a conflict between what the wallet requests and what the merchant believes the exchange can provide). + The wire transfer identifier is already known to us, but for a different amount, + wire method or exchange. + :status 424 Failed Dependency: + The exchange returned an error when we asked it about the "GET /transfer" status + for this wire transfer. Details of the exchange error are returned. - .. ts:def:: TipPickupRequest + .. ts:def:: TransferInformation - interface TipPickupRequest { + interface TransferInformation { + // how much was wired to the merchant (minus fees) + credit_amount: Amount; - // Identifier of the tip. - tip_id: HashCode; + // raw wire transfer identifier identifying the wire transfer (a base32-encoded value) + wtid: WireTransferIdentifierRawP; - // List of planches the wallet wants to use for the tip - planchets: PlanchetDetail[]; + // target account that received the wire transfer + payto_uri: string; + + // base URL of the exchange that made the wire transfer + exchange: string; } - .. ts:def:: PlanchetDetail + .. ts:def:: TrackTransferResponse - interface PlanchetDetail { - // Hash of the denomination's public key (hashed to reduce - // bandwidth consumption) - denom_pub_hash: HashCode; + interface TrackTransferResponse { + // Total amount transferred + total: Amount; - // coin's blinded public key - coin_ev: CoinEnvelope; + // Applicable wire fee that was charged + wire_fee: Amount; + + // Time of the execution of the wire transfer by the exchange, according to the exchange + execution_time: Timestamp; + + // details about the deposits + deposits_sums: TrackTransferDetail[]; } - .. ts:def:: TipResponse + .. ts:def:: TrackTransferDetail - interface TipResponse { + interface TrackTransferDetail { + // Business activity associated with the wire transferred amount + // ``deposit_value``. + order_id: string; - // Blind RSA signatures over the planchets. - // The order of the signatures matches the planchets list. - blind_sigs: BlindSignature[]; + // The total amount the exchange paid back for ``order_id``. + deposit_value: Amount; + + // applicable fees for the deposit + deposit_fee: Amount; } - interface BlindSignature { - // The (blind) RSA signature. Still needs to be unblinded. - blind_sig: RsaSignature; - } + **Details:** + .. ts:def:: TrackTransferConflictDetails + + interface TrackTransferConflictDetails { + // Numerical `error code ` + code: number; + // Text describing the issue for humans. + hint: string; --------------------------- -Dynamic Merchant Instances --------------------------- + // A /deposit response matching ``coin_pub`` showing that the + // exchange accepted ``coin_pub`` for ``amount_with_fee``. + exchange_deposit_proof: DepositSuccess; -.. note:: + // Offset in the ``exchange_transfer`` where the + // exchange's response fails to match the ``exchange_deposit_proof``. + conflict_offset: number; - The endpoints to dynamically manage merchant instances has not been - implemented yet. The bug id for this reference is #5349. + // The response from the exchange which tells us when the + // coin was returned to us, except that it does not match + // the expected value of the coin. + exchange_transfer: TrackTransferResponse; -.. http:get:: /instances + // Proof data we have for the ``exchange_transfer`` data (signatures from exchange) + exchange_proof: TrackTransferProof; - This is used to return the list of all the merchant instances + // Public key of the coin for which we have conflicting information. + coin_pub: EddsaPublicKey; - **Response:** + // Merchant transaction in which ``coin_pub`` was involved for which + // we have conflicting information. + transaction_id: number; - :status 200 OK: - The backend has successfully returned the list of instances stored. Returns - a `InstancesResponse`. + // Expected value of the coin. + amount_with_fee: Amount; - .. ts:def:: InstancesResponse + // Expected deposit fee of the coin. + deposit_fee: Amount; - interface InstancesResponse { - // List of instances that are present in the backend (see `Instance`) - instances: Instance[]; } - The `Instance` object describes the instance registered with the backend. It has the following structure: + .. ts:def:: TrackTransferProof + + interface TrackTransferProof { + // signature from the exchange made with purpose + // ``TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT`` + exchange_sig: EddsaSignature; + + // public EdDSA key of the exchange that was used to generate the signature. + // Should match one of the exchange's signing keys from /keys. Again given + // explicitly as the client might otherwise be confused by clock skew as to + // which signing key was used. + exchange_pub: EddsaSignature; - .. ts:def:: Instance + // hash of the wire details (identical for all deposits) + // Needed to check the ``exchange_sig`` + h_wire: HashCode; + } - interface Instance { - // Merchant name corresponding to this instance. - name: string; - // The URL where the wallet will send coins. - // FIXME: add multi-account support here! - payto: string; - // Merchant instance of the response to create - instance: string; +.. http:get:: /transfers - //unique key for each merchant - merchant_id: string; + Obtain a list of all wire transfers the backend has checked. - // FIXME: add locations (merchant address, jurisdiction) - } + **Request:** + :query payto_uri: *Optional*. Filter for transfers to the given bank account (subject and amount MUST NOT be given in the payto URI) + :query before: *Optional*. Filter for transfers executed before the given timestamp + :query after: *Optional*. Filter for transfers executed after the given timestamp + :query limit: *Optional*. At most return the given number of results. Negative for descending in execution time, positive for ascending in execution time. + :query offset: *Optional*. Starting transfer_serial_id for an iteration. + :query verified: *Optional*. Filter transfers by verification status. -.. http:post:: /instances + **Response:** - This request will be used to create a new merchant instance in the backend. + :status 200 OK: + The body of the response is a `TransferList`. - **Request:** + .. ts:def:: TransferList - The request must be a `InstanceConfigurationMessage`. + interface TransferList { + // list of all the transfers that fit the filter that we know + transfers : TransferDetails[]; + } - **Response:** + interface TransferDetails { + // how much was wired to the merchant (minus fees) + credit_amount: Amount; - :status 204 No content: - The backend has successfully created the instance. - :status 409 Conflict: - This instance already exists, but with other configuration options. - Use "PATCH" to update an instance configuration. + // raw wire transfer identifier identifying the wire transfer (a base32-encoded value) + wtid: WireTransferIdentifierRawP; - .. ts:def:: InstanceConfigurationMessage + // target account that received the wire transfer + payto_uri: string; - interface InstanceConfigurationMessage { - // The URL where the wallet has to send coins. - // payto://-URL of the merchant's bank account. Required. - // FIXME: need an array, and to distinguish between - // supported and active (see taler.conf options on accounts!) - payto: string; + // base URL of the exchange that made the wire transfer + exchange: string; - // Name of the merchant instance to create (will become $INSTANCE). - instance: string; + // Serial number identifying the transfer in the merchant backend. + // Used for filgering via ``offset``. + transfer_serial_id: number; - // Merchant name corresponding to this instance. - name: string; + // Time of the execution of the wire transfer by the exchange, according to the exchange + // Only provided if we did get an answer from the exchange. + execution_time?: Timestamp; - // FIXME: add locations (merchant address, jurisdiction) + // True if we checked the exchange's answer and are happy with it. + // False if we have an answer and are unhappy, missing if we + // do not have an answer from the exchange. + verified?: boolean; } -.. http:patch:: /instances/$INSTANCE - - Update the configuration of a merchant instance. - **Request** - The request must be a `InstanceConfigurationMessage`. +-------------------- +Giving Customer Tips +-------------------- - **Response:** +.. _tips: +.. http:post:: /reserves - :status 204 No content: - The backend has successfully created the instance. - :status 404 Not found: - This instance is unknown and thus cannot be reconfigured. + Create a reserve for tipping. + This request is **not** idempotent. However, while repeating + it will create another reserve, that is generally pretty harmless + (assuming only one of the reserves is filled with a wire transfer). + Clients may want to eventually delete the unused reserves to + avoid clutter. -.. http:get:: /instances/$INSTANCE + **Request:** - This is used to query a specific merchant instance. + The request body is a `ReserveCreateRequest` object. **Response:** :status 200 OK: - The backend has successfully returned the list of instances stored. Returns - a `QueryInstancesResponse`. + The backend is waiting for the reserve to be established. The merchant + must now perform the wire transfer indicated in the `ReserveCreateConfirmation`. + :status 424 Failed Depencency: + We could not obtain /wire details from the specified exchange base URL. - .. ts:def:: QueryInstancesResponse + .. ts:def:: ReserveCreateRequest - interface QueryInstancesResponse { - // The URL where the wallet has to send coins. - // payto://-URL of the merchant's bank account. Required. - payto: string; + interface ReserveCreateRequest { + // Amount that the merchant promises to put into the reserve + initial_amount: Amount; - // Merchant instance of the response to create - // This field is optional. If it is not specified - // then it will automatically be created. - instance?: string; + // Exchange the merchant intends to use for tipping + exchange_base_url: string; - // Merchant name corresponding to this instance. - name: string; + } - // Public key of the merchant/instance, in Crockford Base32 encoding. - merchant_pub: EddsaPublicKey; + .. ts:def:: ReserveCreateConfirmation - // List of the payment targets supported by this instance. Clients can - // specify the desired payment target in /order requests. Note that - // front-ends do not have to support wallets selecting payment targets. - payment_targets: string[]; + interface ReserveCreateConfirmation { + // Public key identifying the reserve + reserve_pub: EddsaPublicKey; - // FIXME: add locations (merchant address, jurisdiction) + // Wire account of the exchange where to transfer the funds + payto_url: string; } +.. http:get:: /reserves -.. http:delete:: /instances/$INSTANCE + Obtain list of reserves that have been created for tipping. - This request will be used to delete (permanently disable) - or purge merchant instance in the backend. Purging will - delete all offers and payments associated with the instance, - while disabling (the default) only deletes the private key - and makes the instance unusuable for new orders or payments. + **Request:** - **Request:** + :query after: *Optional*. Only return reserves created after the given timestamp in milliseconds + :query active: *Optional*. Only return active/inactive reserves depending on the boolean given + :query failures: *Optional*. Only return reserves where we disagree with the exchange about the initial balance. - :query purge: *Optional*. If set to YES, the instance will be fully - deleted. Otherwise only the private key would be deleted. + **Response:** - **Response** + :status 200 OK: + Returns a list of known tipping reserves. + The body is a `TippingReserveStatus`. - :status 204 NoContent: - The backend has successfully removed the instance. The response is a - `PostInstanceRemoveResponse`. - :status 404 Not found: - The instance is unknown to the backend. - :status 409 Conflict: - The instance cannot be deleted because it has pending offers, or - the instance cannot be purged because it has successfully processed - payments that have not passed the TAX_RECORD_EXPIRATION time. - The latter case only applies if ``purge`` was set. + .. ts:def:: TippingReserveStatus + interface TippingReserveStatus { + // Array of all known reserves (possibly empty!) + reserves: ReserveStatusEntry[]; --------------------- -Inventory management --------------------- + } -Inventory management is an *optional* backend feature that can be used to -manage limited stocks of products and to auto-complete product descriptions -in contracts (such that the frontends have to do less work). + .. ts:def:: ReserveStatusEntry -.. http:get:: /products + interface ReserveStatusEntry { - This is used to return the list of all items in the inventory. + // Public key of the reserve + reserve_pub: EddsaPublicKey; - **Response:** + // Timestamp when it was established + creation_time: Timestamp; - :status 200 OK: - The backend has successfully returned the inventory. Returns - a `InventorySummaryResponse`. + // Timestamp when it expires + expiration_time: Timestamp; - .. ts:def:: InventorySummaryResponse + // Initial amount as per reserve creation call + merchant_initial_amount: Amount; - interface InventorySummaryResponse { - // List of items that are present in the inventory - items: InventoryEntry[]; - } + // Initial amount as per exchange, 0 if exchange did + // not confirm reserve creation yet. + exchange_initial_amount: Amount; - The `InventoryEntry` object describes an item in the inventory. It has the following structure: + // Amount picked up so far. + pickup_amount: Amount; - .. ts:def:: InventoryEntry + // Amount approved for tips that exceeds the pickup_amount. + committed_amount: Amount; - interface InventoryEntry { - // Product identifier, as found in the product. - product_id: string; + // Is this reserve active (false if it was deleted but not purged) + active: boolean; + } - // Amount of the product in stock. Given in product-specific units. - // Set to -1 for "infinite" (i.e. for "electronic" books). - stock: integer; - // unit in which the product is metered (liters, kilograms, packages, etc.) - unit: string; - } +.. http:get:: /reserves/$RESERVE_PUB + Obtain information about a specific reserve that have been created for tipping. -.. http:get:: /products/$PRODUCT_ID + **Request:** - This is used to obtain detailed information about a product in the inventory. + :query tips: *Optional*. If set to "yes", returns also information about all of the tips created - **Response:** + **Response:** :status 200 OK: - The backend has successfully returned the inventory. Returns - a `ProductDetail`. + Returns the `ReserveDetail`. + :status 404 Not found: + The tipping reserve is not known. + :status 424 Failed Dependency: + We are having trouble with the request because of a problem with the exchange. + Likely returned with an "exchange_code" in addition to a "code" and + an "exchange_http_status" in addition to our own HTTP status. Also usually + includes the full exchange reply to our request under "exchange_reply". + This is only returned if there was actual trouble with the exchange, not + if the exchange merely did not respond yet or if it responded that the + reserve was not yet filled. - .. ts:def:: ProductDetail + .. ts:def:: ReserveDetail - interface ProductDetail { + interface ReserveDetail { - // Human-readable product description. - description: string; + // Timestamp when it was established + creation_time: Timestamp; - // Map from IETF BCP 47 language tags to localized descriptions - description_i18n?: { [lang_tag: string]: string }; + // Timestamp when it expires + expiration_time: Timestamp; - // unit in which the product is measured (liters, kilograms, packages, etc.) - unit: string; + // Initial amount as per reserve creation call + merchant_initial_amount: Amount; - // The price for one ``unit`` of the product. Zero is used - // to imply that this product is not sold separately, or - // that the price is not fixed, and must be supplied by the - // front-end. If non-zero, this price MUST include applicable - // taxes. - price: Amount; + // Initial amount as per exchange, 0 if exchange did + // not confirm reserve creation yet. + exchange_initial_amount: Amount; - // An optional base64-encoded product image - image?: ImageDataUrl; + // Amount picked up so far. + pickup_amount: Amount; - // a list of taxes paid by the merchant for one unit of this product - taxes: Tax[]; + // Amount approved for tips that exceeds the pickup_amount. + committed_amount: Amount; - // Number of units of the product in stock in sum in total, - // including all existing sales ever. Given in product-specific - // units. - // A value of -1 indicates "infinite" (i.e. for "electronic" books). - total_stocked: integer; + // Array of all tips created by this reserves (possibly empty!). + // Only present if asked for explicitly. + tips?: TipStatusEntry[]; - // Number of units of the product that have already been sold. - total_sold: integer; + } - // Number of units of the product that were lost (spoiled, stolen, etc.) - total_lost: integer; + .. ts:def:: TipStatusEntry - // Number of units of the product that are currently locked by some - // shopping cart. - total_locked: integer; + interface TipStatusEntry { - // Identifies where the product is in stock. - location?: Location; + // Unique identifier for the tip + tip_id: HashCode; - // Identifies when we expect the next restocking to happen. - next_restock?: timestamp; + // Total amount of the tip that can be withdrawn. + total_amount: Amount; + + // Human-readable reason for why the tip was granted. + reason: String; } -.. http:post:: /products +.. http:post:: /reserves/$RESERVE_PUB/authorize-tip - This is used to add a product to the inventory. + Authorize creation of a tip from the given reserve. **Request:** - The request must be a `ProductAddDetail`. + The request body is a `TipCreateRequest` object. **Response:** - :status 204 No content: - The backend has successfully expanded the inventory. - :status 409 Conflict: - The backend already knows a product with this product ID, but with different details. + :status 200 OK: + A tip has been created. The backend responds with a `TipCreateConfirmation` + :status 404 Not Found: + The instance or the reserve is unknown to the backend. + :status 412 Precondition Failed: + The tip amount requested exceeds the available reserve balance for tipping. + .. ts:def:: TipCreateRequest - .. ts:def:: ProductAddDetail + interface TipCreateRequest { + // Amount that the customer should be tipped + amount: Amount; - interface ProductAddDetail { + // Justification for giving the tip + justification: string; - // product ID to use. - product_id: string; + // URL that the user should be directed to after tipping, + // will be included in the tip_token. + next_url: string; + } - // Human-readable product description. - description: string; + .. ts:def:: TipCreateConfirmation - // Map from IETF BCP 47 language tags to localized descriptions - description_i18n?: { [lang_tag: string]: string }; + interface TipCreateConfirmation { + // Unique tip identifier for the tip that was created. + tip_id: HashCode; - // unit in which the product is measured (liters, kilograms, packages, etc.) - unit: string; + // Token that will be handed to the wallet, + // contains all relevant information to accept + // a tip. + tip_token: string; - // The price for one ``unit`` of the product. Zero is used - // to imply that this product is not sold separately, or - // that the price is not fixed, and must be supplied by the - // front-end. If non-zero, this price MUST include applicable - // taxes. - price: Amount; + // URL that will directly trigger processing + // the tip when the browser is redirected to it + tip_redirect_url: string; - // An optional base64-encoded product image - image?: ImageDataUrl; + } - // a list of taxes paid by the merchant for one unit of this product - taxes: Tax[]; - // Number of units of the product in stock in sum in total, - // including all existing sales ever. Given in product-specific - // units. - // A value of -1 indicates "infinite" (i.e. for "electronic" books). - total_stocked: integer; +.. http:post:: /tips - // Identifies where the product is in stock. - location?: Location; + Authorize creation of a tip from the given reserve, except with + automatic selection of a working reserve of the instance by the + backend. Intentionally otherwise identical to the /authorize-tip + endpoint given above. - // Identifies when we expect the next restocking to happen. - next_restock?: timestamp; + **Request:** - } + The request body is a `TipCreateRequest` object. + **Response:** + :status 200 OK: + A tip has been created. The backend responds with a `TipCreateConfirmation` + :status 404 Not Found: + The instance is unknown to the backend. + :status 412 Precondition Failed: + The tip amount requested exceeds the available reserve balance for tipping + in all of the reserves of the instance. -.. http:patch:: /products/$PRODUCT_ID - This is used to update product details in the inventory. Note that the - ``total_stocked`` and ``total_lost`` numbers MUST be greater or equal than - previous values (this design ensures idempotency). In case stocks were lost - but not sold, increment the ``total_lost`` number. All fields in the - request are optional, those that are not given are simply preserved (not - modified). Note that the ``description_i18n`` and ``taxes`` can only be - modified in bulk: if it is given, all translations must be provided, not - only those that changed. "never" should be used for the ``next_restock`` - timestamp to indicate no intention/possibility of restocking, while a time - of zero is used to indicate "unknown". +.. http:delete:: /reserves/$RESERVE_PUB - Limitations: you cannot remove a ``location`` from a product that used to - have a location. + Delete information about a reserve. Fails if the reserve still has + committed to tips that were not yet picked up and that have not yet + expired. **Request:** - The request must be a `ProductPatchDetail`. + :query purge: *Optional*. If set to YES, the reserve and all information + about tips it issued will be fully deleted. + Otherwise only the private key would be deleted. **Response:** :status 204 No content: - The backend has successfully expanded the inventory. + The backend has successfully deleted the reserve. + :status 404 Not found: + The backend does not know the instance or the reserve. + :status 409 Conflict: + The backend refuses to delete the reserve (committed tips awaiting pickup). - interface ProductPatchDetail { - // Human-readable product description. - description?: string; +.. http:get:: /tips/$TIP_ID - // Map from IETF BCP 47 language tags to localized descriptions - description_i18n?: { [lang_tag: string]: string }; + Obtain information about a particular tip. - // unit in which the product is measured (liters, kilograms, packages, etc.) - unit?: string; + **Request:** - // The price for one ``unit`` of the product. Zero is used - // to imply that this product is not sold separately, or - // that the price is not fixed, and must be supplied by the - // front-end. If non-zero, this price MUST include applicable - // taxes. - price?: Amount; + :query pickups: if set to "yes", returns also information about all of the pickups - // An optional base64-encoded product image - image?: ImageDataUrl; + **Response:** - // a list of taxes paid by the merchant for one unit of this product - taxes?: Tax[]; + :status 200 OK: + The tip is known. The backend responds with a `TipDetails` message + :status 404 Not Found: + The tip is unknown to the backend. - // Number of units of the product in stock in sum in total, - // including all existing sales ever. Given in product-specific - // units. - // A value of -1 indicates "infinite" (i.e. for "electronic" books). - total_stocked?: integer; + .. ts:def:: TipDetails - // Number of units of the product that were lost (spoiled, stolen, etc.) - total_lost?: integer; + interface TipDetails { - // Identifies where the product is in stock. - location?: Location; + // Amount that we authorized for this tip. + total_authorized: Amount; - // Identifies when we expect the next restocking to happen. - next_restock?: timestamp; + // Amount that was picked up by the user already. + total_picked_up: Amount; + + // Human-readable reason given when authorizing the tip. + reason: String; + + // Timestamp indicating when the tip is set to expire (may be in the past). + expiration: Timestamp; + + // Reserve public key from which the tip is funded + reserve_pub: EddsaPublicKey; + // Array showing the pickup operations of the wallet (possibly empty!). + // Only present if asked for explicitly. + pickups?: PickupDetail[]; } + .. ts:def:: PickupDetail + interface PickupDetail { -.. http:post:: /products/$PRODUCT_ID/lock + // Unique identifier for the pickup operation. + pickup_id: HashCode; - This is used to lock a certain quantity of the product for a limited - duration while the customer assembles a complete order. Note that - frontends do not have to "unlock", they may rely on the timeout as - given in the ``duration`` field. Re-posting a lock with a different - ``duration`` or ``quantity`` updates the existing lock for the same UUID - and does not result in a conflict. + // Number of planchets involved. + num_planchets: integer; - Unlocking by using a ``quantity`` of zero is is - optional but recommended if customers remove products from the - shopping cart. Note that actually POSTing to ``/orders`` with set - ``manage_inventory`` and using ``lock_uuid`` will **transition** the - lock to the newly created order (which may have a different ``duration`` - and ``quantity`` than what was requested in the lock operation). - If an order is for fewer items than originally locked, the difference - is automatically unlocked. + // Total amount requested for this pickup_id. + requested_amount: Amount; + + // Total amount processed by the exchange for this pickup. + exchange_amount: Amount; + + } + + +.. http:post:: /public/tips/$TIP_ID/pickup + + Handle request from wallet to pick up a tip. **Request:** - The request must be a `LockRequest`. + The request body is a `TipPickupRequest` object. **Response:** - :status 204 No content: - The backend has successfully locked (or unlocked) the requested ``quantity``. - :status 404 Not found: - The backend has does not know this product. - :status 410 Gone: - The backend does not have enough of product in stock. + :status 200 OK: + A tip is being returned. The backend responds with a `TipResponse` + :status 401 Unauthorized: + The tip amount requested exceeds the tip. + :status 404 Not Found: + The tip identifier is unknown. + :status 409 Conflict: + Some of the denomination key hashes of the request do not match those currently available from the exchange (hence there is a conflict between what the wallet requests and what the merchant believes the exchange can provide). - .. ts:def::LockRequest + .. ts:def:: TipPickupRequest - interface LockRequest { + interface TipPickupRequest { - // UUID that identifies the frontend performing the lock - lock_uuid: UUID; + // Identifier of the tip. + tip_id: HashCode; - // How long does the frontend intend to hold the lock - duration: time; + // List of planches the wallet wants to use for the tip + planchets: PlanchetDetail[]; + } - // How many units should be locked? - quantity: integer; + .. ts:def:: PlanchetDetail + + interface PlanchetDetail { + // Hash of the denomination's public key (hashed to reduce + // bandwidth consumption) + denom_pub_hash: HashCode; + + // coin's blinded public key + coin_ev: CoinEnvelope; + + } + + .. ts:def:: TipResponse + + interface TipResponse { + + // Blind RSA signatures over the planchets. + // The order of the signatures matches the planchets list. + blind_sigs: BlindSignature[]; + } + interface BlindSignature { + + // The (blind) RSA signature. Still needs to be unblinded. + blind_sig: RsaSignature; } + + + ------------------ The Contract Terms ------------------ +.. _contract_terms:: + The contract terms must have the following structure: .. ts:def:: ContractTerms @@ -1832,7 +1883,6 @@ The contract terms must have the following structure: interface Product { // merchant-internal identifier for the product. - // FIXME: do we require the use of the /inventory API if this is present? product_id?: string; // Human-readable product description. diff --git a/taler-merchant-api-tutorial.rst b/taler-merchant-api-tutorial.rst index ea8f72b6..d42f74b0 100644 --- a/taler-merchant-api-tutorial.rst +++ b/taler-merchant-api-tutorial.rst @@ -83,8 +83,8 @@ endpoints are prefixed with ``/public/``. Public Sandbox Backend and Authentication ----------------------------------------- -sandbox -authorization +:keywords: sandbox +:keywords: authorization How the frontend authenticates to the Taler backend depends on the configuration. See Taler Merchant Operating Manual. @@ -110,7 +110,7 @@ https://bank.demo.taler.net/. Merchant Instances ------------------ -instance +:keywords: instance The same Taler merchant backend server can be used by multiple separate merchants that are separate business entities. Each of these separate business entities is called a *merchant instance*, and is identified by @@ -139,7 +139,7 @@ Accepting a Simple Payment Creating an Order for a Payment ------------------------------- -order +:keywords: order Payments in Taler revolve around an *order*, which is a machine-readable description of the business transaction for which the payment is to be made. Before accepting a Taler payment as a merchant you must create @@ -229,7 +229,7 @@ the merchant’s obligations under the contract. Giving Refunds ============== -refunds +:keywords: refunds A refund in GNU Taler is a way to “undo” a payment. It needs to be authorized by the merchant. Refunds can be for any fraction of the original amount paid, but they cannot exceed the original payment. @@ -274,12 +274,50 @@ This code snipped illustrates giving a refund: ... headers={"Authorization": "ApiKey sandbox"}) + +Repurchase detection and fulfillment URLs +========================================= + +:keywords: repurchase +A possible problem for merchants selling access to digital articles +is that a customer may have paid for an article on one device, but +may then want to read it on a different device, possibly one that +does not even have a Taler wallet installed. + +Naturally, at this point the customer would at first still be prompted to pay +for the article again. If the customer then opens the taler://-link in the +wallet that did previously pay for the article (for example by scanning the QR +code on the desktop with the Android App), the wallet will claim the contract, +detect that the fulfillment URL is identical to one that it already has made a +payment for in the past, and initiate **repurchase redirection**: Here, the +wallet will contact the merchant and replay the previous payment, except this +time using the (current) session ID of the browser (it learns the session ID +from the QR code). + +The merchant backend then updates the session ID of the existing order to +the current session ID of the browser. When the payment status for the +"new" unpaid order is checked (or already in long-polling), the backend +detects that for the browser's *session ID* and *fulfillment URL* there is an +existing paid contract. It then tells the browser to immediately redirect to +the fulfillment URL where the already paid article is available. + +To ensure this mechanism works as designed, merchants must make sure to not +use the same fulfillment URL for different products or for physical products +where customers may be expected to buy the article repeatedly. Similarly, +it is crucial that merchants consistently use the same fulfillment URL for +the same digital product where repurchase detection is desired. + +Note that changing the session ID to a different device requires the +involvement of the wallet that made the payment, thus reasonably limiting the +possibility of broadly sharing the digital purchases. + + .. _Giving-Customers-Tips: Giving Customers Tips ===================== -tips +:keywords: tips GNU Taler allows Web sites to grant small amounts directly to the visitor. The idea is that some sites may want incentivize actions such as filling out a survey or trying a new feature. It is important to note @@ -692,4 +730,3 @@ locations .. |image0| image:: arch-api.png - -- cgit v1.2.3 From 9e508b7421629532fa76b92d3e6d5526c88bd76b Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 18 Apr 2020 10:12:51 +0200 Subject: update merchant backend spec: add missing fileds --- core/api-merchant.rst | 73 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 23 deletions(-) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index 7885dd4d..09de8b2d 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -98,8 +98,8 @@ Dynamic Merchant Instances // Merchant name corresponding to this instance. name: string; - // Merchant instance of the response to create - instance: string; + // Merchant instance this response is about ($INSTANCE) + id: string; // Public key of the merchant/instance, in Crockford Base32 encoding. merchant_pub: EddsaPublicKey; @@ -137,7 +137,7 @@ Dynamic Merchant Instances payto_uris: string[]; // Name of the merchant instance to create (will become $INSTANCE). - instance: string; + id: string; // Merchant name corresponding to this instance. name: string; @@ -148,6 +148,29 @@ Dynamic Merchant Instances // The jurisdiction under which the merchant conducts its business // (to be put into contracts). jurisdiction: Location; + + // Maximum wire fee this instance is willing to pay. + // Can be overridden by the frontend on a per-order basis. + default_max_wire_fee: Amount; + + // Default factor for wire fee amortization calculations. + // Can be overriden by the frontend on a per-order basis. + default_wire_fee_amortization: integer; + + // Maximum deposit fee (sum over all coins) this instance is willing to pay. + // Can be overridden by the frontend on a per-order basis. + default_max_deposit_fee: Amount; + + // If the frontend does NOT specify an execution date, how long should + // we tell the exchange to wait to aggregate transactions before + // executing the wire transfer? This delay is added to the current + // time when we generate the advisory execution time for the exchange. + default_wire_transfer_delay: RelativeTime; + + // If the frontend does NOT specify a payment deadline, how long should + // offers we make be valid by default? + default_pay_deadline: RelativeTime; + } @@ -157,8 +180,8 @@ Dynamic Merchant Instances **Request** - The request must be a `InstanceUpdateMessage`. Fields that are not - provided are not modified. Removing an existing payto_uri deactivates + The request must be a `InstanceConfigurationMessage`. + Removing an existing payto_uri deactivates the account (it will no longer be used for future contracts). **Response:** @@ -168,24 +191,6 @@ Dynamic Merchant Instances :status 404 Not found: This instance is unknown and thus cannot be reconfigured. - .. ts:def:: InstanceUpdateMessage - - interface InstanceUpdateMessage { - // The URI where the wallet will send coins. A merchant may have - // multiple accounts, thus this is an array. Note that by - // removing URIs from this list - payto_uris?: string[]; - - // Merchant name corresponding to this instance. - name?: string; - - // The merchant's physical address (to be put into contracts). - address?: Location; - - // The jurisdiction under which the merchant conducts its business - // (to be put into contracts). - jurisdiction?: Location; - } .. http:get:: /instances/$INSTANCE @@ -217,6 +222,28 @@ Dynamic Merchant Instances // (to be put into contracts). jurisdiction: Location; + // Maximum wire fee this instance is willing to pay. + // Can be overridden by the frontend on a per-order basis. + default_max_wire_fee: Amount; + + // Default factor for wire fee amortization calculations. + // Can be overriden by the frontend on a per-order basis. + default_wire_fee_amortization: integer; + + // Maximum deposit fee (sum over all coins) this instance is willing to pay. + // Can be overridden by the frontend on a per-order basis. + default_max_deposit_fee: Amount; + + // If the frontend does NOT specify an execution date, how long should + // we tell the exchange to wait to aggregate transactions before + // executing the wire transfer? This delay is added to the current + // time when we generate the advisory execution time for the exchange. + default_wire_transfer_delay: RelativeTime; + + // If the frontend does NOT specify a payment deadline, how long should + // offers we make be valid by default? + default_pay_deadline: RelativeTime; + } .. ts:def:: MerchantAccount -- cgit v1.2.3 From 9a938cf12527a018b4a49ed1e5a73e8f135c773b Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 19 Apr 2020 14:04:18 +0200 Subject: update spec --- core/api-merchant.rst | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index 09de8b2d..b7f81e73 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -180,7 +180,7 @@ Dynamic Merchant Instances **Request** - The request must be a `InstanceConfigurationMessage`. + The request must be a `InstanceReconfigurationMessage`. Removing an existing payto_uri deactivates the account (it will no longer be used for future contracts). @@ -191,6 +191,48 @@ Dynamic Merchant Instances :status 404 Not found: This instance is unknown and thus cannot be reconfigured. + .. ts:def:: InstanceReconfigurationMessage + + interface InstanceReconfigurationMessage { + // The URI where the wallet will send coins. A merchant may have + // multiple accounts, thus this is an array. Note that by + // removing URIs from this list + payto_uris: string[]; + + // Merchant name corresponding to this instance. + name: string; + + // The merchant's physical address (to be put into contracts). + address: Location; + + // The jurisdiction under which the merchant conducts its business + // (to be put into contracts). + jurisdiction: Location; + + // Maximum wire fee this instance is willing to pay. + // Can be overridden by the frontend on a per-order basis. + default_max_wire_fee: Amount; + + // Default factor for wire fee amortization calculations. + // Can be overriden by the frontend on a per-order basis. + default_wire_fee_amortization: integer; + + // Maximum deposit fee (sum over all coins) this instance is willing to pay. + // Can be overridden by the frontend on a per-order basis. + default_max_deposit_fee: Amount; + + // If the frontend does NOT specify an execution date, how long should + // we tell the exchange to wait to aggregate transactions before + // executing the wire transfer? This delay is added to the current + // time when we generate the advisory execution time for the exchange. + default_wire_transfer_delay: RelativeTime; + + // If the frontend does NOT specify a payment deadline, how long should + // offers we make be valid by default? + default_pay_deadline: RelativeTime; + + } + .. http:get:: /instances/$INSTANCE @@ -487,6 +529,7 @@ management. :status 204 No content: The backend has successfully expanded the inventory. + .. ts:def:: ProductPatchDetail interface ProductPatchDetail { @@ -578,6 +621,19 @@ management. } +.. http:delete:: /products/$PRODUCT_ID + + Delete information about a product. Fails if the product is locked by + anyone. + + **Response:** + + :status 204 No content: + The backend has successfully deleted the product. + :status 404 Not found: + The backend does not know the instance or the product. + :status 409 Conflict: + The backend refuses to delete the product because it is locked. ------------------ -- cgit v1.2.3 From 1ab32280f303dc215bbbc2138b30fc4fc25311af Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 19 Apr 2020 17:19:00 +0200 Subject: spec work --- core/api-merchant.rst | 41 +++++++++++++++++------------------------ 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index b7f81e73..a037cd89 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -361,8 +361,8 @@ management. .. ts:def:: InventorySummaryResponse interface InventorySummaryResponse { - // List of items that are present in the inventory - items: InventoryEntry[]; + // List of products that are present in the inventory + products: InventoryEntry[]; } The `InventoryEntry` object describes an item in the inventory. It has the following structure: @@ -400,7 +400,7 @@ management. description: string; // Map from IETF BCP 47 language tags to localized descriptions - description_i18n?: { [lang_tag: string]: string }; + description_i18n: { [lang_tag: string]: string }; // unit in which the product is measured (liters, kilograms, packages, etc.) unit: string; @@ -413,7 +413,7 @@ management. price: Amount; // An optional base64-encoded product image - image?: ImageDataUrl; + image: ImageDataUrl; // a list of taxes paid by the merchant for one unit of this product taxes: Tax[]; @@ -430,12 +430,8 @@ management. // Number of units of the product that were lost (spoiled, stolen, etc.) total_lost: integer; - // Number of units of the product that are currently locked by some - // shopping cart. - total_locked: integer; - // Identifies where the product is in stock. - location?: Location; + location: Location; // Identifies when we expect the next restocking to happen. next_restock?: timestamp; @@ -470,7 +466,7 @@ management. description: string; // Map from IETF BCP 47 language tags to localized descriptions - description_i18n?: { [lang_tag: string]: string }; + description_i18n: { [lang_tag: string]: string }; // unit in which the product is measured (liters, kilograms, packages, etc.) unit: string; @@ -483,7 +479,7 @@ management. price: Amount; // An optional base64-encoded product image - image?: ImageDataUrl; + image: ImageDataUrl; // a list of taxes paid by the merchant for one unit of this product taxes: Tax[]; @@ -495,7 +491,7 @@ management. total_stocked: integer; // Identifies where the product is in stock. - location?: Location; + location: Location; // Identifies when we expect the next restocking to happen. next_restock?: timestamp; @@ -517,9 +513,6 @@ management. timestamp to indicate no intention/possibility of restocking, while a time of zero is used to indicate "unknown". - Limitations: you cannot remove a ``location`` from a product that used to - have a location. - **Request:** The request must be a `ProductPatchDetail`. @@ -534,38 +527,38 @@ management. interface ProductPatchDetail { // Human-readable product description. - description?: string; + description: string; // Map from IETF BCP 47 language tags to localized descriptions - description_i18n?: { [lang_tag: string]: string }; + description_i18n: { [lang_tag: string]: string }; // unit in which the product is measured (liters, kilograms, packages, etc.) - unit?: string; + unit: string; // The price for one ``unit`` of the product. Zero is used // to imply that this product is not sold separately, or // that the price is not fixed, and must be supplied by the // front-end. If non-zero, this price MUST include applicable // taxes. - price?: Amount; + price: Amount; // An optional base64-encoded product image - image?: ImageDataUrl; + image: ImageDataUrl; // a list of taxes paid by the merchant for one unit of this product - taxes?: Tax[]; + taxes: Tax[]; // Number of units of the product in stock in sum in total, // including all existing sales ever. Given in product-specific // units. // A value of -1 indicates "infinite" (i.e. for "electronic" books). - total_stocked?: integer; + total_stocked: integer; // Number of units of the product that were lost (spoiled, stolen, etc.) - total_lost?: integer; + total_lost: integer; // Identifies where the product is in stock. - location?: Location; + location: Location; // Identifies when we expect the next restocking to happen. next_restock?: timestamp; -- cgit v1.2.3 From 925dc91406ff2de7fddc15b64e2aeea708ef9d95 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 20 Apr 2020 19:32:32 +0200 Subject: update spec --- core/api-merchant.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index a037cd89..3583e209 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -431,7 +431,7 @@ management. total_lost: integer; // Identifies where the product is in stock. - location: Location; + address: Location; // Identifies when we expect the next restocking to happen. next_restock?: timestamp; @@ -491,7 +491,7 @@ management. total_stocked: integer; // Identifies where the product is in stock. - location: Location; + address: Location; // Identifies when we expect the next restocking to happen. next_restock?: timestamp; @@ -558,7 +558,7 @@ management. total_lost: integer; // Identifies where the product is in stock. - location: Location; + address: Location; // Identifies when we expect the next restocking to happen. next_restock?: timestamp; -- cgit v1.2.3 From 7b96e3e9b0334c1e6d143bf92697bd0c0ea1a6b2 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 20 Apr 2020 21:34:17 +0200 Subject: fix rst --- core/api-common.rst | 14 ++++- core/api-merchant.rst | 145 ++++++++++++++++++++++++++------------------------ 2 files changed, 89 insertions(+), 70 deletions(-) diff --git a/core/api-common.rst b/core/api-common.rst index 1721c42f..294e33d5 100644 --- a/core/api-common.rst +++ b/core/api-common.rst @@ -549,10 +549,22 @@ uses 512-bit hash codes (64 bytes). uint8_t eddsa_priv[32]; }; - struct TALER_MasterSignatureP { + struct TALER_MasterSignatureP { uint8_t eddsa_signature[64]; }; +.. _WireTransferIdentifierRawP: + + struct WireTransferIdentifierRawP { + uint8_t raw[32]; + }; + +.. _UUID: + + struct UUID { + uint32_t value[4]; + }; + .. _eddsa-coin-pub: .. sourcecode:: c diff --git a/core/api-merchant.rst b/core/api-merchant.rst index 3583e209..002dc976 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -29,8 +29,9 @@ API, which is NOT yet implemented at all! TODO: https://bugs.gnunet.org/view.php?id=5987#c15127 is not yet addressed by this specification! -The ``*/public/*`` endpoints are publicly exposed on the Internet and accessed -both by the user's browser and their wallet. +The ``*/private/*`` endpoints are only supposed to be exposed +to the merchant internally, and must not be exposed on the +Internet. Most endpoints given here can be prefixed by a base URL that includes the specific instance selected (BASE_URL/instances/$INSTANCE/). If @@ -43,7 +44,7 @@ specific instance selected (BASE_URL/instances/$INSTANCE/). If Getting the configuration ------------------------- -.. http:get:: /public/config +.. http:get:: /config Return the protocol version and currency supported by this merchant backend. @@ -71,7 +72,7 @@ Dynamic Merchant Instances -------------------------- .. _instances: -.. http:get:: /instances +.. http:get:: /private/instances This is used to return the list of all the merchant instances @@ -112,7 +113,7 @@ Dynamic Merchant Instances } -.. http:post:: /instances +.. http:post:: /private/instances This request will be used to create a new merchant instance in the backend. @@ -155,7 +156,7 @@ Dynamic Merchant Instances // Default factor for wire fee amortization calculations. // Can be overriden by the frontend on a per-order basis. - default_wire_fee_amortization: integer; + default_wire_fee_amortization: Integer; // Maximum deposit fee (sum over all coins) this instance is willing to pay. // Can be overridden by the frontend on a per-order basis. @@ -174,7 +175,7 @@ Dynamic Merchant Instances } -.. http:patch:: /instances/$INSTANCE +.. http:patch:: /private/instances/$INSTANCE Update the configuration of a merchant instance. @@ -215,7 +216,7 @@ Dynamic Merchant Instances // Default factor for wire fee amortization calculations. // Can be overriden by the frontend on a per-order basis. - default_wire_fee_amortization: integer; + default_wire_fee_amortization: Integer; // Maximum deposit fee (sum over all coins) this instance is willing to pay. // Can be overridden by the frontend on a per-order basis. @@ -234,7 +235,7 @@ Dynamic Merchant Instances } -.. http:get:: /instances/$INSTANCE +.. http:get:: /private/instances/$INSTANCE This is used to query a specific merchant instance. @@ -270,7 +271,7 @@ Dynamic Merchant Instances // Default factor for wire fee amortization calculations. // Can be overriden by the frontend on a per-order basis. - default_wire_fee_amortization: integer; + default_wire_fee_amortization: Integer; // Maximum deposit fee (sum over all coins) this instance is willing to pay. // Can be overridden by the frontend on a per-order basis. @@ -308,7 +309,7 @@ Dynamic Merchant Instances -.. http:delete:: /instances/$INSTANCE +.. http:delete:: /private/instances/$INSTANCE This request will be used to delete (permanently disable) or purge merchant instance in the backend. Purging will @@ -323,7 +324,7 @@ Dynamic Merchant Instances **Response** - :status 204 NoContent: + :status 204 No content: The backend has successfully removed the instance. The response is a `PostInstanceRemoveResponse`. :status 404 Not found: @@ -348,7 +349,7 @@ Taler merchant backend to process payments *without* using its inventory management. -.. http:get:: /products +.. http:get:: /private/products This is used to return the list of all items in the inventory. @@ -373,16 +374,10 @@ management. // Product identifier, as found in the product. product_id: string; - // Amount of the product in stock. Given in product-specific units. - // Set to -1 for "infinite" (i.e. for "electronic" books). - stock: integer; - - // unit in which the product is metered (liters, kilograms, packages, etc.) - unit: string; } -.. http:get:: /products/$PRODUCT_ID +.. http:get:: /private/products/$PRODUCT_ID This is used to obtain detailed information about a product in the inventory. @@ -422,24 +417,24 @@ management. // including all existing sales ever. Given in product-specific // units. // A value of -1 indicates "infinite" (i.e. for "electronic" books). - total_stocked: integer; + total_stocked: Integer; // Number of units of the product that have already been sold. - total_sold: integer; + total_sold: Integer; // Number of units of the product that were lost (spoiled, stolen, etc.) - total_lost: integer; + total_lost: Integer; // Identifies where the product is in stock. address: Location; // Identifies when we expect the next restocking to happen. - next_restock?: timestamp; + next_restock?: Timestamp; } -.. http:post:: /products +.. http:post:: /private/products This is used to add a product to the inventory. @@ -488,19 +483,19 @@ management. // including all existing sales ever. Given in product-specific // units. // A value of -1 indicates "infinite" (i.e. for "electronic" books). - total_stocked: integer; + total_stocked: Integer; // Identifies where the product is in stock. address: Location; // Identifies when we expect the next restocking to happen. - next_restock?: timestamp; + next_restock?: Timestamp; } -.. http:patch:: /products/$PRODUCT_ID +.. http:patch:: /private/products/$PRODUCT_ID This is used to update product details in the inventory. Note that the ``total_stocked`` and ``total_lost`` numbers MUST be greater or equal than @@ -522,6 +517,7 @@ management. :status 204 No content: The backend has successfully expanded the inventory. + .. ts:def:: ProductPatchDetail interface ProductPatchDetail { @@ -552,22 +548,22 @@ management. // including all existing sales ever. Given in product-specific // units. // A value of -1 indicates "infinite" (i.e. for "electronic" books). - total_stocked: integer; + total_stocked: Integer; // Number of units of the product that were lost (spoiled, stolen, etc.) - total_lost: integer; + total_lost: Integer; // Identifies where the product is in stock. address: Location; // Identifies when we expect the next restocking to happen. - next_restock?: timestamp; + next_restock?: Timestamp; } -.. http:post:: /products/$PRODUCT_ID/lock +.. http:post:: /private/products/$PRODUCT_ID/lock This is used to lock a certain quantity of the product for a limited duration while the customer assembles a complete order. Note that @@ -606,15 +602,15 @@ management. lock_uuid: UUID; // How long does the frontend intend to hold the lock - duration: time; + duration: RelativeTime; // How many units should be locked? - quantity: integer; + quantity: Integer; } -.. http:delete:: /products/$PRODUCT_ID +.. http:delete:: /private/products/$PRODUCT_ID Delete information about a product. Fails if the product is locked by anyone. @@ -635,7 +631,7 @@ Receiving Payments .. _post-order: -.. http:post:: /orders +.. http:post:: /private/orders Create a new order that a customer can pay for. @@ -646,7 +642,7 @@ Receiving Payments .. note:: This endpoint does not return a URL to redirect your user to confirm the - payment. In order to get this URL use :http:get:`/orders/$ORDER_ID`. The + payment. In order to get this URL use :http:get:/orders/$ORDER_ID. The API is structured this way since the payment redirect URL is not unique for every order, there might be varying parameters such as the session id. @@ -698,6 +694,8 @@ Receiving Payments } + .. ts:def:: Order + type Order : MinimalOrderDetail | ContractTerms; The following fields must be specified in the ``order`` field of the request. Other fields from @@ -739,7 +737,7 @@ Receiving Payments product_id: string; // How many units of the product are requested - quantity: integer; + quantity: Integer; } @@ -758,24 +756,26 @@ Receiving Payments missing_products: OutOfStockEntry; } + .. ts:def:: OutOfStockEntry + interface OutOfStockEntry { // Product ID of an out-of-stock item product_id: string; // Requested quantity - requested_quantity: integer; + requested_quantity: Integer; // Available quantity (must be below ``requested_quanitity``) - available_quantity: integer; + available_quantity: Integer; // When do we expect the product to be again in stock? // Optional, not given if unknown. - restock_expected?: timestamp; + restock_expected?: Timestamp; } -.. http:get:: /orders +.. http:get:: /private/orders Returns known orders up to some point in the past. @@ -833,7 +833,7 @@ Receiving Payments -.. http:post:: /public/orders/$ORDER_ID/claim +.. http:post:: /orders/$ORDER_ID/claim Wallet claims ownership (via nonce) over an order. By claiming an order, the wallet obtains the full contract terms, and thereby @@ -856,14 +856,14 @@ Receiving Payments :status 200 OK: The client has successfully claimed the order. - The response contains the :ref:`contract terms `. + The response contains the :ref:`contract terms `. :status 404 Not found: The backend is unaware of the instance or order. :status 409 Conflict: The someone else claimed the same order ID with different nonce before. -.. http:post:: /public/orders/$ORDER_ID/pay +.. http:post:: /orders/$ORDER_ID/pay Pay for an order by giving a deposit permission for coins. Typically used by the customer's wallet. Note that this request does not include the @@ -947,7 +947,7 @@ Receiving Payments } -.. http:post:: /public/orders/$ORDER_ID/abort +.. http:post:: /orders/$ORDER_ID/abort Abort paying for an order and obtain a refund for coins that were already deposited as part of a failed payment. @@ -995,6 +995,8 @@ Receiving Payments coins: AbortedCoin[]; } + .. ts:def:: AbortedCoin + interface AbortedCoin { // Public key of a coin for which the wallet is requesting an abort-related refund. coin_pub: EddsaPublicKey; @@ -1002,7 +1004,7 @@ Receiving Payments -.. http:get:: /orders/$ORDER_ID/ +.. http:get:: /private/orders/$ORDER_ID/ Merchant checks the payment status of an order. If the order exists but is not payed yet, the response provides a redirect URL. When the user goes to this URL, @@ -1115,7 +1117,7 @@ Receiving Payments } -.. http:get:: /public/orders/$ORDER_ID/ +.. http:get:: /orders/$ORDER_ID/ Query the payment status of an order. This endpoint is for the wallet. When the wallet goes to this URL and it is unpaid, @@ -1165,7 +1167,7 @@ Receiving Payments } -.. http:delete:: /orders/$ORDER_ID +.. http:delete:: /private/orders/$ORDER_ID Delete information about an order. Fails if the order was paid in the last 10 years (or whatever TAX_RECORD_EXPIRATION is set to) or was @@ -1181,12 +1183,13 @@ Receiving Payments The backend refuses to delete the order. +.. _refund: + -------------- Giving Refunds -------------- -.. _refund: -.. http:post:: /orders/$ORDER_ID/refund +.. http:post:: /private/orders/$ORDER_ID/refund Increase the refund amount associated with a given order. The user should be redirected to the ``taler_refund_url`` to trigger refund processing in the wallet. @@ -1230,7 +1233,7 @@ Giving Refunds Tracking Wire Transfers ------------------------ -.. http:post:: /transfers +.. http:post:: /private/transfers Inform the backend over an incoming wire transfer. The backend should inquire about the details with the exchange and mark the respective orders as wired. Note that the request will fail if the WTID is not unique (which should be guaranteed by a correct exchange). This request is idempotent and should also be used to merely re-fetch the @@ -1361,7 +1364,7 @@ Tracking Wire Transfers } - .. ts:def:: TrackTransferProof + .. ts:def:: TrackTransferProof interface TrackTransferProof { // signature from the exchange made with purpose @@ -1381,7 +1384,7 @@ Tracking Wire Transfers -.. http:get:: /transfers +.. http:get:: /private/transfers Obtain a list of all wire transfers the backend has checked. @@ -1406,6 +1409,8 @@ Tracking Wire Transfers transfers : TransferDetails[]; } + .. ts:def:: TransferDetails + interface TransferDetails { // how much was wired to the merchant (minus fees) credit_amount: Amount; @@ -1441,7 +1446,7 @@ Giving Customer Tips -------------------- .. _tips: -.. http:post:: /reserves +.. http:post:: /private/reserves Create a reserve for tipping. @@ -1460,7 +1465,7 @@ Giving Customer Tips :status 200 OK: The backend is waiting for the reserve to be established. The merchant must now perform the wire transfer indicated in the `ReserveCreateConfirmation`. - :status 424 Failed Depencency: + :status 424 Failed Dependency: We could not obtain /wire details from the specified exchange base URL. .. ts:def:: ReserveCreateRequest @@ -1485,7 +1490,7 @@ Giving Customer Tips } -.. http:get:: /reserves +.. http:get:: /private/reserves Obtain list of reserves that have been created for tipping. @@ -1541,7 +1546,7 @@ Giving Customer Tips } -.. http:get:: /reserves/$RESERVE_PUB +.. http:get:: /private/reserves/$RESERVE_PUB Obtain information about a specific reserve that have been created for tipping. @@ -1604,12 +1609,12 @@ Giving Customer Tips total_amount: Amount; // Human-readable reason for why the tip was granted. - reason: String; + reason: string; } -.. http:post:: /reserves/$RESERVE_PUB/authorize-tip +.. http:post:: /private/reserves/$RESERVE_PUB/authorize-tip Authorize creation of a tip from the given reserve. @@ -1658,7 +1663,7 @@ Giving Customer Tips } -.. http:post:: /tips +.. http:post:: /private/tips Authorize creation of a tip from the given reserve, except with automatic selection of a working reserve of the instance by the @@ -1680,7 +1685,7 @@ Giving Customer Tips in all of the reserves of the instance. -.. http:delete:: /reserves/$RESERVE_PUB +.. http:delete:: /private/reserves/$RESERVE_PUB Delete information about a reserve. Fails if the reserve still has committed to tips that were not yet picked up and that have not yet @@ -1703,7 +1708,7 @@ Giving Customer Tips -.. http:get:: /tips/$TIP_ID +.. http:get:: /private/tips/$TIP_ID Obtain information about a particular tip. @@ -1729,7 +1734,7 @@ Giving Customer Tips total_picked_up: Amount; // Human-readable reason given when authorizing the tip. - reason: String; + reason: string; // Timestamp indicating when the tip is set to expire (may be in the past). expiration: Timestamp; @@ -1750,7 +1755,7 @@ Giving Customer Tips pickup_id: HashCode; // Number of planchets involved. - num_planchets: integer; + num_planchets: Integer; // Total amount requested for this pickup_id. requested_amount: Amount; @@ -1761,7 +1766,7 @@ Giving Customer Tips } -.. http:post:: /public/tips/$TIP_ID/pickup +.. http:post:: /tips/$TIP_ID/pickup Handle request from wallet to pick up a tip. @@ -1812,10 +1817,12 @@ Giving Customer Tips blind_sigs: BlindSignature[]; } + .. ts:def:: BlindSignature + interface BlindSignature { // The (blind) RSA signature. Still needs to be unblinded. - blind_sig: RsaSignature; + blind_sig: BlindedRsaSignature; } @@ -1826,7 +1833,7 @@ Giving Customer Tips The Contract Terms ------------------ -.. _contract_terms:: +.. _contract-terms: The contract terms must have the following structure: @@ -1968,7 +1975,7 @@ The contract terms must have the following structure: description_i18n?: { [lang_tag: string]: string }; // The number of units of the product to deliver to the customer. - quantity: integer; + quantity: Integer; // The unit in which the product is measured (liters, kilograms, packages, etc.) unit: string; -- cgit v1.2.3 From 5823ad8b68e7259de00fda3c1187e046ae04abbd Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 20 Apr 2020 23:40:15 +0200 Subject: update spec --- core/api-merchant.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index 002dc976..b8c9eae8 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -170,7 +170,7 @@ Dynamic Merchant Instances // If the frontend does NOT specify a payment deadline, how long should // offers we make be valid by default? - default_pay_deadline: RelativeTime; + default_pay_delay: RelativeTime; } @@ -230,7 +230,7 @@ Dynamic Merchant Instances // If the frontend does NOT specify a payment deadline, how long should // offers we make be valid by default? - default_pay_deadline: RelativeTime; + default_pay_delay: RelativeTime; } @@ -300,7 +300,7 @@ Dynamic Merchant Instances h_wire: HashCode; // salt used to compute h_wire - salt: string; + salt: HashCode; // true if this account is active, // false if it is historic. -- cgit v1.2.3 From fc155c001adaa71c1dea164b91a923f63c497a4f Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 21 Apr 2020 10:29:37 +0200 Subject: expand repurchase detection text based on Florian's feedback --- taler-merchant-api-tutorial.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/taler-merchant-api-tutorial.rst b/taler-merchant-api-tutorial.rst index d42f74b0..438c1cd9 100644 --- a/taler-merchant-api-tutorial.rst +++ b/taler-merchant-api-tutorial.rst @@ -309,7 +309,11 @@ the same digital product where repurchase detection is desired. Note that changing the session ID to a different device requires the involvement of the wallet that made the payment, thus reasonably limiting the -possibility of broadly sharing the digital purchases. +possibility of broadly sharing the digital purchases. Repurchase detection is +also *only* done for HTTP(S) fulfillment URLs. In particular, this means +fulfillment URIs like "taler://fulfillment-success/$MESSAGE" are not +considered to identify a resource you can pay for and thus do not have to be +unique. .. _Giving-Customers-Tips: -- cgit v1.2.3 From f88e32c24f218e00db6334920421cd305f077421 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Thu, 23 Apr 2020 16:17:08 +0530 Subject: tos rendering design doc --- design-documents/000-template.rst | 23 +++++++++- design-documents/003-tos-rendering.rst | 84 ++++++++++++++++++++++++++++++++++ design-documents/index.rst | 1 + 3 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 design-documents/003-tos-rendering.rst diff --git a/design-documents/000-template.rst b/design-documents/000-template.rst index c969f862..f620248d 100644 --- a/design-documents/000-template.rst +++ b/design-documents/000-template.rst @@ -1,4 +1,25 @@ Template ######## -FIXME: define template +Summary +======= + +Motivation +========== + +Requirements +============ + +Proposed Solution +================= + +Alternatives +============ + +Drawbacks +========= + +Discussion / Q&A +================ + +(This should be filled in with results from discussions on mailing lists / personal communication.) diff --git a/design-documents/003-tos-rendering.rst b/design-documents/003-tos-rendering.rst new file mode 100644 index 00000000..c945654c --- /dev/null +++ b/design-documents/003-tos-rendering.rst @@ -0,0 +1,84 @@ +Design Doc 003: ToS rendering +############################# + +Summary +======= + +This document describes how terms of service (ToS) as well as other "legal +agreement documents" are served, represented and rendered. + +Motivation +========== + +Different exchanges and backup/sync providers each have their custom legal +agreement documents. As we don't know all providers and they are not centrally +registered anywhere, these documents can't be hardcoded into wallet +applications. Instead, these service providers expose endpoints that allow +downloading the latest version of these legal agreement documents. + +These documents must be rendered on a variety of platforms in a user-friendly +way. + +Proposed Solution +================= + +The service providers can output legal agreements in various formats, +determined via the ``"Accept: "`` request header. The format provider **must** +support the ``text/plain`` mime type. The format provider **should** support +the ``text/markdown`` mime type. Except for styling and navigation, the +content of each format of the same legal agreement document **should** be the +same. + +Legal documents with mime type ``text/markdown`` **should** confirm to the +`commonmark specification `__. + +When wallets render ``text/markdown`` legal documents, they **must** disable +embedded HTML rendering. Wallets **may** style the markdown rendering to improve +usability. For example, they can make sections collabsible or add a nagivation side-bar +on bigger screens. + +It is recommended that the ``text/markdown`` document is used as the "master +document" for generating the corresponding legal agreement document in other +formats. However, service providers can also provide custom versions with more +appropriate styling, like a logo in the header of a printable PDF document. + +Alternatives +============ + +We considered and rejected the following alternatives: + +* Use only plain text. This is not user-friendly, as inline formatting (bold, + italic), styled section headers, paragraphs wrapped to the screen size, + formatted lists and tables are not supported. + +* Use HTML. This has a variety of issues: + + * Service providers might provide HTML that does not render nicely on the + device that our wallet application is running on. + * Rendering HTML inside the application poses security risks. + +* Use a strict subset of HTML. This would mean we would have to define some + standardized subset that all wallet implementations support, which is too + much work. Existing HTML renderers (such as Android's ``Html.fromHTML``) + support undocumented subsets that lack features we want, such as ordered + lists. Defining our own HTML subset would also make authoring harder, as it + forces authors of legal agreement documents to author in our HTML subset, as + conversion tools from other format will not generate output in our HTML + subset. + +* Use reStructuredText (directly or via Sphinx). This at first looks like an + obvious choice for a master format, since Taler is already using reStructuredText + for all its documentation. But it doesn't work out well, since the only maintained + implementation of a parser/renderer is written in Python. Even with the Python implementation + (docutils / Sphinx), we can't convert ``.rst`` to Markdown nicely. + +Drawbacks +========= + +* Markdown parsing / rendering libraries can be relatively large. + +Discussion / Q&A +================ + +* Should the legal agreement endpoints have some mechanism to determine what + content types they support? diff --git a/design-documents/index.rst b/design-documents/index.rst index 609cc2d0..4f3732ab 100644 --- a/design-documents/index.rst +++ b/design-documents/index.rst @@ -12,3 +12,4 @@ and protocol. 000-template 001-new-browser-integration 002-wallet-exchange-management + 003-tos-rendering -- cgit v1.2.3 From 4746e24c0eeebcafdc204830240f6cbc4d3c378d Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Thu, 23 Apr 2020 16:31:44 +0530 Subject: compatibility with latest sphinx --- _exts/typescriptdomain.py | 1 + 1 file changed, 1 insertion(+) diff --git a/_exts/typescriptdomain.py b/_exts/typescriptdomain.py index b0780eae..44e30f7b 100644 --- a/_exts/typescriptdomain.py +++ b/_exts/typescriptdomain.py @@ -499,6 +499,7 @@ class MyHtmlBuilder(StandaloneHTMLBuilder): self.highlighter = MyPygmentsBridge( self, self.config.trim_doctest_flags ) + self.dark_highlighter = None def get_annotation(tok, key): -- cgit v1.2.3 From 891570eadc319a1ef14b26f934d747a1c00cc73a Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Thu, 23 Apr 2020 16:34:20 +0530 Subject: add HTTP 308 --- _exts/httpdomain/httpdomain.py | 1 + 1 file changed, 1 insertion(+) diff --git a/_exts/httpdomain/httpdomain.py b/_exts/httpdomain/httpdomain.py index f2569b5e..59665a05 100644 --- a/_exts/httpdomain/httpdomain.py +++ b/_exts/httpdomain/httpdomain.py @@ -196,6 +196,7 @@ HTTP_STATUS_CODES = { 304: 'Not Modified', 305: 'Use Proxy', 307: 'Temporary Redirect', + 308: 'Permanent Redirect', 400: 'Bad Request', 401: 'Unauthorized', 402: 'Payment Required', # unused -- cgit v1.2.3 From 6a9c36ad28f4316d3acea7b9fd3044b0e707461a Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Thu, 23 Apr 2020 16:34:27 +0530 Subject: syntax fix --- core/api-common.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/api-common.rst b/core/api-common.rst index 294e33d5..93d6d09e 100644 --- a/core/api-common.rst +++ b/core/api-common.rst @@ -554,12 +554,14 @@ uses 512-bit hash codes (64 bytes). }; .. _WireTransferIdentifierRawP: +.. sourcecode:: c struct WireTransferIdentifierRawP { uint8_t raw[32]; }; .. _UUID: +.. sourcecode:: c struct UUID { uint32_t value[4]; -- cgit v1.2.3 From d45af5cacdf719c368af806619405f2dd1d2275b Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Thu, 23 Apr 2020 16:47:27 +0530 Subject: fix index --- genindex.rst | 2 ++ index.rst | 1 + taler-merchant-api-tutorial.rst | 18 +++++++++++------- 3 files changed, 14 insertions(+), 7 deletions(-) create mode 100644 genindex.rst diff --git a/genindex.rst b/genindex.rst new file mode 100644 index 00000000..98f0d6ef --- /dev/null +++ b/genindex.rst @@ -0,0 +1,2 @@ +Complete Index +============== diff --git a/index.rst b/index.rst index 2ead8f27..1a4d56c5 100644 --- a/index.rst +++ b/index.rst @@ -66,6 +66,7 @@ Documentation Overview libeufin/index global-licensing manindex + genindex .. toctree:: :hidden: diff --git a/taler-merchant-api-tutorial.rst b/taler-merchant-api-tutorial.rst index 438c1cd9..34064a04 100644 --- a/taler-merchant-api-tutorial.rst +++ b/taler-merchant-api-tutorial.rst @@ -80,11 +80,12 @@ Some functionality of the backend (the “public interface“) is also exposed to the customer’s browser directly. In the HTTP API, all public endpoints are prefixed with ``/public/``. + +.. index:: sandbox, authorization + Public Sandbox Backend and Authentication ----------------------------------------- -:keywords: sandbox -:keywords: authorization How the frontend authenticates to the Taler backend depends on the configuration. See Taler Merchant Operating Manual. @@ -107,10 +108,11 @@ The sandbox backend https://backend.demo.taler.net/ uses ``KUDOS`` as an imaginary currency. Coins denominated in ``KUDOS`` can be withdrawn from https://bank.demo.taler.net/. +.. index:: instance + Merchant Instances ------------------ -:keywords: instance The same Taler merchant backend server can be used by multiple separate merchants that are separate business entities. Each of these separate business entities is called a *merchant instance*, and is identified by @@ -136,10 +138,11 @@ not affiliated with or officially approved by the respective projects. Accepting a Simple Payment ========================== +.. index:: order + Creating an Order for a Payment ------------------------------- -:keywords: order Payments in Taler revolve around an *order*, which is a machine-readable description of the business transaction for which the payment is to be made. Before accepting a Taler payment as a merchant you must create @@ -225,11 +228,11 @@ usually needs to trigger the business logic for the merchant to fulfill the merchant’s obligations under the contract. .. _Giving-Refunds: +.. index:: refunds Giving Refunds ============== -:keywords: refunds A refund in GNU Taler is a way to “undo” a payment. It needs to be authorized by the merchant. Refunds can be for any fraction of the original amount paid, but they cannot exceed the original payment. @@ -275,10 +278,11 @@ This code snipped illustrates giving a refund: +.. index:: repurchase + Repurchase detection and fulfillment URLs ========================================= -:keywords: repurchase A possible problem for merchants selling access to digital articles is that a customer may have paid for an article on one device, but may then want to read it on a different device, possibly one that @@ -317,11 +321,11 @@ unique. .. _Giving-Customers-Tips: +.. index:: tips Giving Customers Tips ===================== -:keywords: tips GNU Taler allows Web sites to grant small amounts directly to the visitor. The idea is that some sites may want incentivize actions such as filling out a survey or trying a new feature. It is important to note -- cgit v1.2.3 From 3c1500b932e81453d5acbb0b83422953dd56a0ec Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Thu, 23 Apr 2020 14:13:06 -0300 Subject: exchanges MUST provide ToS in markdown format --- design-documents/003-tos-rendering.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/design-documents/003-tos-rendering.rst b/design-documents/003-tos-rendering.rst index c945654c..5f6d8157 100644 --- a/design-documents/003-tos-rendering.rst +++ b/design-documents/003-tos-rendering.rst @@ -24,7 +24,7 @@ Proposed Solution The service providers can output legal agreements in various formats, determined via the ``"Accept: "`` request header. The format provider **must** -support the ``text/plain`` mime type. The format provider **should** support +support the ``text/plain`` mime type. The format provider **must** support the ``text/markdown`` mime type. Except for styling and navigation, the content of each format of the same legal agreement document **should** be the same. -- cgit v1.2.3 From d2a49c7f9998249cf4ed23c631bdbc976b9ba8cf Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Thu, 23 Apr 2020 16:08:41 -0300 Subject: Add Design Doc 004: Wallet Withdrawal Flow --- conf.py | 5 + design-documents/004-wallet-withdrawal-flow.rst | 129 ++++++++++++++++++++++++ design-documents/index.rst | 1 + 3 files changed, 135 insertions(+) create mode 100644 design-documents/004-wallet-withdrawal-flow.rst diff --git a/conf.py b/conf.py index 4010d57b..a1a653af 100644 --- a/conf.py +++ b/conf.py @@ -57,6 +57,7 @@ extensions = [ 'sphinx.ext.imgmath', 'httpdomain.httpdomain', 'recommonmark', + 'sphinx.ext.graphviz', ] # Add any paths that contain templates here, relative to this directory. @@ -350,3 +351,7 @@ texinfo_documents = [ # If true, do not generate a @detailmenu in the "Top" node's menu. #texinfo_no_detailmenu = False + +# The output format for Graphviz when building HTML files. +# This must be either 'png' or 'svg'; the default is 'png'. +graphviz_output_format = 'svg' diff --git a/design-documents/004-wallet-withdrawal-flow.rst b/design-documents/004-wallet-withdrawal-flow.rst new file mode 100644 index 00000000..e448a773 --- /dev/null +++ b/design-documents/004-wallet-withdrawal-flow.rst @@ -0,0 +1,129 @@ +Design Doc 004: Wallet Withdrawal Flow +###################################### + +Summary +======= + +This document describes the recommended way of implementing the user experience +of withdrawing digital cash in GNU Taler wallets. + +Motivation +========== + +When digital cash is withdrawn, it is tied to and in custody of an exchange. +There can be many exchanges offered by different entities, +each having their custom legal agreement documents and fee structures. +The user is free to choose an exchange. +Therefore, the process of withdrawing needs to account for this choice. + +Proposed Solution +================= + +There are three screens involved in the process: + +1. **Select exchange**: + Here the user can pick an exchange from a list of known exchanges + or add a new one for immediate use. + For details see :doc:`002-wallet-exchange-management`. +2. **Display an exchange's Terms of Service**: + Shows the terms and gives an option to accept them. + For details see :doc:`003-tos-rendering`. +3. **Withdrawal details and confirmation**: + This should show the amount to be withdrawn along with its currency, + the currently selected exchange and the fee charged by it for the withdrawal. + +The user flow between these screens is described in the following graph: + +.. graphviz:: + + digraph G { + rankdir=LR; + nodesep=0.5; + default_exchange [ + label = "Has default\nexchange?"; + shape = diamond; + ]; + tos_changed [ + label = "ToS\nchanged?"; + shape = diamond; + ]; + tos_accepted [ + label = "ToS\naccepted?"; + shape = diamond; + ]; + accept_tos [ + label = "Accept\nToS?"; + shape = diamond; + ]; + withdrawal_action [ + label = "Withdrawal\nAction"; + shape = diamond; + ]; + select_exchange [ + label = "Select\nexchange"; + shape = rect; + ]; + tos [ + label = "ToS"; + shape = rect; + ]; + withdraw [ + label = "Confirm\nwithdrawal"; + shape = rect; + ]; + transactions [ + label = "Transactions"; + shape = circle; + ]; + + default_exchange -> tos_changed [label="Yes"]; + default_exchange -> select_exchange [label="No"]; + tos_changed -> tos [label="Yes"]; + tos_changed -> withdraw [label="No"]; + select_exchange -> tos_accepted; + tos_accepted -> tos_changed [label="Yes"]; + tos_accepted -> tos [label="No"]; + tos -> accept_tos; + accept_tos -> withdraw [label="Yes"]; + accept_tos -> select_exchange [label="No"]; + withdraw -> withdrawal_action; + withdrawal_action -> transactions [label="Confirm"]; + withdrawal_action -> select_exchange [label="Change Exchange"]; + + { rank=same; tos_accepted; tos_changed; } + { rank=same; select_exchange; tos; } + { rank=same; withdrawal_action; withdraw; } + } + +This enables the user to change the current exchange at any time in the process. +It ensures that the latest version of the exchange's terms of service have been accepted by the user +before allowing them to confirm the withdrawal. + +Some special regional or test currencies might have only a single known exchange. +For those, the wallet should not offer the option to change an exchange. + +Alternatives +============ + +We considered and rejected the following alternatives: + +* Do not allow more than one exchange to make Taler simpler to use and understand: + Taler wants to allow custom exchanges for custom currencies + and foster competition between exchanges for the same currency + to provide the best possible service to users at the lowest fee. +* Do not require acceptance to terms of service: + Having these terms and prompting the user to accept them + is a legal and business requirement in many jurisdictions, + so Taler needs to support them. + However, Taler encourages exchanges to keep their terms as short and simple as possible. + +Discussion / Q&A +================ + +* Should wallets pre-set a default exchange for the most common currencies, + so that users will not be burdened to understand exchanges and their fee structures + when making their first withdrawal? + This could increase user retention, but discourage +* What should happen when an exchange changes its terms of service + and the user wants to use the funds stored there, + but does not initiate a new withdrawal with that exchange? diff --git a/design-documents/index.rst b/design-documents/index.rst index 4f3732ab..aa0ca65a 100644 --- a/design-documents/index.rst +++ b/design-documents/index.rst @@ -13,3 +13,4 @@ and protocol. 001-new-browser-integration 002-wallet-exchange-management 003-tos-rendering + 004-wallet-withdrawal-flow -- cgit v1.2.3 From 8ad917c84fb5d12797f0e70f7f0b895849a52187 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Fri, 24 Apr 2020 13:02:30 +0530 Subject: taler.conf clarification --- manpages/taler.conf.5.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/manpages/taler.conf.5.rst b/manpages/taler.conf.5.rst index 5c2b7558..d7ca470c 100644 --- a/manpages/taler.conf.5.rst +++ b/manpages/taler.conf.5.rst @@ -262,9 +262,9 @@ WIRE_RESPONSE (exchange and merchant) taler-merchant-httpd (to generate and then use the file). HONOR_instance - Must be set to YES for the instances (where "instance" is the section - name of the instance) of the merchant backend that should allow - incoming wire transfers for this bank account. + Must be set to YES for the instances (where "instance" is the section name + of the instance) of the merchant backend that should accept payments (i.e. + Taler deposit operations) with the corresponding payto URI. ACTIVE_instance Must be set to YES for the instances (where “instance” is the section -- cgit v1.2.3 From 69a679117bc6a8426f36e2c2c7edf250391cdb24 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Fri, 24 Apr 2020 15:30:37 +0530 Subject: document decision for wallet integration --- design-documents/001-new-browser-integration.rst | 26 +++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/design-documents/001-new-browser-integration.rst b/design-documents/001-new-browser-integration.rst index f436a4f7..8dbe2a43 100644 --- a/design-documents/001-new-browser-integration.rst +++ b/design-documents/001-new-browser-integration.rst @@ -1,10 +1,30 @@ Design Doc 001: New Browser Integration ####################################### -.. note:: +.. warning:: - This design document is currently a draft, it - does not reflect any implementation decisions yet. + We have decided not to follow through with the proposed solution in this + design doc. We care a lot about a nice upgrade path for when better + browser integration becomes available. Encouraging the ``#taler://`` fragment + based integration might lead merchant frontends to **only** support this type + of integration. + + Instead, the following path will be taken: + + 1. CSS-based presence detection will be removed from the wallet, + as there is no satisfactory upgrade path to better mechanisms + 2. Manual triggering will be implemented as described in this design doc. + 3. The ``webRequest`` permission that allows ``"Taler: "`` header based + browser integration will become opt-in. + 4. The interactive API will be put on hold. Instead, SPAs should + ask the user to open the wallet popup (and/or render a QR code for mobile wallets). + 5. To enable easier integration for merchants, the reference merchant backend + might include a page to trigger payments, which displays the QR code + correctly, does long-polling via JS and serves the ``"Taler: "`` header. + 6. The presence detection ``taler://`` URI described in this document + will **not** be supported, as allowing presence detection might + encourage merchants to treat mobile / detached wallets as 2nd class + citizens. Summary ======= -- cgit v1.2.3 From 0b3dbb1972bc9ef0f202467aa0aebd9a98cb7f0b Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Mon, 27 Apr 2020 10:59:53 -0300 Subject: Add proposal for wallet transactions API --- taler-wallet.rst | 154 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) diff --git a/taler-wallet.rst b/taler-wallet.rst index c619d430..6223512f 100644 --- a/taler-wallet.rst +++ b/taler-wallet.rst @@ -77,6 +77,160 @@ Android Wallet APIs and Data Formats ===================== +.. warning:: + + These APIs are still a work in progress and *not* final. + +Transactions +------------ + +Transactions are all operations or events that are affecting the balance. + +:name: ``"transactions"`` +:description: Get a list of past and pending transactions. +:request: + .. ts:def:: TransactionsRequest + + interface TransactionsRequest { + // return only transactions in the given currency + currency: string; + + // if present, results will be limited to transactions related to the given search string + search?: string; + } +:response: + .. ts:def:: TransactionsResponse + + interface TransactionsResponse { + // a list of past and pending transactions + transactions: Transaction[]; + } + + .. ts:def:: Transaction + + interface Transaction { + // opaque unique ID for the transaction, used as a starting point for paginating queries + // and for invoking actions on the transaction (e.g. deleting/hiding it from the history) + transactionId: string; + + // the type of the transaction; different types might provide additional information + type: TransactionType; + + // main timestamp of the transaction + timestamp: Timestamp; + + // true if the transaction is still pending, false otherwise + pending: boolean; + } + + .. ts:def:: TransactionType + + type TransactionType = ( + TransactionWithdrawal | + TransactionPayment | + TransactionRefund | + TransactionTip + ) + + .. ts:def:: TransactionWithdrawal + + // This should only be used for actual withdrawals + // and not for tips that have their own transactions type. + interface TransactionWithdrawal extends Transaction { + type: string = "withdrawal", + + // Exchange that was withdrawn from. + exchangeBaseUrl: string; + + // If the withdrawal is pending, this can include a Url for extra user confirmation. + bankWithdrawConfirmUrl?: string; + + // Amount that has been subtracted from the reserve's balance for this withdrawal. + amountRaw: Amount; + + // Amount that actually was (or will be) added to the wallet's balance. + amountEffective: Amount; + } + + .. ts:def:: TransactionPayment + + interface TransactionPayment extends Transaction { + type: string = "payment", + + // Additional information about the payment. + info: TransactionInfo; + + // Amount that was paid, including deposit, wire and refresh fees. + amountEffective: Amount; + } + + .. ts:def:: TransactionInfo + + interface TransactionInfo { + // Order ID, uniquely identifies the order within a merchant instance + orderId: string; + + // More information about the merchant + merchant: Merchant; + + // Amount that must be paid for the contract + amount: Amount; + + // Summary of the order, given by the merchant + summary: string; + + // Map from IETF BCP 47 language tags to localized summaries + summary_i18n?: { [lang_tag: string]: string }; + + // List of products that are part of the order + products: Product[]; + + // URL of the fulfillment, given by the merchant + fulfillmentUrl: string; + } + + .. ts:def:: TransactionRefund + + interface TransactionRefund extends Transaction { + type: string = "refund", + + // Additional information about the refunded payment + info: TransactionInfo; + + // Part of the refund that couldn't be applied because the refund permissions were expired + amountInvalid: Amount; + + // Amount that has been refunded by the merchant + amountRaw: Amount; + + // Amount will be added to the wallet's balance after fees and refreshing + amountEffective: Amount; + } + + .. ts:def:: TransactionTip + + interface TransactionTip extends Transaction { + type: string = "tip", + + // true if the user still needs to accept/decline this tip + waiting: boolean; + + // true if the user has accepted this top, false otherwise + accepted: boolean; + + // Exchange that the tip will be (or was) withdrawn from + exchangeBaseUrl: string; + + // More information about the merchant that sent the tip + merchant: Merchant; + + // Raw amount of the tip, without extra fees that apply + amountRaw: Amount; + + // Amount will be (or was) added to the wallet's balance after fees and refreshing + amountEffective: Amount; + } + Refunds ------- -- cgit v1.2.3 From 062769f73d73880b4e138540b92932f39e103338 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Mon, 27 Apr 2020 23:58:38 +0530 Subject: wallet backup&sync --- design-documents/005-wallet-backup-sync.rst | 146 ++++++++++++++++++++++++++++ design-documents/index.rst | 1 + 2 files changed, 147 insertions(+) create mode 100644 design-documents/005-wallet-backup-sync.rst diff --git a/design-documents/005-wallet-backup-sync.rst b/design-documents/005-wallet-backup-sync.rst new file mode 100644 index 00000000..0bba03e2 --- /dev/null +++ b/design-documents/005-wallet-backup-sync.rst @@ -0,0 +1,146 @@ +Design Doc 005: Wallet Backup and Sync +###################################### + +.. warning:: + + This is an unfinished draft. + +Summary +======= + +This document discusses considerations for backup and synchronization of wallets. + + +Requirements +============ + +* Backup and sync must not require any synchronous communication between the + wallets +* Wallets operating (payments/withdrawals/...) for longer periods of time without + synchronizing should be handled well +* Conflicts should be resolved automatically in pretty much all cases +* One wallet can be enrolled with multiple sync servers, and a wallet can + join +* Other wallets connected to the sync server are trusted. + +Proposed Solution +================= + +The blob stored on the backup/sync server is a compressed and encrypted JSON file. + +The various entity types managed by the wallet are modeled LWW-Sets (Last Write +Wins Set CRDT). Timestamps for inserts/deletes are are Lamport timestamps. Concurrent, conflicting insert/delete +operations are resolved in favor of "delete". + +The managed entities are: + + * set of exchanges with the data from /keys, /wire + * set of directly trusted exchange public keys + * set of trusted auditors for currencies + * set of reserves together with reserve history + * set of accepted bank withdrawal operations + * set of coins together with coin history and blinding secret (both for normal withdrawal and refresh) + and coin source info (refresh operation, tip, reserve) + * set of purchases (contract terms, applied refunds, ...) + +(Some of these might be further split up to allow more efficient updates.) + +Entities that are **not** synchronized are: + +* purchases before the corresponding order has been claimed +* withdrawal operations before they have been accepted by the user + +Entities that **could** be synchronized (to be decided): + +* private keys of other sync accounts +* coin planchets +* tips before the corresponding coins have been withdrawn +* refresh sessions (not only the "meta data" about the operation, + but everything) + + +Garbage collection +------------------ + +There are two types of garbage collection involved: + +1. CRDT tombstones / other administrative data in the sync blob. These can be deleted + after we're sure all wallets enrolled in the sync server have a Lamport timestamp + larger than the timestamp of the tombstone. Wallets include their own Lamport timestamp + in the sync blob: + + .. code:: javascript + + { + clocks: { + my_desktop_wallet: 5, + my_phone_wallet: 3 + }, + ... + } + + All tombstones / overwritten set elements with a timestamp smaller than the + smallest clock value can be deleted. + +2. Normal wallet GC. The deletion operations resulting from the wallet garbage + collection (i.g. deleting legally expired denomination keys, coins, exchange + signing keys, ...) are propagated to the respective CRDT set in the sync + blob. + + +Ghost Entities +-------------- + +Sometimes a wallet can learn about an operation that happened in another synced +wallet **before** a sync over the sync server happens. An example of this is a +deposit operation. When two synced wallets spend the same coin on something, +one of them will receive an error from the exchange that proves the coin has +been spent on something else. The wallet will add a "ghost entry" for such an +event, in order to be able to show a consistent history (i.e. all numbers +adding up) to the user. + +When the two wallets sync later, the ghost entry is replaced by the actual +purchase entity from the wallet that initiated the spending. + +Ghost entities are not added to the sync state. + + +References +========== + +* Shapiro, M., Preguiça, N., Baquero, C., & Zawirski, M. (2011). A + comprehensive study of convergent and commutative replicated data types. [`PDF `__] + +Discussion / Q&A +================ + +* Why is backup/sync not split into two services / use-cases? + + * For privacy reasons, we can't use some interactive sync service. Thus we + use the backup blob as a CRDT that also synchronization for us. + +* Do we synchronize the list of other backup enrollments? How + do we handle distributing the different private keys for them? + + * If we automatically sync the sync enrollments and the old sync account + is compromised, the new sync account would automatically be compromised as well! + + * If every wallet had its own sync key pair, we could select which existing wallets + to roll over as well. + +* How do we handle a synced wallet that becomes malicious deleting all coins or purchased products? + + * This needs to balance the genuine need to permanently delete data. + * Should the sync server allow to fetch previous versions of the sync blob? + * Should the individual wallets keep tombstones (i.e. entities just marked as deleted) + around for some time, or should they delete and "sanitize" (delete data not needed for the CRDT) + tombstones as soon as possible? + +* How are wallets identified for backup/sync? + + * UUID / EdDSA pub and nick name? When nickname clashes, + some number is added based on lexical sort of the random id ("phone#1", "phone#2"). + +* Do we have a passphrase for our backup account key(s)? + + * ??? diff --git a/design-documents/index.rst b/design-documents/index.rst index aa0ca65a..590cd451 100644 --- a/design-documents/index.rst +++ b/design-documents/index.rst @@ -14,3 +14,4 @@ and protocol. 002-wallet-exchange-management 003-tos-rendering 004-wallet-withdrawal-flow + 005-wallet-backup-sync -- cgit v1.2.3 From b589f49c55ed8943488dccfd265c5523bb257a0a Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Tue, 28 Apr 2020 00:01:10 +0530 Subject: formatting --- design-documents/005-wallet-backup-sync.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/design-documents/005-wallet-backup-sync.rst b/design-documents/005-wallet-backup-sync.rst index 0bba03e2..75f387fa 100644 --- a/design-documents/005-wallet-backup-sync.rst +++ b/design-documents/005-wallet-backup-sync.rst @@ -34,14 +34,14 @@ operations are resolved in favor of "delete". The managed entities are: - * set of exchanges with the data from /keys, /wire - * set of directly trusted exchange public keys - * set of trusted auditors for currencies - * set of reserves together with reserve history - * set of accepted bank withdrawal operations - * set of coins together with coin history and blinding secret (both for normal withdrawal and refresh) - and coin source info (refresh operation, tip, reserve) - * set of purchases (contract terms, applied refunds, ...) +* set of exchanges with the data from /keys, /wire +* set of directly trusted exchange public keys +* set of trusted auditors for currencies +* set of reserves together with reserve history +* set of accepted bank withdrawal operations +* set of coins together with coin history and blinding secret (both for normal withdrawal and refresh) + and coin source info (refresh operation, tip, reserve) +* set of purchases (contract terms, applied refunds, ...) (Some of these might be further split up to allow more efficient updates.) -- cgit v1.2.3 From 1c8c1a4c507e5d5d2b6a6fb272f0066c04da84d1 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Tue, 28 Apr 2020 00:09:06 +0530 Subject: coin assignment --- design-documents/005-wallet-backup-sync.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/design-documents/005-wallet-backup-sync.rst b/design-documents/005-wallet-backup-sync.rst index 75f387fa..2a8ef3ee 100644 --- a/design-documents/005-wallet-backup-sync.rst +++ b/design-documents/005-wallet-backup-sync.rst @@ -42,6 +42,7 @@ The managed entities are: * set of coins together with coin history and blinding secret (both for normal withdrawal and refresh) and coin source info (refresh operation, tip, reserve) * set of purchases (contract terms, applied refunds, ...) +* assignment of coins to their "primary wallet" (Some of these might be further split up to allow more efficient updates.) -- cgit v1.2.3 From 856a101e5ff8f6a7d199da9b59e9e559c5cbf5e0 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Tue, 28 Apr 2020 00:22:02 +0530 Subject: multi sync --- design-documents/005-wallet-backup-sync.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/design-documents/005-wallet-backup-sync.rst b/design-documents/005-wallet-backup-sync.rst index 2a8ef3ee..d91c3ff5 100644 --- a/design-documents/005-wallet-backup-sync.rst +++ b/design-documents/005-wallet-backup-sync.rst @@ -106,6 +106,19 @@ purchase entity from the wallet that initiated the spending. Ghost entities are not added to the sync state. +Multiple sync servers +--------------------- + +When a wallet is connected to multiple sync servers, it automatically +propagates changes it received from one sync server to the others. Local +changes made by the wallet are propoagated to all sync servers. The goal of +this is to make the state of the sync servers converge. + +The different sync servers one wallet is enrolled with do not necessarily +have the same set of other wallet enrolled. Each sync server has a separate Lamport clock +and contains a separate CRDT. + + References ========== -- cgit v1.2.3 From c811b1a396f2edf1239e2bbc6364d5ea1f2f3556 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Tue, 28 Apr 2020 10:00:31 -0300 Subject: add confirmation flag to wallet API withdrawal transaction --- taler-wallet.rst | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/taler-wallet.rst b/taler-wallet.rst index 6223512f..8c2d7eba 100644 --- a/taler-wallet.rst +++ b/taler-wallet.rst @@ -142,8 +142,13 @@ Transactions are all operations or events that are affecting the balance. // Exchange that was withdrawn from. exchangeBaseUrl: string; - // If the withdrawal is pending, this can include a Url for extra user confirmation. - bankWithdrawConfirmUrl?: string; + // true if the bank has confirmed the withdrawal, false if not. + // An unconfirmed withdrawal usually requires user-input and should be highlighted in the UI. + // See also bankConfirmationUrl below. + confirmed: boolean; + + // If the withdrawal is unconfirmed, this can include a URL for user initiated confirmation. + bankConfirmationUrl?: string; // Amount that has been subtracted from the reserve's balance for this withdrawal. amountRaw: Amount; -- cgit v1.2.3 From 8a6d90384d3e1af4412c1be91e8e2ca9c777c183 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Tue, 28 Apr 2020 12:19:30 -0300 Subject: update build instructions for Android apps --- developers-manual.rst | 46 ++++++++++++++++++++++------------------------ taler-wallet.rst | 2 +- 2 files changed, 23 insertions(+), 25 deletions(-) diff --git a/developers-manual.rst b/developers-manual.rst index 42e52d36..3a5cc83c 100644 --- a/developers-manual.rst +++ b/developers-manual.rst @@ -596,22 +596,18 @@ Android Apps Android App Nightly Builds -------------------------- -There are currently three Android apps: +There are currently three Android apps in +`the official Git repository `__: * Wallet - [`Git Repo `__] - [`Git Mirror `__] - [`CI `__] + [`CI `__] * Merchant PoS Terminal - [`Git Repo `__] - [`Git Mirror `__] - [`CI `__] + [`CI `__] * Cashier - [`Git Repo `__] - [`Git Mirror `__] - [`CI `__] + [`CI `__] -Their git repositories are mirrored at Gitlab to utilize their CI +Their git repositories are `mirrored at Gitlab `__ +to utilize their CI and `F-Droid `_'s Gitlab integration to `publish automatic nightly builds `_ for each change on the ``master`` branch. @@ -638,7 +634,8 @@ Building apps from source Note that this guide is different from other guides for building Android apps, because it does not require you to run non-free software. -It uses the Merchant PoS Terminal as an example, but works as well for the other apps. +It uses the Merchant PoS Terminal as an example, but works as well for the other apps +if you replace ``merchant-terminal`` with ``wallet`` or ``cashier``. First, ensure that you have the required dependencies installed: @@ -650,20 +647,20 @@ Then you can get the app's source code using git: .. code-block:: shell - # Start by cloning the git repository - git clone https://git.taler.net/merchant-terminal-android.git + # Start by cloning the Android git repository + git clone https://git.taler.net/taler-android.git - # Change into the directory of the cloned app - cd merchant-terminal-android + # Change into the directory of the cloned repository + cd taler-android # Find out which Android SDK version you will need - grep -i compileSdkVersion app/build.gradle + grep -i compileSdkVersion merchant-terminal/build.gradle The last command will return something like ``compileSdkVersion 29``. So visit the `Android Rebuilds `_ project and look for that version of the Android SDK there. If the SDK version is not yet available as a free rebuild, -you can try to lower the ``compileSdkVersion`` in the app's ``app/build.gradle`` file. +you can try to lower the ``compileSdkVersion`` in the app's ``merchant-terminal/build.gradle`` file. Note that this might break things or require you to also lower other versions such as ``targetSdkVersion``. @@ -682,21 +679,22 @@ and unpack it: # Tell the build system where to find the SDK export ANDROID_SDK_ROOT="$HOME/android-sdk_eng.10.0.0_r14_linux-x86" - # Change into the directory of the cloned app - cd merchant-terminal-android + # Change into the directory of the cloned repository + cd taler-android - # Build the app - ./gradlew assembleRelease + # Build the merchant-terminal app + ./gradlew :merchant-terminal:assembleRelease If you get an error message complaining about build-tools > Failed to install the following Android SDK packages as some licences have not been accepted. build-tools;29.0.3 Android SDK Build-Tools 29.0.3 -you can try changing the ``buildToolsVersion`` in the app's ``app/build.gradle`` file +you can try changing the ``buildToolsVersion`` in the app's ``merchant-terminal/build.gradle`` file to the latest "Android SDK build tools" version supported by the Android Rebuilds project. -After the build finished successfully, you find your APK in ``app/build/outputs/apk/release/``. +After the build finished successfully, +you will find your APK in ``merchant-terminal/build/outputs/apk/release/``. .. _Code-coverage: diff --git a/taler-wallet.rst b/taler-wallet.rst index 8c2d7eba..9ebc1f36 100644 --- a/taler-wallet.rst +++ b/taler-wallet.rst @@ -71,7 +71,7 @@ Building from source Android Wallet ============== -*TBD.* +Please see :ref:`Build-apps-from-source` in the :doc:`developers-manual`. APIs and Data Formats -- cgit v1.2.3 From d6df3784a31df42b5d2e77ef92259b62c7a6c47b Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Wed, 29 Apr 2020 09:45:15 -0300 Subject: slight tweaks to proposed transactions wallet API --- taler-wallet.rst | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/taler-wallet.rst b/taler-wallet.rst index 9ebc1f36..f9161211 100644 --- a/taler-wallet.rst +++ b/taler-wallet.rst @@ -121,6 +121,12 @@ Transactions are all operations or events that are affecting the balance. // true if the transaction is still pending, false otherwise pending: boolean; + + // Raw amount of the transaction (exclusive of fees or other extra costs) + amountRaw: Amount; + + // Amount added or removed from the wallet's balance (including all fees and other costs) + amountEffective: Amount; } .. ts:def:: TransactionType @@ -129,7 +135,8 @@ Transactions are all operations or events that are affecting the balance. TransactionWithdrawal | TransactionPayment | TransactionRefund | - TransactionTip + TransactionTip | + TransactionRefresh ) .. ts:def:: TransactionWithdrawal @@ -165,6 +172,13 @@ Transactions are all operations or events that are affecting the balance. // Additional information about the payment. info: TransactionInfo; + // true if the payment failed, false otherwise. + // Note that failed payments with zero effective amount will not be returned by the API. + failed: boolean; + + // Amount that must be paid for the contract + amountRaw: Amount; + // Amount that was paid, including deposit, wire and refresh fees. amountEffective: Amount; } @@ -178,9 +192,6 @@ Transactions are all operations or events that are affecting the balance. // More information about the merchant merchant: Merchant; - // Amount that must be paid for the contract - amount: Amount; - // Summary of the order, given by the merchant summary: string; @@ -199,6 +210,9 @@ Transactions are all operations or events that are affecting the balance. interface TransactionRefund extends Transaction { type: string = "refund", + // ID for the transaction that is refunded + refundedTransactionId: string; + // Additional information about the refunded payment info: TransactionInfo; @@ -236,6 +250,24 @@ Transactions are all operations or events that are affecting the balance. amountEffective: Amount; } + .. ts:def:: TransactionRefresh + + // A transaction shown for refreshes that are not associated to other transactions + // such as a refresh necessary before coin expiration. + // It should only be returned by the API if the effective amount is different from zero. + interface TransactionRefresh extends Transaction { + type: string = "refresh", + + // Exchange that the coins are refreshed with + exchangeBaseUrl: string; + + // Raw amount that is refreshed + amountRaw: Amount; + + // Amount that will be paid as fees for the refresh + amountEffective: Amount; + } + Refunds ------- -- cgit v1.2.3 From 220b06cf14f44f3241590e8e1cc08d23d44885e0 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 29 Apr 2020 22:28:16 +0200 Subject: update spec --- core/api-merchant.rst | 46 +++++++++++++++++++--------------------------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index b8c9eae8..70241b09 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -417,7 +417,7 @@ management. // including all existing sales ever. Given in product-specific // units. // A value of -1 indicates "infinite" (i.e. for "electronic" books). - total_stocked: Integer; + total_stock: Integer; // Number of units of the product that have already been sold. total_sold: Integer; @@ -483,7 +483,7 @@ management. // including all existing sales ever. Given in product-specific // units. // A value of -1 indicates "infinite" (i.e. for "electronic" books). - total_stocked: Integer; + total_stock: Integer; // Identifies where the product is in stock. address: Location; @@ -498,7 +498,7 @@ management. .. http:patch:: /private/products/$PRODUCT_ID This is used to update product details in the inventory. Note that the - ``total_stocked`` and ``total_lost`` numbers MUST be greater or equal than + ``total_stock`` and ``total_lost`` numbers MUST be greater or equal than previous values (this design ensures idempotency). In case stocks were lost but not sold, increment the ``total_lost`` number. All fields in the request are optional, those that are not given are simply preserved (not @@ -548,7 +548,7 @@ management. // including all existing sales ever. Given in product-specific // units. // A value of -1 indicates "infinite" (i.e. for "electronic" books). - total_stocked: Integer; + total_stock: Integer; // Number of units of the product that were lost (spoiled, stolen, etc.) total_lost: Integer; @@ -786,7 +786,7 @@ Receiving Payments :query wired: *Optional*. If set to yes, only return wired orders, if no only orders with missing wire transfers. Do not give (or use "all") to see all orders regardless of wire transfer status. :query date: *Optional.* Time threshold, see ``delta`` for its interpretation. Defaults to the oldest or most recent entry, depending on ``delta``. :query start: *Optional*. Row number threshold, see ``delta`` for its interpretation. Defaults to ``UINT64_MAX``, namely the biggest row id possible in the database. - :query delta: *Optional*. takes value of the form ``N (-N)``, so that at most ``N`` values strictly younger (older) than ``start`` and ``date`` are returned. Defaults to ``-20``. + :query delta: *Optional*. takes value of the form ``N (-N)``, so that at most ``N`` values strictly older (younger) than ``start`` and ``date`` are returned. Defaults to ``-20`` to return the last 20 entries (before ``start`` and/or ``date``). :query timeout_ms: *Optional*. Timeout in milli-seconds to wait for additional orders if the answer would otherwise be negative (long polling). Only useful if delta is positive. Note that the merchant MAY still return a response that contains fewer than delta orders. **Response:** @@ -815,20 +815,6 @@ Receiving Payments // Transaction's timestamp timestamp: Timestamp; - // Total amount the customer should pay for this order. - total: Amount; - - // Total amount the customer did pay for this order. Payments - // that were later aborted (/abort) are NOT included. - paid: Amount; - - // Total amount the customer was refunded for this order. - // (excludes refunds from aborts). - refunded: Amount; - - // Was the order fully paid? - is_paid: boolean; - } @@ -921,7 +907,13 @@ Receiving Payments .. ts:def:: PayRequest interface PayRequest { + // The coins used to make the payment. coins: CoinPaySig[]; + + // The session for which the payment is made (or replayed). + // Only set for session-based payments. + session_id: string; + } .. ts:def:: CoinPaySig @@ -936,8 +928,8 @@ Receiving Payments // Signature made by the denomination public key. ub_sig: string; - // The denomination public key associated with this coin. - denom_pub: string; + // The hash of the denomination public key associated with this coin. + h_denom: HashCode; // The amount that is subtracted from this coin with this payment. contribution: Amount; @@ -1975,28 +1967,28 @@ The contract terms must have the following structure: description_i18n?: { [lang_tag: string]: string }; // The number of units of the product to deliver to the customer. - quantity: Integer; + quantity?: Integer; // The unit in which the product is measured (liters, kilograms, packages, etc.) - unit: string; + unit?: string; // The price of the product; this is the total price for ``quantity`` times ``unit`` of this product. - price: Amount; + price?: Amount; // An optional base64-encoded product image image?: ImageDataUrl; // a list of taxes paid by the merchant for this product. Can be empty. - taxes: Tax[]; + taxes?: Tax[]; // time indicating when this product should be delivered - delivery_date: Timestamp; + delivery_date?: Timestamp; // where to deliver this product. This may be an URL for online delivery // (i.e. 'http://example.com/download' or 'mailto:customer@example.com'), // or a location label defined inside the proposition's 'locations'. // The presence of a colon (':') indicates the use of an URL. - delivery_location: string; + delivery_location?: string; } .. ts:def:: Tax -- cgit v1.2.3 From f5609ae8922205af512d243abb235ea5176a6ca4 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Thu, 30 Apr 2020 14:50:13 -0300 Subject: Add markdown conventions to design document 003 --- design-documents/003-tos-rendering.rst | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/design-documents/003-tos-rendering.rst b/design-documents/003-tos-rendering.rst index 5f6d8157..52d293c3 100644 --- a/design-documents/003-tos-rendering.rst +++ b/design-documents/003-tos-rendering.rst @@ -42,6 +42,27 @@ document" for generating the corresponding legal agreement document in other formats. However, service providers can also provide custom versions with more appropriate styling, like a logo in the header of a printable PDF document. +Markdown Conventions +-------------------- + +The ``text/markdown`` document **should** follow +the `commonmark spec `__. +Main headlines (level 1) and their following content (until the next main headline) +will be shown as expandable sections in wallets. + +The document **must** begin with a main headline: + +.. code-block:: + + # First Headline + +or + +.. code-block:: + + First Headline + ============== + Alternatives ============ -- cgit v1.2.3 From dc8ff9b27e4db934f4f905488163390edf30f2f0 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 30 Apr 2020 21:48:40 +0200 Subject: api revisions (#5987) --- core/api-merchant.rst | 52 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 9 deletions(-) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index 70241b09..3c3f670a 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -912,7 +912,7 @@ Receiving Payments // The session for which the payment is made (or replayed). // Only set for session-based payments. - session_id: string; + session_id?: string; } @@ -920,13 +920,13 @@ Receiving Payments export interface CoinPaySig { // Signature by the coin. - coin_sig: string; + coin_sig: EddsaSignature; // Public key of the coin being spend. - coin_pub: string; + coin_pub: EddsaPublicKey; // Signature made by the denomination public key. - ub_sig: string; + ub_sig: RsaSignature; // The hash of the denomination public key associated with this coin. h_denom: HashCode; @@ -968,7 +968,8 @@ Receiving Payments The merchant's interaction with the exchange failed in some way. The error from the exchange is included. - The backend will return verbatim the error codes received from the exchange's + The backend will return an `abort response `, which includes + verbatim the error codes received from the exchange's :ref:`refund <_refund>` API. The frontend should pass the replies verbatim to the browser/wallet. @@ -980,18 +981,51 @@ Receiving Payments // wallet/customer in case $ORDER_ID is guessable). h_contract: HashCode; - // List of coins the wallet would like to see refunds for. // (Should be limited to the coins for which the original // payment succeeded, as far as the wallet knows.) - coins: AbortedCoin[]; + coins: AbortingCoin[]; } - .. ts:def:: AbortedCoin + .. ts:def:: AbortingCoin - interface AbortedCoin { + interface AbortingCoin { // Public key of a coin for which the wallet is requesting an abort-related refund. coin_pub: EddsaPublicKey; + + // The amount to be refunded (matches the original contribution) + contribution: Amount; + + // The refund fee the wallet expects to pay (based on the coin's denomination) + refund_fee: Amount; + + // URL of the exchange this coin was withdrawn from. + exchange_url: string; + } + + + .. ts:def:: AbortResponse + + interface AbortResponse { + + // List of refund responses about the coins that the wallet + // requested an abort for. In the same order as the 'coins' + // from the original request. + refunds: RefundResult[]; + } + + .. ts:def:: RefundResult + + interface RefundResult { + // HTTP status of the request to the exchange. + exchange_status: integer; + + // The full reply from the exchange. Note only actually + // a if the `exchange_status` is 200, otherwise + // the error message as defined by the refund API. For + // aborts, the `rtransaction_id` is always 0. + exchange_body: RefundSuccess; + } -- cgit v1.2.3 From 4291ccab9db213edd2ce8bb8d6a1c6af661afcda Mon Sep 17 00:00:00 2001 From: buckE Date: Fri, 1 May 2020 02:28:35 +0000 Subject: added "Internationalization" section pertaining to weblate Line 594 --- developers-manual.rst | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/developers-manual.rst b/developers-manual.rst index 3a5cc83c..c34d6c81 100644 --- a/developers-manual.rst +++ b/developers-manual.rst @@ -590,6 +590,42 @@ for that. There is also the possibility to trigger builds manually, but this is only reserved to "admin" users. + +Internationalization +==================== + +Translations and internationalization is handled with Weblate (https://weblate.org) via our instance at ``https://weblate.taler.net/``. + +At this time, this system is still very new for Taler.net and over time we intend to learn and document the following: + +Who can Register +---------------- + +At this time, anyone can register an account at ``https://weblate.taler.net/`` to create translations. + +Who can Create Projects +----------------------- + +Creating a Weblate translation project is a power reserved for superusers. At this time, Christian, Florian, and Buck have the ability to create projects. + +Who can Create Components +----------------------- + +Weblate *projects* are subdivided into *components*. At this time it is not clear what priviledges are necessary to create components. + +How to Create a Translation +--------------------------- + +More information will be forthcoming as we learn this new system. Expert users are welcome to participate and contribute to our knowledge pool. + +GPG Signing of Translations +--------------------------- + +weblate.taler.net signs GPG commits with the GPG key CD33CE35801462FA5EB0B695F2664BF474BFE502, and the corresponding public key can be found at https://weblate.taler.net/keys/. + +This means that contributions made through weblate will not be signed with the individual contributor's key when they are checked into the Git repository, but with the weblate key. + + Android Apps ============ -- cgit v1.2.3 From a0aa887e5686ad083d2fcd43886570e9a2297775 Mon Sep 17 00:00:00 2001 From: buckE Date: Fri, 1 May 2020 02:59:47 +0000 Subject: updated how to perform translation --- developers-manual.rst | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/developers-manual.rst b/developers-manual.rst index c34d6c81..39978415 100644 --- a/developers-manual.rst +++ b/developers-manual.rst @@ -601,22 +601,40 @@ At this time, this system is still very new for Taler.net and over time we inten Who can Register ---------------- -At this time, anyone can register an account at ``https://weblate.taler.net/`` to create translations. +At this time, anyone can register an account at ``https://weblate.taler.net/`` to create translations. Registered users default to the **Users** and **Viewers** privilege level. -Who can Create Projects ------------------------ +About Privilege Levels +---------------------- -Creating a Weblate translation project is a power reserved for superusers. At this time, Christian, Florian, and Buck have the ability to create projects. +This is the breakdown of privilege levels in Weblate: -Who can Create Components ------------------------ +**Users**,**Viewers** = Can log in, view Translations (*applies to new users*) +**Reviewers** = Can contribute translations to existing *Components* +**Managers** = Can create new *Components* of existing *Projects* +**Superusers** = Can create new *Projects* -Weblate *projects* are subdivided into *components*. At this time it is not clear what priviledges are necessary to create components. +Upgrading Privileges +-------------------- + +To upgrade from **Users**/**Viewers**, a superuser must manually augment your privileges. At this time, superusers are Christian, Florian, and Buck. How to Create a Translation --------------------------- -More information will be forthcoming as we learn this new system. Expert users are welcome to participate and contribute to our knowledge pool. +1 - Log into ``https://weblate.taler.net`` + +2 - Navigate to *Projects* > *Browse all projects* + +3 - Choose the *project* you wish to contribute to. + +4 - Choose the *component* you wish to contribute to. + +5 - Find the language you want to translate into. Click "Translate" on that line. + +6 - Find a phrase and translate it. + +You may also wish to refer to ``https://docs.weblate.org/``. + GPG Signing of Translations --------------------------- -- cgit v1.2.3 From 0c2646f6ceb0b4b132180dc84b08b68b2642e8e6 Mon Sep 17 00:00:00 2001 From: buckE Date: Fri, 1 May 2020 03:07:47 +0000 Subject: Internationalization updates re: formatting --- developers-manual.rst | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/developers-manual.rst b/developers-manual.rst index 39978415..57ab3094 100644 --- a/developers-manual.rst +++ b/developers-manual.rst @@ -594,9 +594,9 @@ only reserved to "admin" users. Internationalization ==================== -Translations and internationalization is handled with Weblate (https://weblate.org) via our instance at ``https://weblate.taler.net/``. +Internationalization (a.k.a "Translation") is handled with Weblate (https://weblate.org) via our instance at ``https://weblate.taler.net/``. -At this time, this system is still very new for Taler.net and over time we intend to learn and document the following: +At this time, this system is still very new for Taler.net and this documentation may be incorrect and is certainly incomplete. Who can Register ---------------- @@ -608,9 +608,12 @@ About Privilege Levels This is the breakdown of privilege levels in Weblate: -**Users**,**Viewers** = Can log in, view Translations (*applies to new users*) -**Reviewers** = Can contribute translations to existing *Components* +**Users**/**Viewers** = Can log in, view Translations (*applies to new users*) + +**Reviewers** = Can contribute Translations to existing *Components* + **Managers** = Can create new *Components* of existing *Projects* + **Superusers** = Can create new *Projects* Upgrading Privileges -- cgit v1.2.3 From 5a461236c48614faa820c1eee1b92646720f0f62 Mon Sep 17 00:00:00 2001 From: buckE Date: Fri, 1 May 2020 06:56:00 +0000 Subject: Privilege Levels formatting --- developers-manual.rst | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/developers-manual.rst b/developers-manual.rst index 57ab3094..dc8142c1 100644 --- a/developers-manual.rst +++ b/developers-manual.rst @@ -608,13 +608,13 @@ About Privilege Levels This is the breakdown of privilege levels in Weblate: -**Users**/**Viewers** = Can log in, view Translations (*applies to new users*) +* **Users**/**Viewers** = Can log in, view Translations (*applies to new users*) -**Reviewers** = Can contribute Translations to existing *Components* +* **Reviewers** = Can contribute Translations to existing *Components* -**Managers** = Can create new *Components* of existing *Projects* +* **Managers** = Can create new *Components* of existing *Projects* -**Superusers** = Can create new *Projects* +* **Superusers** = Can create new *Projects* Upgrading Privileges -------------------- @@ -638,6 +638,13 @@ How to Create a Translation You may also wish to refer to ``https://docs.weblate.org/``. +Translation Standards and Practices +----------------------------------- + +By default, our Weblate instance is set to accept translations in English, French, German, Italian, Russian, Spanish, and Portuguese. + +If you want to contribute a translation in a different language, navigate to the *Component* you want to translate for, and click "Start new translation" to begin. If you require a privilege upgrade, please contact a superuser with your request. + GPG Signing of Translations --------------------------- -- cgit v1.2.3 From 9f12faa11c8d356a90139c0ed7046223dd8cb6eb Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 1 May 2020 12:43:05 +0200 Subject: address #5987-15826, subpoints #4/#5 --- core/api-merchant.rst | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index 3c3f670a..e20b5319 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -946,7 +946,12 @@ Receiving Payments **Request:** - The request must be an `abort request `. + The request must be an `abort request `. We force the wallet + to specify the affected coins as it may only request for a subset of the coins + (i.e. because the wallet knows that some were double-spent causing the failure). + Also we need to know the coins because there may be two wallets "competing" over + the same order and one wants to abort while the other still proceeds with the + payment. Here we need to again know which subset of the deposits to abort. **Response:** @@ -962,6 +967,9 @@ Receiving Payments :status 404 Not found: The merchant backend could not find the order or the instance and thus cannot process the abort request. + :status 410 Gone: + It is too late for aborting, the exchange may have already sent wired funds + to the merchant. :status 412 Precondition Failed: Aborting the payment is not allowed, as the original payment did succeed. :status 424 Failed Dependency: @@ -996,9 +1004,6 @@ Receiving Payments // The amount to be refunded (matches the original contribution) contribution: Amount; - // The refund fee the wallet expects to pay (based on the coin's denomination) - refund_fee: Amount; - // URL of the exchange this coin was withdrawn from. exchange_url: string; } @@ -1230,6 +1235,9 @@ Giving Refunds The refund amount has been increased, the backend responds with a `MerchantRefundResponse` :status 404 Not found: The order is unknown to the merchant + :status 410 Gone: + It is too late for aborting, the exchange may have already wired the funds + to the merchant. :status 409 Conflict: The refund amount exceeds the amount originally paid -- cgit v1.2.3 From 86274e64807f70386baea68557b9b8535d5fdf24 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 1 May 2020 13:44:30 +0200 Subject: more refund documentation --- core/api-merchant.rst | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index e20b5319..2cc57ae0 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -1021,6 +1021,8 @@ Receiving Payments .. ts:def:: RefundResult + // RefundResult differs from RefundDetail as in this case we + // can generate a substantially shorter response. interface RefundResult { // HTTP status of the request to the exchange. exchange_status: integer; @@ -1185,7 +1187,7 @@ Receiving Payments // Amount that was refunded in total. refund_amount: Amount; - // Refunds for this payment, empty array for none. + // Successful refunds for this payment, empty array for none. refunds: RefundDetail[]; // URI that the wallet must process to complete the payment. @@ -1197,6 +1199,36 @@ Receiving Payments } + .. ts:def:: RefundDetail + + // Additional details needed to verify the refund confirmation signature + // (``h_contract_terms`` and ``merchant_pub``) are already known + // to the wallet and thus not included. + interface RefundDetail { + + // the EdDSA :ref:`signature` (binary-only) with purpose + // `TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND` using a current signing key of the + // exchange affirming the successful refund + exchange_sig: EddsaSignature; + + // public EdDSA key of the exchange that was used to generate the signature. + // Should match one of the exchange's signing keys from /keys. It is given + // explicitly as the client might otherwise be confused by clock skew as to + // which signing key was used. + exchange_pub: EddsaPublicKey; + + // Refund transaction ID. + rtransaction_id: Integer; + + // public key of a coin that was refunded + coin_pub: EddsaPublicKey; + + // Amount that was refunded, including refund fee charged by the exchange + // to the customer. + refund_amout: Amount; + + } + .. http:delete:: /private/orders/$ORDER_ID -- cgit v1.2.3 From 05784bf7f83566f06fc2874ddb3089c65a3f9846 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Fri, 1 May 2020 09:21:34 -0300 Subject: Add minor clarifications for end of wallet withdrawal flow --- design-documents/004-wallet-withdrawal-flow.rst | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/design-documents/004-wallet-withdrawal-flow.rst b/design-documents/004-wallet-withdrawal-flow.rst index e448a773..e82564e8 100644 --- a/design-documents/004-wallet-withdrawal-flow.rst +++ b/design-documents/004-wallet-withdrawal-flow.rst @@ -72,7 +72,7 @@ The user flow between these screens is described in the following graph: shape = rect; ]; transactions [ - label = "Transactions"; + label = "List of\nTransactions"; shape = circle; ]; @@ -102,6 +102,15 @@ before allowing them to confirm the withdrawal. Some special regional or test currencies might have only a single known exchange. For those, the wallet should not offer the option to change an exchange. +After confirming the withdrawal, +the user is brought to the list of transactions of the current currency. +It will include a pending `TransactionWithdrawal` which might require additional user confirmation +such as a two-factor-authentication step with the bank. + +If the withdrawal proceeds very quickly, +the `TransactionWithdrawal` might not show as pending +and its effective amount is added to the displayed balance right away. + Alternatives ============ -- cgit v1.2.3 From 7de324667a1e82cc5fdde856476b81b73b63cbf9 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 1 May 2020 19:21:50 +0200 Subject: document exchange protocol v8 --- core/api-exchange.rst | 11 ++++++----- core/api-merchant.rst | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/core/api-exchange.rst b/core/api-exchange.rst index 536458ec..5fe560a3 100644 --- a/core/api-exchange.rst +++ b/core/api-exchange.rst @@ -631,7 +631,7 @@ denomination. interface DepositRequest { // Amount to be deposited, can be a fraction of the // coin's total value. - f: Amount; + contribution: Amount; // The merchant's account details. This must be a JSON object whose format // must correspond to one of the supported wire transfer formats of the exchange. @@ -1354,10 +1354,6 @@ Refunds // must be larger than the refund fee. refund_amount: Amount; - // Refund fee associated with the given coin. - // must be smaller than the refund amount. - refund_fee: Amount; - // SHA-512 hash of the contact of the merchant with the customer. h_contract_terms: HashCode; @@ -1386,4 +1382,9 @@ Refunds // explicitly as the client might otherwise be confused by clock skew as to // which signing key was used. exchange_pub: EddsaPublicKey; + + // Refund fee charged by the exchange for the given coin. + // must be smaller than the refund amount. + refund_fee: Amount; + } diff --git a/core/api-merchant.rst b/core/api-merchant.rst index 2cc57ae0..7d009c8f 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -1025,13 +1025,13 @@ Receiving Payments // can generate a substantially shorter response. interface RefundResult { // HTTP status of the request to the exchange. - exchange_status: integer; + exchange_http_status: integer; // The full reply from the exchange. Note only actually // a if the `exchange_status` is 200, otherwise // the error message as defined by the refund API. For // aborts, the `rtransaction_id` is always 0. - exchange_body: RefundSuccess; + exchange_reply: RefundSuccess; } -- cgit v1.2.3 From 0c0defcf958cf42c67fe34c2c8f75c86c0a74650 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Fri, 1 May 2020 23:12:50 +0530 Subject: LibEuFin conceptual overview --- libeufin/concepts.rst | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++ libeufin/index.rst | 1 + 2 files changed, 159 insertions(+) create mode 100644 libeufin/concepts.rst diff --git a/libeufin/concepts.rst b/libeufin/concepts.rst new file mode 100644 index 00000000..0825a8c8 --- /dev/null +++ b/libeufin/concepts.rst @@ -0,0 +1,158 @@ +################### +Conceptual Overview +################### + + +What is LibEuFin +================ + +The goal of LibEuFin is to make the development and testing of +FinTech applications easier. It hides implementation details +of complex legacy banking APIs behind a simple interface. + +LibEuFin Nexus and Sandbox +-------------------------- + +LibEuFin has two main components: + +1. The LibEuFin nexus receives banking-related requests in a LibEuFin-specific + format via an HTTP API. It then translates those request into interactions + with other banking APIs, abstracting away different underlying protocol and + hiding the complexity of the legacy protocols used by some banks. + +2. The LibEuFin sandbox implements the server side of protocols + that banks speak. It also emulates a *very*, *very* simple + core banking system to manage accounts and their balance. + The main use case for the sandbox is testing LibEuFin itself, + as well as applications developed with LibEuFin. + The sandbox has a JSON API to set it up for tests (creating bank + hosts, bank accounts, fake transactions). + + +High-Level Concepts +=================== + +Nexus Users +----------- + +The concept of a *nexus user* is used to implement access control to the +operations that the nexus provides. + +A nexus user can be marked as *superuser*. All permission checks +are skipped for superusers. + +Only superusers are allowed to create/modify other users. + +Bank Accounts +------------- + +A bank account is the local representation of some bank account. +The information stored about it includes: + +* Local alias ("nickname") of the bank account +* Account identification (IBAN / BIC / account holder) +* A local mirror of the bank transaction history +* Payment requests, i.e. payments that have been locally requested, together + with their state (sent or not sent, acknowledged in bank statement or not). +* Error reports (e.g. failed payment requests, bank statement items that were not understood + by LibEuFin) +* A default bank transport (if configured) that is used by default + for operations on the account +* Other connected bank transports + +Examples: + +.. code:: none + + # Download latest transactions via the default bank transport and store them locally + curl -XPOST $AUTHEADER https://example1.libeufin.tech/bank-accounts/my-acct/collect-transactions + +Bank Transports +--------------- + +Bank transports connect the local LibEuFin bank account to the real bank. +The bank transport includes the following data: + +* Local alias ("nickname") of the bank transport +* the type of transport (EBICS, FinTS, loopback, sandbox) +* credentials to use the transport (e.g. password, EBICS subscriber keys) +* protocol configuration (hostname, port, protocol sub-version/flags) + +Bank transports provide the following actions: + +* Initial setup of the transport + +* Execute protocol-specific actions (e.g. EBICS: C53, C52, CCT, CRZ) + + * These actions to not have any effect on the LibEuFin local bank account. + To persist changes to the local bank account (transaction history, payment request status), + the bank transport must be invoked via the bank account. + +* Import bank accounts + + * Some bank transport protocols allow LibEuFin to query a list of bank + accounts that the transport has access to. This makes setup easier, + as the user doesn't have to create the local bank account manually. + +Examples: + +.. code:: none + + # Manually request the inter-day account report via the EBICS C52 order + curl -XPOST $AUTHEADER https://example1.libeufin.tech/bank-transports/my-ebics-testacct/send-c52 + + # Download available bank accounts that can be accessed through this transport, + # according to the bank server (with EBICS, does a HTD request). + curl -XPOST $AUTHEADER https://example1.libeufin.tech/bank-transports/my-ebics-testacct/query-bank-accounts + +Layers +------ + +Layers allow extra domain-specific functionality to be implemented on top of users, bank accounts +and bank transports. Layers store the following information: + +* Local name of the layer +* Layer type and options specific to the type +* associated bank accounts and bank transports that can be accessed by the layer +* internal tables used by the layer (i.e. layers are stateful) + +The only layer currently supported by LibEuFin is the "Taler Wire Gateway API" layer. +It provides a filtered view on the transaction history, a more restricted API to create payment +requests, and a mechanism to create a counter-transaction for incoming transaction that do +not conform to a certain format. + +Examples: + +.. code:: none + + # Request the Taler-specific history through the layer + curl $AUTHEADER https://example1.libeufin.tech/layers/my-taler-wire-gw/api/history/incoming + +Access Control +============== + +The goal of access control in LibEuFin is to allow the following scenarios: + +* The Nexus can be used by multiple clients for different bank accounts/transports, + and these users can't access each other's bank accounts +* For monitoring / dashboard (e.g. Taler rejected transactions, blacklists), + some users should only be able to have read-only access. + +It is currently not planned to have more fine-grained permissions, such as +spending limits or more fine-grained read/write permissions. + +Users can be normal users or superusers. Permission checks do not apply to superusers, +and only superusers can create other users. + +Each top-level object (bank account, bank transport, layer) has a list of +nexus users with write access, and a list of users with read access. + +When using a bank transport through a bank account, permission checks must +succees for both the bank account and the bank transport. + +This works differently for layers: A layer has a set of associated bank transports +and bank accounts it can access. Permissions on these associated objects +are checked when the layer is *created*. When invoking operations on the layer, +the nexus only checks if the current nexus user can access the layer and *not* the +underlying objects abstracted by the layer. + diff --git a/libeufin/index.rst b/libeufin/index.rst index 62af14b4..9dc62685 100644 --- a/libeufin/index.rst +++ b/libeufin/index.rst @@ -6,6 +6,7 @@ LibEuFin is a project providing free software tooling for European FinTech. .. toctree:: :glob: + concepts ebics architecture api-sandbox -- cgit v1.2.3 From 69261836ba7985ce6363a4b2754bb1d1f2fa3cd7 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Fri, 1 May 2020 23:20:49 +0530 Subject: user clarification --- libeufin/concepts.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libeufin/concepts.rst b/libeufin/concepts.rst index 0825a8c8..5caa645b 100644 --- a/libeufin/concepts.rst +++ b/libeufin/concepts.rst @@ -38,10 +38,11 @@ Nexus Users The concept of a *nexus user* is used to implement access control to the operations that the nexus provides. -A nexus user can be marked as *superuser*. All permission checks -are skipped for superusers. +A user has a login name and a (salted, hashed) password. (Other authentication +methods could be added in the future.) -Only superusers are allowed to create/modify other users. +A nexus user can be marked as *superuser*. All permission checks are skipped +for superusers. Only superusers are allowed to create/modify other users. Bank Accounts ------------- -- cgit v1.2.3 From 7e2ddb7094d48a41051b4ebd763b8296f6224d6a Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 1 May 2020 19:54:17 +0200 Subject: document /seed API --- core/api-exchange.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/core/api-exchange.rst b/core/api-exchange.rst index 5fe560a3..2fbdfbbf 100644 --- a/core/api-exchange.rst +++ b/core/api-exchange.rst @@ -76,6 +76,15 @@ possibly by using HTTPS. If the "Etag" is missing, the client should not cache the response and instead prompt the user again at the next opportunity. This is usually only the case if the privacy policy was not configured correctly. +.. http:get:: /seed + + Return an entropy seed. The exchange will return a high-entropy + value that will differ for every call. The response is NOT in + JSON, but simply high-entropy binary data in the HTTP body. + This API can be used by wallets to guard themselves against + running on low-entropy (bad PRNG) hardware. Naturally, the entropy + returned MUST be mixed with locally generated entropy. + .. http:get:: /keys Get a list of all denomination keys offered by the bank, -- cgit v1.2.3 From 05aa6d5ac501a62063f5b903805cdb633d14b2db Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 2 May 2020 19:43:33 +0200 Subject: finish spec part of #5987 --- core/api-merchant.rst | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index 7d009c8f..5b086f80 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -956,8 +956,11 @@ Receiving Payments **Response:** :status 200 OK: - The exchange accepted all of the coins. The body is a - a `merchant refund response `. + The merchant accepted the request, and passed it on to the exchange. The body is a + a `merchant refund response `. Note that the exchange + MAY still have encountered errors in processing. Those will then be part of + the body. Wallets MUST carefully consider errors for each of the coins as + returned by the exchange. :status 400 Bad request: Either the client request is malformed or some specific processing error happened that may be the fault of the client as detailed in the JSON body @@ -967,11 +970,13 @@ Receiving Payments :status 404 Not found: The merchant backend could not find the order or the instance and thus cannot process the abort request. - :status 410 Gone: - It is too late for aborting, the exchange may have already sent wired funds - to the merchant. + :status 408 Request Timeout: + The merchant backend took too long getting a response from the exchange. + The wallet SHOULD retry soon. :status 412 Precondition Failed: Aborting the payment is not allowed, as the original payment did succeed. + It is possible that a different wallet succeeded with the payment. This + wallet should thus try to refresh all of the coins involved in the payment. :status 424 Failed Dependency: The merchant's interaction with the exchange failed in some way. The error from the exchange is included. -- cgit v1.2.3 From 43fbfe18115fb2e55f8c742e92543789715af369 Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Sat, 2 May 2020 22:41:57 +0200 Subject: plural --- libeufin/concepts.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libeufin/concepts.rst b/libeufin/concepts.rst index 5caa645b..f5ac96b4 100644 --- a/libeufin/concepts.rst +++ b/libeufin/concepts.rst @@ -16,7 +16,7 @@ LibEuFin Nexus and Sandbox LibEuFin has two main components: 1. The LibEuFin nexus receives banking-related requests in a LibEuFin-specific - format via an HTTP API. It then translates those request into interactions + format via an HTTP API. It then translates those requests into interactions with other banking APIs, abstracting away different underlying protocol and hiding the complexity of the legacy protocols used by some banks. -- cgit v1.2.3 From 125b05aea8d181dfff5dd808b05c4de3fd236c85 Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Sat, 2 May 2020 22:50:10 +0200 Subject: plural --- libeufin/concepts.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libeufin/concepts.rst b/libeufin/concepts.rst index f5ac96b4..b35b3842 100644 --- a/libeufin/concepts.rst +++ b/libeufin/concepts.rst @@ -17,7 +17,7 @@ LibEuFin has two main components: 1. The LibEuFin nexus receives banking-related requests in a LibEuFin-specific format via an HTTP API. It then translates those requests into interactions - with other banking APIs, abstracting away different underlying protocol and + with other banking APIs, abstracting away different underlying protocols and hiding the complexity of the legacy protocols used by some banks. 2. The LibEuFin sandbox implements the server side of protocols -- cgit v1.2.3 From 398e37dc5afa79087e2db8c9ced563b72701e5a3 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 3 May 2020 17:06:42 +0200 Subject: add confirmed information --- core/api-merchant.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index 5b086f80..26c8175d 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -1126,6 +1126,10 @@ Receiving Payments // Total amount that has been wire transfered // to the merchant amount: Amount; + + // Was this transfer confirmed by the merchant via the + // POST /transfers API, or is it merely claimed by the exchange? + confirmed: boolean; } .. ts:def:: TransactionConflictProof -- cgit v1.2.3 From 3a9f06d20bab3a13e1a5634015b4cd690f5bee03 Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Mon, 4 May 2020 12:35:12 +0200 Subject: typo --- libeufin/concepts.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libeufin/concepts.rst b/libeufin/concepts.rst index b35b3842..0a5e621a 100644 --- a/libeufin/concepts.rst +++ b/libeufin/concepts.rst @@ -149,7 +149,7 @@ Each top-level object (bank account, bank transport, layer) has a list of nexus users with write access, and a list of users with read access. When using a bank transport through a bank account, permission checks must -succees for both the bank account and the bank transport. +succeed for both the bank account and the bank transport. This works differently for layers: A layer has a set of associated bank transports and bank accounts it can access. Permissions on these associated objects -- cgit v1.2.3 From 5f6334a60612c93acd6eb09bed2b7610e10586ac Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Mon, 4 May 2020 12:41:45 +0200 Subject: typo --- libeufin/concepts.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libeufin/concepts.rst b/libeufin/concepts.rst index 0a5e621a..a2c61b9b 100644 --- a/libeufin/concepts.rst +++ b/libeufin/concepts.rst @@ -85,7 +85,7 @@ Bank transports provide the following actions: * Execute protocol-specific actions (e.g. EBICS: C53, C52, CCT, CRZ) - * These actions to not have any effect on the LibEuFin local bank account. + * These actions do not have any effect on the LibEuFin local bank account. To persist changes to the local bank account (transaction history, payment request status), the bank transport must be invoked via the bank account. -- cgit v1.2.3 From 1496bf96e48eeef5dd25c601420c0f234a79d481 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Mon, 4 May 2020 14:50:05 -0300 Subject: clarify wallet transactions API sorting --- taler-wallet.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/taler-wallet.rst b/taler-wallet.rst index f9161211..379dba0c 100644 --- a/taler-wallet.rst +++ b/taler-wallet.rst @@ -102,7 +102,10 @@ Transactions are all operations or events that are affecting the balance. .. ts:def:: TransactionsResponse interface TransactionsResponse { - // a list of past and pending transactions + // a list of past and pending transactions sorted by pending, timestamp and transactionId. + // In case two events are both pending and have the same timestamp, + // they are sorted by the transactionId + // (lexically ascending and locale-independent comparison). transactions: Transaction[]; } @@ -120,6 +123,8 @@ Transactions are all operations or events that are affecting the balance. timestamp: Timestamp; // true if the transaction is still pending, false otherwise + // If a transaction is not longer pending, its timestamp will be updated, + // but its transactionId will remain unchanged pending: boolean; // Raw amount of the transaction (exclusive of fees or other extra costs) -- cgit v1.2.3 From 61116728f510487762d5adae70b656df3f620bfb Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Mon, 4 May 2020 15:02:45 -0300 Subject: Add three possible withdrawal confirmation cases to design doc 4 --- design-documents/004-wallet-withdrawal-flow.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/design-documents/004-wallet-withdrawal-flow.rst b/design-documents/004-wallet-withdrawal-flow.rst index e82564e8..b13896a6 100644 --- a/design-documents/004-wallet-withdrawal-flow.rst +++ b/design-documents/004-wallet-withdrawal-flow.rst @@ -107,6 +107,12 @@ the user is brought to the list of transactions of the current currency. It will include a pending `TransactionWithdrawal` which might require additional user confirmation such as a two-factor-authentication step with the bank. +1. The bank transfer happens immediately +2. A second factor is required which is "detached", + i.e. you have to press "confirm" on a physical Taler ATM, + or a Taler cashier has to do a final "confirm" on their device. +3. The bank provides a ``bankConfirmationUrl`` that the user needs to visit. + If the withdrawal proceeds very quickly, the `TransactionWithdrawal` might not show as pending and its effective amount is added to the displayed balance right away. -- cgit v1.2.3 From 478c5d2e631eee2b8efbf2abff7dad4e83fef69a Mon Sep 17 00:00:00 2001 From: buckE Date: Tue, 5 May 2020 04:03:25 +0000 Subject: updated Component creation info for Internationalization --- developers-manual.rst | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/developers-manual.rst b/developers-manual.rst index dc8142c1..cef2095c 100644 --- a/developers-manual.rst +++ b/developers-manual.rst @@ -621,6 +621,26 @@ Upgrading Privileges To upgrade from **Users**/**Viewers**, a superuser must manually augment your privileges. At this time, superusers are Christian, Florian, and Buck. +How to Create a Project +----------------------- + +The *GNU Taler* project is probably the correct project for most Components and Translations falling under this guide. Please contact a superuser if you need another Project created. + +How to Create a Component +------------------------- + +In Weblate, a *Component* is a subset of a *Project* and each Component contains N translations. A Component is generally associated with a Git repo. + +To create a Component, log into https://weblate.taler.net/ with your *Manager* or higher credentials and choose **+ Add* from the upper-right corner. + +What follows is a sort of Wizard. You can find detailed docs at https://docs.weblate.org/. Here are some important notes about connecting your Component to the Taler Git repository: + +* **Source code repository** - Generally `git+ssh://git@git.taler.net/`. Check with `git remote -v`. +* **Repository branch ** - Choose the correct branch to draw from and commit to. +* **Repository push URL** - This is generally `git+ssh://git@git.taler.net/` Check with `git remote -v`. +* **Repository browser** - This is the www URL of the Git repo's file browser. Example `https://git.taler.net/.git/tree/{{filename}}#L{{line}}` +* **Merge style ** - *Rebase*, in line with GNU Taler development procedures + How to Create a Translation --------------------------- @@ -628,9 +648,9 @@ How to Create a Translation 2 - Navigate to *Projects* > *Browse all projects* -3 - Choose the *project* you wish to contribute to. +3 - Choose the *Project* you wish to contribute to. -4 - Choose the *component* you wish to contribute to. +4 - Choose the *Component* you wish to contribute to. 5 - Find the language you want to translate into. Click "Translate" on that line. -- cgit v1.2.3 From 74109cd0682cd4ced092ab6a858b35b65b380317 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Tue, 5 May 2020 12:07:55 +0530 Subject: layer->facade --- libeufin/concepts.rst | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/libeufin/concepts.rst b/libeufin/concepts.rst index a2c61b9b..86797a52 100644 --- a/libeufin/concepts.rst +++ b/libeufin/concepts.rst @@ -106,18 +106,18 @@ Examples: # according to the bank server (with EBICS, does a HTD request). curl -XPOST $AUTHEADER https://example1.libeufin.tech/bank-transports/my-ebics-testacct/query-bank-accounts -Layers ------- +Facades +------- -Layers allow extra domain-specific functionality to be implemented on top of users, bank accounts -and bank transports. Layers store the following information: +Facades allow extra domain-specific functionality to be implemented on top of users, bank accounts +and bank transports. Facades store the following information: -* Local name of the layer -* Layer type and options specific to the type -* associated bank accounts and bank transports that can be accessed by the layer -* internal tables used by the layer (i.e. layers are stateful) +* Local name of the facade +* Facade type and options specific to the type +* Associated bank accounts and bank transports that can be accessed by the layer +* Internal tables used by the facade (i.e. facades are stateful) -The only layer currently supported by LibEuFin is the "Taler Wire Gateway API" layer. +The only facade currently supported by LibEuFin is the "Taler Wire Gateway API" layer. It provides a filtered view on the transaction history, a more restricted API to create payment requests, and a mechanism to create a counter-transaction for incoming transaction that do not conform to a certain format. @@ -126,8 +126,8 @@ Examples: .. code:: none - # Request the Taler-specific history through the layer - curl $AUTHEADER https://example1.libeufin.tech/layers/my-taler-wire-gw/api/history/incoming + # Request the Taler-specific history through the facade + curl $AUTHEADER https://example1.libeufin.tech/facades/my-taler-wire-gw/api/history/incoming Access Control ============== -- cgit v1.2.3 From 4b34f9a973bcb382e4dc267fa265521c54b30b44 Mon Sep 17 00:00:00 2001 From: buckE Date: Wed, 6 May 2020 04:52:15 +0000 Subject: adding to Internationalization --- developers-manual.rst | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/developers-manual.rst b/developers-manual.rst index cef2095c..ec25f794 100644 --- a/developers-manual.rst +++ b/developers-manual.rst @@ -635,12 +635,17 @@ To create a Component, log into https://weblate.taler.net/ with your *Manager* o What follows is a sort of Wizard. You can find detailed docs at https://docs.weblate.org/. Here are some important notes about connecting your Component to the Taler Git repository: +Under *https://weblate.taler.net/create/component/vcs/*: + * **Source code repository** - Generally `git+ssh://git@git.taler.net/`. Check with `git remote -v`. * **Repository branch ** - Choose the correct branch to draw from and commit to. * **Repository push URL** - This is generally `git+ssh://git@git.taler.net/` Check with `git remote -v`. -* **Repository browser** - This is the www URL of the Git repo's file browser. Example `https://git.taler.net/.git/tree/{{filename}}#L{{line}}` +* **Repository browser** - This is the www URL of the Git repo's file browser. Example `https://git.taler.net/.git/tree/{{filename}}?h={{branch}}#n{{line}}` * **Merge style ** - *Rebase*, in line with GNU Taler development procedures +* **Translation license** - *GNU General Public License v3.0 or Later* +* **Adding new translation** - Decide how to handle adding new translations + How to Create a Translation --------------------------- @@ -661,10 +666,11 @@ You may also wish to refer to ``https://docs.weblate.org/``. Translation Standards and Practices ----------------------------------- -By default, our Weblate instance is set to accept translations in English, French, German, Italian, Russian, Spanish, and Portuguese. +By default, our Weblate instance is set to accept translations in English, French, German, Italian, Russian, Spanish, and Portuguese. If you want to contribute a translation in a different language, navigate to the *Component* you want to translate for, and click "Start new translation" to begin. If you require a privilege upgrade, please contact a superuser with your request. -If you want to contribute a translation in a different language, navigate to the *Component* you want to translate for, and click "Start new translation" to begin. If you require a privilege upgrade, please contact a superuser with your request. +When asked, set the license to GPLv3 or later. +Set commit/push to manual only. GPG Signing of Translations --------------------------- -- cgit v1.2.3 From 0c0a865b6b6960455c24fbd045aa2748284ea3cc Mon Sep 17 00:00:00 2001 From: buckE Date: Wed, 6 May 2020 05:54:06 +0000 Subject: adding to Internationalization --- developers-manual.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/developers-manual.rst b/developers-manual.rst index ec25f794..ba5d69b1 100644 --- a/developers-manual.rst +++ b/developers-manual.rst @@ -629,6 +629,8 @@ The *GNU Taler* project is probably the correct project for most Components and How to Create a Component ------------------------- +Reference: https://docs.weblate.org/en/weblate-4.0.3/admin/projects.html#component-configuration + In Weblate, a *Component* is a subset of a *Project* and each Component contains N translations. A Component is generally associated with a Git repo. To create a Component, log into https://weblate.taler.net/ with your *Manager* or higher credentials and choose **+ Add* from the upper-right corner. -- cgit v1.2.3 From 8a9d85394717a9cf889f6c21811e9da3ab8370eb Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 6 May 2020 18:06:32 +0530 Subject: clarify --- libeufin/concepts.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libeufin/concepts.rst b/libeufin/concepts.rst index 86797a52..00afe9a6 100644 --- a/libeufin/concepts.rst +++ b/libeufin/concepts.rst @@ -104,7 +104,8 @@ Examples: # Download available bank accounts that can be accessed through this transport, # according to the bank server (with EBICS, does a HTD request). - curl -XPOST $AUTHEADER https://example1.libeufin.tech/bank-transports/my-ebics-testacct/query-bank-accounts + # For each of them, create a bank account resource in LibEuFin. + curl -XPOST $AUTHEADER https://example1.libeufin.tech/bank-transports/my-ebics-testacct/import-accounts Facades ------- -- cgit v1.2.3 From ab650a346997bba69ad9c45d3d86ad1fc907c8c8 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Wed, 6 May 2020 11:24:58 -0300 Subject: Add wallet-core integration test cases --- core/api-merchant.rst | 2 +- taler-merchant-api-tutorial.rst | 1 + taler-wallet.rst | 54 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index 26c8175d..34071e3b 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -938,7 +938,7 @@ Receiving Payments exchange_url: string; } - +.. _order-abort: .. http:post:: /orders/$ORDER_ID/abort Abort paying for an order and obtain a refund for coins that diff --git a/taler-merchant-api-tutorial.rst b/taler-merchant-api-tutorial.rst index 34064a04..f97f96c1 100644 --- a/taler-merchant-api-tutorial.rst +++ b/taler-merchant-api-tutorial.rst @@ -279,6 +279,7 @@ This code snipped illustrates giving a refund: .. index:: repurchase +.. _repurchase: Repurchase detection and fulfillment URLs ========================================= diff --git a/taler-wallet.rst b/taler-wallet.rst index 379dba0c..11167ea9 100644 --- a/taler-wallet.rst +++ b/taler-wallet.rst @@ -293,8 +293,11 @@ Refunds } +Integration Tests +================= + Integration Test Example -======================== +------------------------ Integration tests can be done with the low-level wallet commands. To select which coins and denominations to use, the wallet can dump the coins in an easy-to-process format (`CoinDumpJson `__). @@ -356,3 +359,52 @@ top-level command and not the subcommand: # Update exchange /keys with time travel, value in microseconds $ taler-wallet-cli --timetravel=1000000 --wallet-db=mydb.json exchanges update -f https://exchange.int.taler.net/ +Test Cases +---------- + +Things we already have tests for: + +* Can the wallet recoup coins and spend them? + [`link `__] + +Things we still need tests for: + +* Does the wallet do retries correctly when the exchange is not reachable? + Or when the merchant is not reachable? Or the bank? + This can be tested by temporarily killing those services. +* How does the wallet deal with processing the same ``taler://(pay|withdraw)`` URI twice? +* Test tipping (accepting/refusing a tip) +* Test refunds +* Test for :ref:`session-based payments ` +* Test case for auto-refunds + (scenario where the vending machine finds out that its motor is broken, + so it automatically gives a refund) +* Does the wallet report "insufficient balance" correctly + (as opposed to, say, crashing)? +* Perf tests: How does the wallet handle withdrawing a *LOT* of coins? +* Are the transaction history and pending operations reported correctly? + +Tests for things the wallet doesn't handle correctly yet: + +* What happens if the wallet double-spends a coin? + (Easy to test by copying the wallet DB before spending + and then running a spend again with the old DB). +* What happens when a reserve is changed between accepting withdrawal + and actually withdrawing coins? + (This is harder to test. Might not be possible with the current CLI. + The idea would be be to have some ``--inhibit=withdraw`` flag + that tells the wallet to not actually withdraw, + so we can change the reserve state and then resume the wallet.) +* What happens if the exchange suddenly has a completely new list of denominations on offer? +* What happens if the exchange changes its master public key? + The wallet *should* handle this gracefully + even if we have coins with that exchange, + provided that the old denominations can be recouped. + (That one is pretty difficult!) +* Does the wallet handle :ref:`payment aborts ` correctly? + +There are test cases that require us to modify the communication between the wallet and exchange. + +* What does the wallet do when the exchange/merchant announce an incompatible protocol version? +* What happens if some signature made by the exchange/merchant is garbage? +* What if the exchange reports a double-spend and the proof it gives us is invalid? -- cgit v1.2.3 From a0164bcd7c88360ccd11fecc00b4a57f61fe4d5f Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Thu, 7 May 2020 14:38:28 +0200 Subject: nexus API upgrade --- libeufin/api-nexus2.rst | 231 ++++++++++++++++++++++++++++++++++++++++++++++++ libeufin/index.rst | 2 +- 2 files changed, 232 insertions(+), 1 deletion(-) create mode 100644 libeufin/api-nexus2.rst diff --git a/libeufin/api-nexus2.rst b/libeufin/api-nexus2.rst new file mode 100644 index 00000000..0802cf07 --- /dev/null +++ b/libeufin/api-nexus2.rst @@ -0,0 +1,231 @@ +Nexus API +########### + +HTTP API +======== + +Authentication +-------------- + +**Every** request made to nexus must be authenticated +using the *HTTP basic auth* mechanism. + +Users Management +---------------- + +.. http:post:: /users + + Create a new user. Only the super-user can call this API. + + **Request:** + + The body is a `User` object. + + **Response:** + + :status 409 Conflict: Username is not available. + + **Details:** + + .. ts:def:: User + + interface User { + + // User name + username: string; + + // Shadow password + shadowPassword: string; + } + +Bank Account Management +----------------------- + +.. http:get:: /bank-accounts + + Return the list of bank accounts belonging to the requesting + user. + + **Response:** A list of `BankAccount` objects. + + .. ts:def:: BankAccount + + interface BankAccount { + // mnemonic name identifying this bank account. + account: string; + // IBAN + iban: string; + // BIC + bic: string; + // Legal subject owning the account. + holder: string; + } + +.. http:post:: /bank-accounts//prepare-payment + + Ask nexus to prepare instructions for a new payment. **The technique + to submit prepared payments at the bank is still work in progress!** + Note that ``my-acct`` is the bank account that will be **debited** + after this operation. + +.. There are (at least) two styles to specify the bank-transport +.. to use: (1) we specify it here in a field the name of the bank-transport, +.. or (2) we associate a ID to this prepared payment, and make another +.. endpoint that accepts the payment's ID and the bank-transport to +.. use for the submission. Style (2) seems more flexible. + + **Request:** + .. ts:def:: PreparedPayment + + interface PreparedPayment { + // IBAN that will receive the payment. + iban: string; + // BIC hosting the IBAN. + bic: string; + // Legal subject that will receive the payment. + name: string; + + // amount, in the format CURRENCY:XX.YY + amount: string + } + + **Response:** + + **Details:** + +.. http:post:: /bank-accounts//collect-transactions + + Ask the default transport to download the latest transactions + and store them locally. + + **Request:** + The request body is a `CollectTransactions` JSON object. + ``my-acct`` is the mnemonic identifier that any bank account + stored locally at the nexus has. Typically, it is the real + bank that assigns such identifiers to the bank accounts. + + **Details** + + .. ts:def:: CollectTransactions + + interface CollectTransactions { + // Optional field to specify the bank transport to + // use for such operation. + bankTransport: string; + // dashed date (YYYY-MM-DD) of the earliest payment + // in the result. Optional, defaults to "earliest + // possible" date. + start: string; + // dashed date (YYYY-MM-DD) of the earliest payment + // in the result. Optional, defaults to "latest + // possible" date. + end: string; + } + +.. http:post:: /collected-transactions + + Shows which transactions are stored locally at nexus. + + **Request:** + + .. ts:def:: TimeRange + + interface TimeRange { + // start date of desired payments. Optional, + // defaults to "earliest possible" date. + start: string; + // end date of desired payments. Optional, + // defaults to "latest possible" date. + end: string; + } + + **Response:** A list of `Transaction` objects. + + .. ts:def:: Transaction + + interface Transaction { + // local bank account involved in the transaction. + account: string; + + // counterpart IBAN + counterpartIban: string; + + // counterpart BIC + counterpartBic: string; + + // counterpart holder name + counterpartName: string; + + // amount, in the format [-]CURRENCY:XX.YY, + // where the minus sign as prefix indicates + // a debit for the user's bank account. + amount: string + } + +Bank Transports +--------------- + +Bank transports connect the local LibEuFin bank account +to the real bank. + +.. http:post:: /bank-transports + + Activate a new bank transport for the requesting user. + + **Request:** + Object of the type `BankTransport` + + **Response:** + + :status 409 Conflict: The ``name`` field exists already for + the requesting user. + + **Details:** + + .. ts:def:: BankTransport + + interface BankTransport { + + // Mnemonic identifier for the transport bein created. + name: string; + + // Optional field to restore a previous transport. + backup: TransportBackup; + + // Type of the transport (ebics, fints, native, ..) + type: string; + } + + + .. ts:def:: TransportBackup + + interface TransportBackup { + + // The information needed in this type depend entirely + // on which transport is being restored. + + } + +.. http:post:: /bank-transports//sendMSG. + + Perform the ``MSG`` operation offered by ``transport-name`` + **without** affecting the nexus database. + + **Response:** + + :status 404 Not Found: ``transport-name`` doesn't exist for + the requesting user. + +.. http:post:: /bank-transports//syncMSG. + + Some transports **do** have operations that aren't semantically + related to a bank account but need to be stored locally at the nexus. + One typical example is the downloading of the bank's keys vie the + EBICS transport. This API lets the user perform the ``MSG`` + operation that should result in new data being stored locally + at the nexus. + + **Response:** + + :status 404 Not Found: ``transport-name`` doesn't exist for + the requesting user. diff --git a/libeufin/index.rst b/libeufin/index.rst index 9dc62685..ea3c7aa3 100644 --- a/libeufin/index.rst +++ b/libeufin/index.rst @@ -10,5 +10,5 @@ LibEuFin is a project providing free software tooling for European FinTech. ebics architecture api-sandbox - api-nexus + api-nexus2 iso20022 -- cgit v1.2.3 From c6f4e9b3598aedff6d9cce09953f73d49dccee76 Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Thu, 7 May 2020 15:24:51 +0200 Subject: nexus Adding endpoints to submit a prepare payment at the bank and ask for their status. --- libeufin/api-nexus2.rst | 121 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 87 insertions(+), 34 deletions(-) diff --git a/libeufin/api-nexus2.rst b/libeufin/api-nexus2.rst index 0802cf07..af940dec 100644 --- a/libeufin/api-nexus2.rst +++ b/libeufin/api-nexus2.rst @@ -43,10 +43,10 @@ Bank Account Management .. http:get:: /bank-accounts - Return the list of bank accounts belonging to the requesting - user. + **Response:** - **Response:** A list of `BankAccount` objects. + A list of `BankAccount` objects + that belong to the requester. .. ts:def:: BankAccount @@ -61,50 +61,103 @@ Bank Account Management holder: string; } -.. http:post:: /bank-accounts//prepare-payment - - Ask nexus to prepare instructions for a new payment. **The technique - to submit prepared payments at the bank is still work in progress!** - Note that ``my-acct`` is the bank account that will be **debited** - after this operation. +.. http:post:: /bank-accounts//submit-payment -.. There are (at least) two styles to specify the bank-transport -.. to use: (1) we specify it here in a field the name of the bank-transport, -.. or (2) we associate a ID to this prepared payment, and make another -.. endpoint that accepts the payment's ID and the bank-transport to -.. use for the submission. Style (2) seems more flexible. + Ask nexus to submit one prepare payment at the bank. **Request:** - .. ts:def:: PreparedPayment - - interface PreparedPayment { - // IBAN that will receive the payment. - iban: string; - // BIC hosting the IBAN. - bic: string; - // Legal subject that will receive the payment. - name: string; - - // amount, in the format CURRENCY:XX.YY - amount: string + + .. ts:def:: SubmitPayment + + interface SubmitPayment { + // Unique identifier of the (previously) prepared payment + // to submit at the bank. + uuid: string; + + // Optional field to specify the bank transport to use + // for the submission. + transport: string; + } + + :status 404 Not Found: the unique identifier **or** + the bank transport could not be found in the system + + +.. http:get:: /bank-accounts//prepared-payment/$uuid + + Ask the status of payment ``$uuid``. + + **Response:** + + .. ts:def:: PaymentStatus + + interface PaymentStatus { + + // Payment unique identifier + uuid: string; + + // True for submitted payments + submitted: boolean; + + // Creditor IBAN + creditorIban: string; + + // Creditor BIC + creditorBic: string; + + // Creditor legal name + creditorName: string; + + // Amount + amount: string; + + // Date of submission (in dashed form YYYY-MM-DD) + submissionDate: string; + + // Date of preparation (in dashed form YYYY-MM-DD) + preparationDate: string; } +.. http:post:: /bank-accounts//prepare-payment + + Ask nexus to prepare instructions for a new payment. + Note that ``my-acct`` is the bank account that will be + **debited** after this operation. + + **Request:** + + .. ts:def:: PreparedPaymentRequest + + interface PreparedPayment { + // IBAN that will receive the payment. + iban: string; + // BIC hosting the IBAN. + bic: string; + // Legal subject that will receive the payment. + name: string; + + // amount, in the format CURRENCY:XX.YY + amount: string + } + **Response:** - **Details:** + .. ts:def:: PreparedPaymentResponse + + interface PreparedPaymentResponse { + + // Opaque identifier to be communicated when + // the user wants to submit the payment to the + // bank. + uuid: string; + } .. http:post:: /bank-accounts//collect-transactions Ask the default transport to download the latest transactions - and store them locally. + related to ``my-acct`` and store them locally. **Request:** - The request body is a `CollectTransactions` JSON object. - ``my-acct`` is the mnemonic identifier that any bank account - stored locally at the nexus has. Typically, it is the real - bank that assigns such identifiers to the bank accounts. - - **Details** .. ts:def:: CollectTransactions -- cgit v1.2.3 From 72918cd8aad170a5d361e4d3bb63c3773eb7a771 Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Thu, 7 May 2020 15:29:42 +0200 Subject: comment --- libeufin/api-nexus2.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libeufin/api-nexus2.rst b/libeufin/api-nexus2.rst index af940dec..1fd6a474 100644 --- a/libeufin/api-nexus2.rst +++ b/libeufin/api-nexus2.rst @@ -61,6 +61,12 @@ Bank Account Management holder: string; } +.. + WARNING: the 'my-acct' part is actually REDUNDANT, + because all the information about one prepared payment + can be restored already using the $uuid value. + The same holds for the GET-based status-reporting endpoint. + .. http:post:: /bank-accounts//submit-payment Ask nexus to submit one prepare payment at the bank. -- cgit v1.2.3 From a7e87ce60e37b7e3789b564ab83591360c819419 Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Thu, 7 May 2020 16:02:27 +0200 Subject: remove comment --- libeufin/api-nexus2.rst | 6 ------ 1 file changed, 6 deletions(-) diff --git a/libeufin/api-nexus2.rst b/libeufin/api-nexus2.rst index 1fd6a474..af940dec 100644 --- a/libeufin/api-nexus2.rst +++ b/libeufin/api-nexus2.rst @@ -61,12 +61,6 @@ Bank Account Management holder: string; } -.. - WARNING: the 'my-acct' part is actually REDUNDANT, - because all the information about one prepared payment - can be restored already using the $uuid value. - The same holds for the GET-based status-reporting endpoint. - .. http:post:: /bank-accounts//submit-payment Ask nexus to submit one prepare payment at the bank. -- cgit v1.2.3 From 92607df88f02ebd2b7f5fec8ca328cc2087dc6ef Mon Sep 17 00:00:00 2001 From: buckE Date: Fri, 8 May 2020 02:52:27 +0000 Subject: formatting of list in intl --- developers-manual.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/developers-manual.rst b/developers-manual.rst index ba5d69b1..8dd83037 100644 --- a/developers-manual.rst +++ b/developers-manual.rst @@ -640,10 +640,10 @@ What follows is a sort of Wizard. You can find detailed docs at https://docs.we Under *https://weblate.taler.net/create/component/vcs/*: * **Source code repository** - Generally `git+ssh://git@git.taler.net/`. Check with `git remote -v`. -* **Repository branch ** - Choose the correct branch to draw from and commit to. +* **Repository branch** - Choose the correct branch to draw from and commit to. * **Repository push URL** - This is generally `git+ssh://git@git.taler.net/` Check with `git remote -v`. -* **Repository browser** - This is the www URL of the Git repo's file browser. Example `https://git.taler.net/.git/tree/{{filename}}?h={{branch}}#n{{line}}` -* **Merge style ** - *Rebase*, in line with GNU Taler development procedures +* **Repository browser** - This is the www URL of the Git repo's file browser. Example `https://git.taler.net/.git/tree/{{filename}}?h={{branch}}#n{{line}}` where gets replaced but *{{filename}}* and other items in braces are actual variables in the string. +* **Merge style** - *Rebase*, in line with GNU Taler development procedures * **Translation license** - *GNU General Public License v3.0 or Later* * **Adding new translation** - Decide how to handle adding new translations -- cgit v1.2.3 From a92981f37ddca8903e4f72359a22a6ff699546dd Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Fri, 8 May 2020 14:45:43 +0530 Subject: LibEuFin: remove outdated architecture docs (superseeded by concepts doc) --- libeufin/architecture.rst | 58 ----------------------------------------------- libeufin/index.rst | 1 - 2 files changed, 59 deletions(-) delete mode 100644 libeufin/architecture.rst diff --git a/libeufin/architecture.rst b/libeufin/architecture.rst deleted file mode 100644 index e5cad890..00000000 --- a/libeufin/architecture.rst +++ /dev/null @@ -1,58 +0,0 @@ -LibEuFin Architecture -##################### - -Sandbox -======= - -* the sandbox's EBICS API emulates the behavior of a real bank's EBICS - interface - -* *(Only in the future)*: FinTS API and other FinTech APIs - -* the sandbox's management API allows an administrator to: - - * create new **bank** accounts - * create new **EBICS subscriber** accounts - - * a subscriber has (optionally?) a SystemID (for technical subscribers), - a UserID and a PartnerID - * each bank account has a list of subscribers than can access it - - * delete accounts - * ... - -* the sandbox's "miscellaneous" API provides public functionality that is not covered - directly by EBICS, such as: - - * a way to get the transactions in form of a JSON message, to check if it matches the EBICS response - - * you could call it a "reference history" - - * publicly accessible key management functionality, for example for the EBICS INI process - - * this is the "electronic version" of sending an HIA/INI letter - -* things that we do **not** want to implement right now: - - * Distributed electronic signatures. For now, it is enough for every order - to be signed just by one authorized subscriber. - -Nexus -===== - -The Nexus takes JSON requests and translates them into API calls for the -respective real bank accounts (EBICS, FinTS, ...). It also stores the bank -transaction history to enable a linearlized view on the transaction history -with unique transaction identifier, which some of the underlying banking APIs -don't provide directly. - -``libeufin-nexus-httpd`` is the binary (or wrapper around the Java invocation) -that runs the HTTP service. - - -CLI Tools -========= - -The Sandbox and Nexus are only HTTP services. The CLI tools are used to -actually access them. - diff --git a/libeufin/index.rst b/libeufin/index.rst index ea3c7aa3..e128cf04 100644 --- a/libeufin/index.rst +++ b/libeufin/index.rst @@ -8,7 +8,6 @@ LibEuFin is a project providing free software tooling for European FinTech. concepts ebics - architecture api-sandbox api-nexus2 iso20022 -- cgit v1.2.3 From af572ded501cc77a2ac89bae27a9bf7d19cc9739 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Fri, 8 May 2020 15:11:09 +0530 Subject: user API --- libeufin/api-nexus2.rst | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/libeufin/api-nexus2.rst b/libeufin/api-nexus2.rst index af940dec..3609b0e0 100644 --- a/libeufin/api-nexus2.rst +++ b/libeufin/api-nexus2.rst @@ -7,12 +7,33 @@ HTTP API Authentication -------------- -**Every** request made to nexus must be authenticated -using the *HTTP basic auth* mechanism. +Currently every request made to nexus must be authenticated using the *HTTP +basic auth* mechanism. + +Other authentication mechanisms (e.g. OpenID Connect) might +be supported in the future. Users Management ---------------- +.. http:get:: /user + + Get information about the current user (based on the authentication information + in this request). + + **Response:** + + .. ts:def:: GetUserResponse + + interface UserResponse { + + // User name + username: string; + + // Is it a superuser? + superuser: boolean; + } + .. http:post:: /users Create a new user. Only the super-user can call this API. @@ -27,15 +48,15 @@ Users Management **Details:** - .. ts:def:: User + .. ts:def:: CreateUserRequest interface User { // User name username: string; - // Shadow password - shadowPassword: string; + // Initial password + password: string; } Bank Account Management @@ -164,7 +185,7 @@ Bank Account Management interface CollectTransactions { // Optional field to specify the bank transport to // use for such operation. - bankTransport: string; + bankTransport?: string; // dashed date (YYYY-MM-DD) of the earliest payment // in the result. Optional, defaults to "earliest // possible" date. -- cgit v1.2.3 From 78ed70157eb923632a2964558a3d3e43b789b2a1 Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Fri, 8 May 2020 13:57:48 +0200 Subject: Making terminology more resource-centric. --- libeufin/api-nexus2.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libeufin/api-nexus2.rst b/libeufin/api-nexus2.rst index 3609b0e0..76265ff3 100644 --- a/libeufin/api-nexus2.rst +++ b/libeufin/api-nexus2.rst @@ -82,7 +82,7 @@ Bank Account Management holder: string; } -.. http:post:: /bank-accounts//submit-payment +.. http:post:: /bank-accounts//prepared-payments/submit Ask nexus to submit one prepare payment at the bank. @@ -104,7 +104,7 @@ Bank Account Management the bank transport could not be found in the system -.. http:get:: /bank-accounts//prepared-payment/$uuid +.. http:get:: /bank-accounts//prepared-payments/$uuid Ask the status of payment ``$uuid``. @@ -139,7 +139,7 @@ Bank Account Management preparationDate: string; } -.. http:post:: /bank-accounts//prepare-payment +.. http:post:: /bank-accounts//prepared-payments Ask nexus to prepare instructions for a new payment. Note that ``my-acct`` is the bank account that will be -- cgit v1.2.3 From cf767b60cab0dd2365b006c3d97c1f4c3fe0a569 Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Fri, 8 May 2020 15:35:52 +0200 Subject: collectED-transactions --- libeufin/api-nexus2.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libeufin/api-nexus2.rst b/libeufin/api-nexus2.rst index 76265ff3..ca86d769 100644 --- a/libeufin/api-nexus2.rst +++ b/libeufin/api-nexus2.rst @@ -173,7 +173,7 @@ Bank Account Management uuid: string; } -.. http:post:: /bank-accounts//collect-transactions +.. http:post:: /bank-accounts//collected-transactions Ask the default transport to download the latest transactions related to ``my-acct`` and store them locally. @@ -196,7 +196,7 @@ Bank Account Management end: string; } -.. http:post:: /collected-transactions +.. http:get:: /bank-accounts//collected-transactions Shows which transactions are stored locally at nexus. -- cgit v1.2.3 From 9224d72693bc53336103ed1f8294372fb8648682 Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Fri, 8 May 2020 15:41:48 +0200 Subject: query parameters --- libeufin/api-nexus2.rst | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/libeufin/api-nexus2.rst b/libeufin/api-nexus2.rst index ca86d769..2cd0b2eb 100644 --- a/libeufin/api-nexus2.rst +++ b/libeufin/api-nexus2.rst @@ -200,18 +200,13 @@ Bank Account Management Shows which transactions are stored locally at nexus. - **Request:** + **Query parameters:** - .. ts:def:: TimeRange + * **start** start (dashed YYYY-MM-DD) date of desired payments. + Optional, defaults to "earliest possible" date + * **end** end (dashed YYYY-MM-DD) date of desired payments. + Optional, defaults to "earliest possible" date - interface TimeRange { - // start date of desired payments. Optional, - // defaults to "earliest possible" date. - start: string; - // end date of desired payments. Optional, - // defaults to "latest possible" date. - end: string; - } **Response:** A list of `Transaction` objects. -- cgit v1.2.3 From 38df5382734bcf4de85c0f65e27a1b8800594ad9 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 9 May 2020 17:50:33 +0200 Subject: update/clarify spec --- core/api-exchange.rst | 8 ++--- core/api-merchant.rst | 96 +++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 89 insertions(+), 15 deletions(-) diff --git a/core/api-exchange.rst b/core/api-exchange.rst index 2fbdfbbf..ea735edc 100644 --- a/core/api-exchange.rst +++ b/core/api-exchange.rst @@ -661,10 +661,7 @@ denomination. // exchange's unblinded RSA signature of the coin ub_sig: RsaSignature; - // timestamp when the contract was finalized, must match approximately the - // current time of the exchange; if the timestamp is too far off, the - // exchange returns "400 Bad Request" with an error code of - // "TALER_EC_DEPOSIT_INVALID_TIMESTAMP". + // timestamp when the contract was finalized. timestamp: Timestamp; // indicative time by which the exchange undertakes to transfer the funds to @@ -701,6 +698,9 @@ denomination. // URL, or if the base URL has changed since the deposit. transaction_base_url?: string; + // timestamp when the deposit was received by the exchange. + exchange_timestamp: Timestamp; + // the EdDSA signature of `TALER_DepositConfirmationPS` using a current // `signing key of the exchange ` affirming the successful // deposit and that the exchange will transfer the funds after the refund diff --git a/core/api-merchant.rst b/core/api-merchant.rst index 26c8175d..f2a09442 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -1186,9 +1186,13 @@ Receiving Payments .. ts:def:: PublicPayStatusResponse - interface PublicPayStatusResponse { + type PublicPayStatusResponse = StatusPaid | StatusUnpaid + + .. ts:def:: StatusPaid + + interface StatusPaid { // Has the payment for this order (ever) been completed? - paid: boolean; + paid: true; // Was the payment refunded (even partially, via refund or abort)? refunded: boolean; @@ -1197,7 +1201,15 @@ Receiving Payments refund_amount: Amount; // Successful refunds for this payment, empty array for none. - refunds: RefundDetail[]; + refunds: RefundStatus[]; + + } + + .. ts:def:: StatusUnpaid + + interface StatusUnpaid { + // Has the payment for this order (ever) been completed? + paid: false; // URI that the wallet must process to complete the payment. taler_pay_uri: string; @@ -1208,12 +1220,47 @@ Receiving Payments } - .. ts:def:: RefundDetail + + .. ts:def:: RefundStatus + + type RefundStatus = RefundFailure | RefundConfirmation + + + .. ts:def:: RefundFailure + + // Details about why a refund failed. + interface RefundFailure { + + // HTTP status of the exchange request, must NOT be 200. + exchange_status: Integer; + + // Taler error code from the exchange reply, if available. + exchange_code?: Integer; + + // If available, HTTP reply from the exchange. + exchange_reply?: json; + + // Refund transaction ID. + rtransaction_id: Integer; + + // public key of a coin that was refunded + coin_pub: EddsaPublicKey; + + // Amount that was refunded, including refund fee charged by the exchange + // to the customer. + refund_amout: Amount; + + } + + .. ts:def:: RefundConfirmation // Additional details needed to verify the refund confirmation signature // (``h_contract_terms`` and ``merchant_pub``) are already known // to the wallet and thus not included. - interface RefundDetail { + interface RefundConfirmation { + + // HTTP status of the exchange request, 200 required for refund confirmations. + exchange_status: 200; // the EdDSA :ref:`signature` (binary-only) with purpose // `TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND` using a current signing key of the @@ -1349,6 +1396,8 @@ Tracking Wire Transfers The exchange returned an error when we asked it about the "GET /transfer" status for this wire transfer. Details of the exchange error are returned. + **Details:** + .. ts:def:: TransferInformation interface TransferInformation { @@ -1397,8 +1446,6 @@ Tracking Wire Transfers } - **Details:** - .. ts:def:: TrackTransferConflictDetails interface TrackTransferConflictDetails { @@ -1421,8 +1468,23 @@ Tracking Wire Transfers // the expected value of the coin. exchange_transfer: TrackTransferResponse; - // Proof data we have for the ``exchange_transfer`` data (signatures from exchange) - exchange_proof: TrackTransferProof; + // Public key of the exchange used to sign the response + exchange_pub: EdDSAPublicKey; + + // Signature of the exchange signing the (conflicting) response + exchange_sig: EdDSASignature; + + // Hash of the merchant's bank account the wire transfer went to + h_wire: HashCode; + + // Hash of the contract terms with the conflicting deposit. + h_contract_terms: HashCode; + + // At what time the exchange received the deposit. + deposit_timestamp: Timestamp; + + // At what time the refund possibility expired (needed to verify ``exchange_sig``). + refund_deadline: Timestamp; // Public key of the coin for which we have conflicting information. coin_pub: EddsaPublicKey; @@ -1431,9 +1493,15 @@ Tracking Wire Transfers // we have conflicting information. transaction_id: number; - // Expected value of the coin. + // Amount the exchange counted the coin for in the transfer. amount_with_fee: Amount; + // Expected value of the coin. + coin_value: Amount; + + // Expected deposit fee of the coin. + coin_fee: Amount; + // Expected deposit fee of the coin. deposit_fee: Amount; @@ -1466,12 +1534,18 @@ Tracking Wire Transfers **Request:** :query payto_uri: *Optional*. Filter for transfers to the given bank account (subject and amount MUST NOT be given in the payto URI) + :query before: *Optional*. Filter for transfers executed before the given timestamp + :query after: *Optional*. Filter for transfers executed after the given timestamp + :query limit: *Optional*. At most return the given number of results. Negative for descending in execution time, positive for ascending in execution time. + :query offset: *Optional*. Starting transfer_serial_id for an iteration. + :query verified: *Optional*. Filter transfers by verification status. + **Response:** :status 200 OK: @@ -1497,7 +1571,7 @@ Tracking Wire Transfers payto_uri: string; // base URL of the exchange that made the wire transfer - exchange: string; + exchange_url: string; // Serial number identifying the transfer in the merchant backend. // Used for filgering via ``offset``. -- cgit v1.2.3 From 4f541207d82b1b5f16b097ba6edacd5887299783 Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Fri, 8 May 2020 19:24:20 +0200 Subject: use optional type notation --- libeufin/api-nexus2.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libeufin/api-nexus2.rst b/libeufin/api-nexus2.rst index 2cd0b2eb..7d5b1f0e 100644 --- a/libeufin/api-nexus2.rst +++ b/libeufin/api-nexus2.rst @@ -95,9 +95,8 @@ Bank Account Management // to submit at the bank. uuid: string; - // Optional field to specify the bank transport to use - // for the submission. - transport: string; + // Specify the bank transport to use for the submission. + transport: string?; } :status 404 Not Found: the unique identifier **or** -- cgit v1.2.3 From 76013b87e4879d12946d566f24af4c34ae7bc65b Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Fri, 8 May 2020 23:19:35 +0200 Subject: fix optional field notation --- libeufin/api-nexus2.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libeufin/api-nexus2.rst b/libeufin/api-nexus2.rst index 7d5b1f0e..ba4d4de7 100644 --- a/libeufin/api-nexus2.rst +++ b/libeufin/api-nexus2.rst @@ -96,7 +96,7 @@ Bank Account Management uuid: string; // Specify the bank transport to use for the submission. - transport: string?; + transport?: string; } :status 404 Not Found: the unique identifier **or** @@ -148,14 +148,15 @@ Bank Account Management .. ts:def:: PreparedPaymentRequest - interface PreparedPayment { + interface PreparedPaymentRequest { // IBAN that will receive the payment. iban: string; // BIC hosting the IBAN. bic: string; // Legal subject that will receive the payment. name: string; - + // payment subject. + subject: string; // amount, in the format CURRENCY:XX.YY amount: string } -- cgit v1.2.3 From c77c686b2cd6f37a490780b633b620cace2fcc74 Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Fri, 8 May 2020 23:21:16 +0200 Subject: fix plural --- libeufin/api-nexus2.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libeufin/api-nexus2.rst b/libeufin/api-nexus2.rst index ba4d4de7..e96b6862 100644 --- a/libeufin/api-nexus2.rst +++ b/libeufin/api-nexus2.rst @@ -180,9 +180,9 @@ Bank Account Management **Request:** - .. ts:def:: CollectTransactions + .. ts:def:: CollectedTransaction - interface CollectTransactions { + interface CollectedTransaction { // Optional field to specify the bank transport to // use for such operation. bankTransport?: string; -- cgit v1.2.3 From 5f538d13b733bf45272881e818084dfe173e0c28 Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Sat, 9 May 2020 12:04:42 +0200 Subject: rename file --- libeufin/api-nexus.rst | 325 ++++++++++++++++++++++++++++++++---------------- libeufin/api-nexus2.rst | 300 -------------------------------------------- 2 files changed, 219 insertions(+), 406 deletions(-) delete mode 100644 libeufin/api-nexus2.rst diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index 745182cf..e96b6862 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -1,187 +1,300 @@ Nexus API ########### - HTTP API ======== +Authentication +-------------- + +Currently every request made to nexus must be authenticated using the *HTTP +basic auth* mechanism. + +Other authentication mechanisms (e.g. OpenID Connect) might +be supported in the future. + Users Management ---------------- -Users are the entity that access accounts. They do not necessarily correspond -to the actual legal owner of an account. Their main purpose in the nexus is -access management. +.. http:get:: /user -.. http:get:: /users + Get information about the current user (based on the authentication information + in this request). - List users. + **Response:** - **Required permission:** Administrator. + .. ts:def:: GetUserResponse + + interface UserResponse { + + // User name + username: string; + + // Is it a superuser? + superuser: boolean; + } .. http:post:: /users - Create a new user. + Create a new user. Only the super-user can call this API. + + **Request:** - **Required permission:** Administrators. + The body is a `User` object. + **Response:** + + :status 409 Conflict: Username is not available. + + **Details:** + + .. ts:def:: CreateUserRequest + + interface User { + + // User name + username: string; + + // Initial password + password: string; + } Bank Account Management ----------------------- .. http:get:: /bank-accounts + + **Response:** - List bank accouts managed by nexus. + A list of `BankAccount` objects + that belong to the requester. + .. ts:def:: BankAccount + + interface BankAccount { + // mnemonic name identifying this bank account. + account: string; + // IBAN + iban: string; + // BIC + bic: string; + // Legal subject owning the account. + holder: string; + } -.. http:post:: /bank-accounts +.. http:post:: /bank-accounts//prepared-payments/submit - List bank accouts managed by nexus. + Ask nexus to submit one prepare payment at the bank. + **Request:** -.. http:get:: /bank-accounts/{acctid}/history + .. ts:def:: SubmitPayment - :query method: Method to query the bank transaction (cached, ebics, fints, ...) + interface SubmitPayment { + // Unique identifier of the (previously) prepared payment + // to submit at the bank. + uuid: string; - Query the transaction history of an account via the specified method. + // Specify the bank transport to use for the submission. + transport?: string; + } + :status 404 Not Found: the unique identifier **or** + the bank transport could not be found in the system -.. http:get:: /bank-accounts/{acctid}/payments - List payments made with this bank account via nexus. +.. http:get:: /bank-accounts//prepared-payments/$uuid + + Ask the status of payment ``$uuid``. -.. http:post:: /bank-accounts/{acctid}/payments + **Response:** - Initiate a payment. + .. ts:def:: PaymentStatus + interface PaymentStatus { -Low-level EBICS API -------------------- + // Payment unique identifier + uuid: string; -.. http:post:: /ebics/subscribers/{id}/backup - - Ask the server to export the three keys, protected with passphrase. + // True for submitted payments + submitted: boolean; - .. ts:def:: NexusEbicsBackupRequest - - interface NexusEbicsBackupRequest { - passphrase: string; - } + // Creditor IBAN + creditorIban: string; + // Creditor BIC + creditorBic: string; - .. ts:def:: NexusEbicsBackupResponse + // Creditor legal name + creditorName: string; - interface NexusEbicsBackupResponse { - - // The three passphrase-protected private keys in the PKCS#8 format + // Amount + amount: string; - authBlob: string; // base64 - encBlob: string; // base64 - sigBlob: string; // base64 - hostID: string; - userID: string; - partnerID: string; - ebicsURL: string; - } + // Date of submission (in dashed form YYYY-MM-DD) + submissionDate: string; + // Date of preparation (in dashed form YYYY-MM-DD) + preparationDate: string; + } -.. http:post:: /ebics/subscribers/{id}/restoreBackup +.. http:post:: /bank-accounts//prepared-payments - Ask the server to restore the keys. Always creates a NEW - "{id}" account, and fails if it exists already. + Ask nexus to prepare instructions for a new payment. + Note that ``my-acct`` is the bank account that will be + **debited** after this operation. + + **Request:** + + .. ts:def:: PreparedPaymentRequest + + interface PreparedPaymentRequest { + // IBAN that will receive the payment. + iban: string; + // BIC hosting the IBAN. + bic: string; + // Legal subject that will receive the payment. + name: string; + // payment subject. + subject: string; + // amount, in the format CURRENCY:XX.YY + amount: string + } + + **Response:** + + .. ts:def:: PreparedPaymentResponse + + interface PreparedPaymentResponse { + + // Opaque identifier to be communicated when + // the user wants to submit the payment to the + // bank. + uuid: string; + } - .. ts:def:: NexusEbicsRestoreBackupRequest +.. http:post:: /bank-accounts//collected-transactions - interface NexusEbicsRestoreBackupRequest { - - // passphrase to decrypt the keys - passphrase: string; + Ask the default transport to download the latest transactions + related to ``my-acct`` and store them locally. - // The three passphrase-protected private keys in the PKCS#8 format - authBlob: string; // base64 - encBlob: string; // base64 - sigBlob: string; // base64 - hostID: string; - userID: string; - partnerID: string; - ebicsURL: string; - } + **Request:** - .. ts:def:: NexusEbicsCreateSubscriber + .. ts:def:: CollectedTransaction -.. http:post:: /ebics/subscribers + interface CollectedTransaction { + // Optional field to specify the bank transport to + // use for such operation. + bankTransport?: string; + // dashed date (YYYY-MM-DD) of the earliest payment + // in the result. Optional, defaults to "earliest + // possible" date. + start: string; + // dashed date (YYYY-MM-DD) of the earliest payment + // in the result. Optional, defaults to "latest + // possible" date. + end: string; + } - Create a new subscriber. Create keys for the subscriber that - will be used in later operations. +.. http:get:: /bank-accounts//collected-transactions - .. ts:def:: NexusEbicsCreateSubscriber + Shows which transactions are stored locally at nexus. - interface NexusEbicsCreateSubscriber { - ebicsUrl: string; - hostID: string; - partnerID: string; - userID: string; - systemID: string? - } + **Query parameters:** + * **start** start (dashed YYYY-MM-DD) date of desired payments. + Optional, defaults to "earliest possible" date + * **end** end (dashed YYYY-MM-DD) date of desired payments. + Optional, defaults to "earliest possible" date -.. http:get:: /ebics/subscribers - List EBICS subscribers managed by nexus. + **Response:** A list of `Transaction` objects. + .. ts:def:: Transaction -.. http:get:: /ebics/subscribers/{id} + interface Transaction { + // local bank account involved in the transaction. + account: string; - Get details about an EBICS subscriber. + // counterpart IBAN + counterpartIban: string; -.. http:get:: /ebics/subscriber/{id}/keyletter + // counterpart BIC + counterpartBic: string; - Get a formatted letter (mark-down) to confirm keys via ordinary mail. + // counterpart holder name + counterpartName: string; -.. http:post:: /ebics/subscriber/{id}/sendIni + // amount, in the format [-]CURRENCY:XX.YY, + // where the minus sign as prefix indicates + // a debit for the user's bank account. + amount: string + } - Send INI message to the EBICS host. +Bank Transports +--------------- -.. http:post:: /ebics/subscriber/{id}/sendHia +Bank transports connect the local LibEuFin bank account +to the real bank. - Send HIA message to the EBICS host. +.. http:post:: /bank-transports + + Activate a new bank transport for the requesting user. + + **Request:** + Object of the type `BankTransport` -.. http:get:: /ebics/subscriber/{id}/sendHtd + **Response:** - Send HTD message to the EBICS host. + :status 409 Conflict: The ``name`` field exists already for + the requesting user. -.. http:post:: /ebics/subscriber/{id}/sync + **Details:** - Synchronize with the EBICS server. Sends the HPB message - and updates the bank's keys. + .. ts:def:: BankTransport -.. http:post:: /ebics/subscriber/{id}/sendEbicsOrder + interface BankTransport { - Sends an arbitrary bank-technical EBICS order. Can be an upload - order or a download order. + // Mnemonic identifier for the transport bein created. + name: string; - .. ts:def:: NexusEbicsSendOrderRequest:: + // Optional field to restore a previous transport. + backup: TransportBackup; - interface NexusEbicsSendOrderRequest { - // Bank-technical order type, such as C54 (query transactions) - // or CCC (initiate payment) - orderType: string; + // Type of the transport (ebics, fints, native, ..) + type: string; + } - // Generic order parameters, such as a date range for querying - // an account's transaction history. - orderParams: OrderParams - // Body (XML, MT940 or whatever the bank server wants) - // of the order type, if it is an upload order - orderMessage: string; - } + .. ts:def:: TransportBackup + + interface TransportBackup { + // The information needed in this type depend entirely + // on which transport is being restored. -.. http:post:: /ebics/subscriber/{id}/ebicsOrders + } + +.. http:post:: /bank-transports//sendMSG. + + Perform the ``MSG`` operation offered by ``transport-name`` + **without** affecting the nexus database. - .. note:: + **Response:** + + :status 404 Not Found: ``transport-name`` doesn't exist for + the requesting user. + +.. http:post:: /bank-transports//syncMSG. + + Some transports **do** have operations that aren't semantically + related to a bank account but need to be stored locally at the nexus. + One typical example is the downloading of the bank's keys vie the + EBICS transport. This API lets the user perform the ``MSG`` + operation that should result in new data being stored locally + at the nexus. - This one should be implemented last and specified better! + **Response:** - Return a list of previously sent ebics messages together with their status. - This allows retrying sending a message, if there was a crash during sending - the message. + :status 404 Not Found: ``transport-name`` doesn't exist for + the requesting user. diff --git a/libeufin/api-nexus2.rst b/libeufin/api-nexus2.rst deleted file mode 100644 index e96b6862..00000000 --- a/libeufin/api-nexus2.rst +++ /dev/null @@ -1,300 +0,0 @@ -Nexus API -########### - -HTTP API -======== - -Authentication --------------- - -Currently every request made to nexus must be authenticated using the *HTTP -basic auth* mechanism. - -Other authentication mechanisms (e.g. OpenID Connect) might -be supported in the future. - -Users Management ----------------- - -.. http:get:: /user - - Get information about the current user (based on the authentication information - in this request). - - **Response:** - - .. ts:def:: GetUserResponse - - interface UserResponse { - - // User name - username: string; - - // Is it a superuser? - superuser: boolean; - } - -.. http:post:: /users - - Create a new user. Only the super-user can call this API. - - **Request:** - - The body is a `User` object. - - **Response:** - - :status 409 Conflict: Username is not available. - - **Details:** - - .. ts:def:: CreateUserRequest - - interface User { - - // User name - username: string; - - // Initial password - password: string; - } - -Bank Account Management ------------------------ - -.. http:get:: /bank-accounts - - **Response:** - - A list of `BankAccount` objects - that belong to the requester. - - .. ts:def:: BankAccount - - interface BankAccount { - // mnemonic name identifying this bank account. - account: string; - // IBAN - iban: string; - // BIC - bic: string; - // Legal subject owning the account. - holder: string; - } - -.. http:post:: /bank-accounts//prepared-payments/submit - - Ask nexus to submit one prepare payment at the bank. - - **Request:** - - .. ts:def:: SubmitPayment - - interface SubmitPayment { - // Unique identifier of the (previously) prepared payment - // to submit at the bank. - uuid: string; - - // Specify the bank transport to use for the submission. - transport?: string; - } - - :status 404 Not Found: the unique identifier **or** - the bank transport could not be found in the system - - -.. http:get:: /bank-accounts//prepared-payments/$uuid - - Ask the status of payment ``$uuid``. - - **Response:** - - .. ts:def:: PaymentStatus - - interface PaymentStatus { - - // Payment unique identifier - uuid: string; - - // True for submitted payments - submitted: boolean; - - // Creditor IBAN - creditorIban: string; - - // Creditor BIC - creditorBic: string; - - // Creditor legal name - creditorName: string; - - // Amount - amount: string; - - // Date of submission (in dashed form YYYY-MM-DD) - submissionDate: string; - - // Date of preparation (in dashed form YYYY-MM-DD) - preparationDate: string; - } - -.. http:post:: /bank-accounts//prepared-payments - - Ask nexus to prepare instructions for a new payment. - Note that ``my-acct`` is the bank account that will be - **debited** after this operation. - - **Request:** - - .. ts:def:: PreparedPaymentRequest - - interface PreparedPaymentRequest { - // IBAN that will receive the payment. - iban: string; - // BIC hosting the IBAN. - bic: string; - // Legal subject that will receive the payment. - name: string; - // payment subject. - subject: string; - // amount, in the format CURRENCY:XX.YY - amount: string - } - - **Response:** - - .. ts:def:: PreparedPaymentResponse - - interface PreparedPaymentResponse { - - // Opaque identifier to be communicated when - // the user wants to submit the payment to the - // bank. - uuid: string; - } - -.. http:post:: /bank-accounts//collected-transactions - - Ask the default transport to download the latest transactions - related to ``my-acct`` and store them locally. - - **Request:** - - .. ts:def:: CollectedTransaction - - interface CollectedTransaction { - // Optional field to specify the bank transport to - // use for such operation. - bankTransport?: string; - // dashed date (YYYY-MM-DD) of the earliest payment - // in the result. Optional, defaults to "earliest - // possible" date. - start: string; - // dashed date (YYYY-MM-DD) of the earliest payment - // in the result. Optional, defaults to "latest - // possible" date. - end: string; - } - -.. http:get:: /bank-accounts//collected-transactions - - Shows which transactions are stored locally at nexus. - - **Query parameters:** - - * **start** start (dashed YYYY-MM-DD) date of desired payments. - Optional, defaults to "earliest possible" date - * **end** end (dashed YYYY-MM-DD) date of desired payments. - Optional, defaults to "earliest possible" date - - - **Response:** A list of `Transaction` objects. - - .. ts:def:: Transaction - - interface Transaction { - // local bank account involved in the transaction. - account: string; - - // counterpart IBAN - counterpartIban: string; - - // counterpart BIC - counterpartBic: string; - - // counterpart holder name - counterpartName: string; - - // amount, in the format [-]CURRENCY:XX.YY, - // where the minus sign as prefix indicates - // a debit for the user's bank account. - amount: string - } - -Bank Transports ---------------- - -Bank transports connect the local LibEuFin bank account -to the real bank. - -.. http:post:: /bank-transports - - Activate a new bank transport for the requesting user. - - **Request:** - Object of the type `BankTransport` - - **Response:** - - :status 409 Conflict: The ``name`` field exists already for - the requesting user. - - **Details:** - - .. ts:def:: BankTransport - - interface BankTransport { - - // Mnemonic identifier for the transport bein created. - name: string; - - // Optional field to restore a previous transport. - backup: TransportBackup; - - // Type of the transport (ebics, fints, native, ..) - type: string; - } - - - .. ts:def:: TransportBackup - - interface TransportBackup { - - // The information needed in this type depend entirely - // on which transport is being restored. - - } - -.. http:post:: /bank-transports//sendMSG. - - Perform the ``MSG`` operation offered by ``transport-name`` - **without** affecting the nexus database. - - **Response:** - - :status 404 Not Found: ``transport-name`` doesn't exist for - the requesting user. - -.. http:post:: /bank-transports//syncMSG. - - Some transports **do** have operations that aren't semantically - related to a bank account but need to be stored locally at the nexus. - One typical example is the downloading of the bank's keys vie the - EBICS transport. This API lets the user perform the ``MSG`` - operation that should result in new data being stored locally - at the nexus. - - **Response:** - - :status 404 Not Found: ``transport-name`` doesn't exist for - the requesting user. -- cgit v1.2.3 From b79d14082a08ab5c8613e841baed101542988ccf Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Sat, 9 May 2020 12:06:39 +0200 Subject: add missing fields --- libeufin/api-nexus.rst | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index e96b6862..3ebc5c3b 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -228,7 +228,13 @@ Bank Account Management // amount, in the format [-]CURRENCY:XX.YY, // where the minus sign as prefix indicates // a debit for the user's bank account. - amount: string + amount: string; + + // Dashed date YYYY-MM(01-12)-DD(01-31) of the transaction. + date: string; + + // Payment subject. + subject: string; } Bank Transports -- cgit v1.2.3 From 705f17a040c85b1b615be77d167e3130b602cbc6 Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Sat, 9 May 2020 12:34:19 +0200 Subject: missing field --- libeufin/api-nexus.rst | 3 +++ libeufin/index.rst | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index 3ebc5c3b..699fdafa 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -131,6 +131,9 @@ Bank Account Management // Amount amount: string; + // Subject + subject: string; + // Date of submission (in dashed form YYYY-MM-DD) submissionDate: string; diff --git a/libeufin/index.rst b/libeufin/index.rst index e128cf04..bc00b964 100644 --- a/libeufin/index.rst +++ b/libeufin/index.rst @@ -9,5 +9,5 @@ LibEuFin is a project providing free software tooling for European FinTech. concepts ebics api-sandbox - api-nexus2 + api-nexus iso20022 -- cgit v1.2.3 From 4bb037096c73025f98d0d73a68060414429d2498 Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Sun, 10 May 2020 01:20:01 +0200 Subject: use the ? notation for optional fields --- libeufin/api-nexus.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index 699fdafa..bc3dacce 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -267,8 +267,8 @@ to the real bank. // Mnemonic identifier for the transport bein created. name: string; - // Optional field to restore a previous transport. - backup: TransportBackup; + // Restore a previous transport. + backup?: TransportBackup; // Type of the transport (ebics, fints, native, ..) type: string; -- cgit v1.2.3 From 04b2105c352a974d4559df3e3372583d1ab59686 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 10 May 2020 19:57:16 +0200 Subject: clarify filter --- core/api-merchant.rst | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index db6da6df..d1563da1 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -1529,21 +1529,28 @@ Tracking Wire Transfers .. http:get:: /private/transfers - Obtain a list of all wire transfers the backend has checked. + Obtain a list of all wire transfers the backend has checked. Note that when + filtering by timestamp (using "before" and/or "after"), we use the time + reported by the exchange and thus will ONLY return results for which we already + have a response from the exchange. This should be virtually all transfers, however + it is conceivable that for some transfer the exchange responded with a temporary + error (i.e. HTTP status 500+) and then we do not yet have an execution time to + filter by. Thus, IF timestamp filters are given, transfers for which we have no + response from the exchange yet are automatically excluded. **Request:** - :query payto_uri: *Optional*. Filter for transfers to the given bank account (subject and amount MUST NOT be given in the payto URI) + :query payto_uri: *Optional*. Filter for transfers to the given bank account (subject and amount MUST NOT be given in the payto URI) - :query before: *Optional*. Filter for transfers executed before the given timestamp + :query before: *Optional*. Filter for transfers executed before the given timestamp - :query after: *Optional*. Filter for transfers executed after the given timestamp + :query after: *Optional*. Filter for transfers executed after the given timestamp - :query limit: *Optional*. At most return the given number of results. Negative for descending in execution time, positive for ascending in execution time. + :query limit: *Optional*. At most return the given number of results. Negative for descending in execution time, positive for ascending in execution time. - :query offset: *Optional*. Starting transfer_serial_id for an iteration. + :query offset: *Optional*. Starting transfer_serial_id for an iteration. - :query verified: *Optional*. Filter transfers by verification status. + :query verified: *Optional*. Filter transfers by verification status. **Response:** -- cgit v1.2.3 From 61279319a7813d8da388760bf1d64e0e9401fd32 Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Mon, 11 May 2020 00:47:26 +0200 Subject: Define request type directly under Request section. --- libeufin/api-nexus.rst | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index bc3dacce..865b5faa 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -48,7 +48,7 @@ Users Management **Details:** - .. ts:def:: CreateUserRequest + .. ts:def:: User interface User { @@ -251,14 +251,6 @@ to the real bank. Activate a new bank transport for the requesting user. **Request:** - Object of the type `BankTransport` - - **Response:** - - :status 409 Conflict: The ``name`` field exists already for - the requesting user. - - **Details:** .. ts:def:: BankTransport @@ -284,6 +276,11 @@ to the real bank. } + **Response:** + + :status 409 Conflict: The ``name`` field exists already for + the requesting user. + .. http:post:: /bank-transports//sendMSG. Perform the ``MSG`` operation offered by ``transport-name`` -- cgit v1.2.3 From 9f8638a0799548529c7e8003d1891b1eedf13d3d Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Mon, 11 May 2020 01:03:03 +0200 Subject: Gather data for a fresh bank transport. --- libeufin/api-nexus.rst | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index 865b5faa..2d36fac6 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -256,14 +256,18 @@ to the real bank. interface BankTransport { + // Type of the transport (ebics, fints, native, ..) + type: string; + // Mnemonic identifier for the transport bein created. name: string; // Restore a previous transport. backup?: TransportBackup; - - // Type of the transport (ebics, fints, native, ..) - type: string; + + // Data to create a fresh bank transport without + // restoring any backup. + new?: TransportNew; } -- cgit v1.2.3 From 8543129d81eabc25731a4de885ee27c94a25a010 Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Mon, 11 May 2020 01:05:02 +0200 Subject: precedence between fields --- libeufin/api-nexus.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index 2d36fac6..4e259eee 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -262,7 +262,8 @@ to the real bank. // Mnemonic identifier for the transport bein created. name: string; - // Restore a previous transport. + // Restore a previous transport. Take precedence + // over the 'new' field. backup?: TransportBackup; // Data to create a fresh bank transport without -- cgit v1.2.3 From 2a698585f0e1a2450c7bbe504c2b39df00abadab Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Mon, 11 May 2020 01:09:51 +0200 Subject: remove superfluous field --- libeufin/api-nexus.rst | 3 --- 1 file changed, 3 deletions(-) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index 4e259eee..0bd35681 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -256,9 +256,6 @@ to the real bank. interface BankTransport { - // Type of the transport (ebics, fints, native, ..) - type: string; - // Mnemonic identifier for the transport bein created. name: string; -- cgit v1.2.3 From 97f1aa494582afead7cdc534fc245c6bdc2c7ead Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Tue, 12 May 2020 11:10:36 +0200 Subject: more structure to point at transports --- libeufin/api-nexus.rst | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index 0bd35681..d0658ced 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -96,7 +96,23 @@ Bank Account Management uuid: string; // Specify the bank transport to use for the submission. - transport?: string; + transport?: Transport; + } + + + .. ts:def:: Transport + + + interface Transport { + + // Transport type: 'ebics', 'local', 'fints' (forthcoming). + // It must match one of the types actually implemented by + // nexus. + type: string; + + // A mnemonic identifier given by the user to one particular + // transport instance. + name: string; } :status 404 Not Found: the unique identifier **or** -- cgit v1.2.3 From 47961a49d928223feb4ca79c4ed3baa442894c06 Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Tue, 12 May 2020 15:24:35 +0200 Subject: adapt API spec to new code --- libeufin/api-nexus.rst | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index d0658ced..caca4390 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -102,7 +102,6 @@ Bank Account Management .. ts:def:: Transport - interface Transport { // Transport type: 'ebics', 'local', 'fints' (forthcoming). @@ -299,11 +298,15 @@ to the real bank. :status 409 Conflict: The ``name`` field exists already for the requesting user. -.. http:post:: /bank-transports//sendMSG. +.. http:post:: /bank-transports/sendMSG. Perform the ``MSG`` operation offered by ``transport-name`` **without** affecting the nexus database. + **Request:** + + A `Transport` object. + **Response:** :status 404 Not Found: ``transport-name`` doesn't exist for -- cgit v1.2.3 From 05cb8fc7935cb409d4776eb78f21452a86e66693 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Tue, 12 May 2020 11:26:19 -0300 Subject: Small tweaks of transactions API --- taler-wallet.rst | 52 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/taler-wallet.rst b/taler-wallet.rst index 11167ea9..beae2068 100644 --- a/taler-wallet.rst +++ b/taler-wallet.rst @@ -92,8 +92,8 @@ Transactions are all operations or events that are affecting the balance. .. ts:def:: TransactionsRequest interface TransactionsRequest { - // return only transactions in the given currency - currency: string; + // return only transactions in the given currency, if present + currency?: string; // if present, results will be limited to transactions related to the given search string search?: string; @@ -177,9 +177,8 @@ Transactions are all operations or events that are affecting the balance. // Additional information about the payment. info: TransactionInfo; - // true if the payment failed, false otherwise. - // Note that failed payments with zero effective amount will not be returned by the API. - failed: boolean; + // The current status of this payment. + status: PaymentStatus; // Amount that must be paid for the contract amountRaw: Amount; @@ -210,6 +209,26 @@ Transactions are all operations or events that are affecting the balance. fulfillmentUrl: string; } + .. ts:def:: PaymentStatus + + enum PaymentStatus { + // Explicitly aborted after timeout / failure + Aborted = "aborted", + + // Payment failed, wallet will auto-retry. + // User should be given the option to retry now / abort. + Failed = "failed", + + // Paid successfully + Paid = "paid", + + // Only offered, user must accept / decline + Offered = "offered", + + // User accepted, payment is processing. + Accepted = "accepted", + } + .. ts:def:: TransactionRefund interface TransactionRefund extends Transaction { @@ -236,11 +255,8 @@ Transactions are all operations or events that are affecting the balance. interface TransactionTip extends Transaction { type: string = "tip", - // true if the user still needs to accept/decline this tip - waiting: boolean; - - // true if the user has accepted this top, false otherwise - accepted: boolean; + // The current status of this tip. + status: TipStatus; // Exchange that the tip will be (or was) withdrawn from exchangeBaseUrl: string; @@ -255,6 +271,22 @@ Transactions are all operations or events that are affecting the balance. amountEffective: Amount; } + .. ts:def:: TipStatus + + enum TipStatus { + // Only offered, user must accept / decline + Offered = "offered", + + // User accepted, tip is processing. + Accepted = "accepted", + + // User declined. + Declined = "declined", + + // Received successfully + Received = "received", + } + .. ts:def:: TransactionRefresh // A transaction shown for refreshes that are not associated to other transactions -- cgit v1.2.3 From d8a5bb40882aaa067a5caf49a8428374349d530b Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Tue, 12 May 2020 19:09:09 +0200 Subject: more on the overloaded types --- libeufin/api-nexus.rst | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index caca4390..4acd31db 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -271,8 +271,7 @@ to the real bank. interface BankTransport { - // Mnemonic identifier for the transport bein created. - name: string; + transport: Transport; // Restore a previous transport. Take precedence // over the 'new' field. @@ -284,6 +283,22 @@ to the real bank. } + .. ts:def:: TransportNew + + interface TransportNew { + + // This type is strictly dependent on + // the transport being created. For Ebics, + // it will contain the required fields (as strings): + // 'ebicsURL', 'userID', 'partnerID', 'hostID', and + // the optional 'systemID'. + + // Other transport types, like 'local' (used for testing + // purposes skipping any interaction with the bank service) + // and 'fints' are all work in progress! + + } + .. ts:def:: TransportBackup interface TransportBackup { -- cgit v1.2.3 From 8ae2e5b610aab1a97cd695212bcd1083cb5635a5 Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Tue, 12 May 2020 19:15:26 +0200 Subject: make type clickable --- libeufin/api-nexus.rst | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index 4acd31db..e2f97f35 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -279,7 +279,7 @@ to the real bank. // Data to create a fresh bank transport without // restoring any backup. - new?: TransportNew; + newTransport?: TransportNew; } @@ -287,24 +287,25 @@ to the real bank. interface TransportNew { - // This type is strictly dependent on - // the transport being created. For Ebics, - // it will contain the required fields (as strings): - // 'ebicsURL', 'userID', 'partnerID', 'hostID', and - // the optional 'systemID'. - - // Other transport types, like 'local' (used for testing - // purposes skipping any interaction with the bank service) - // and 'fints' are all work in progress! + // This type is strictly dependent on + // the transport being created. For Ebics, + // it will contain the required fields (as strings): + // 'ebicsURL', 'userID', 'partnerID', 'hostID', and + // the optional 'systemID'. + + // Other transport types, like 'local' (used for testing + // purposes skipping any interaction with the bank service) + // and 'fints' are all work in progress! } + .. ts:def:: TransportBackup interface TransportBackup { - // The information needed in this type depend entirely - // on which transport is being restored. + // The information needed in this type depend entirely + // on which transport is being restored. } -- cgit v1.2.3 From 58dffa046cc531114a031d2cfcc833f987285155 Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Tue, 12 May 2020 19:18:38 +0200 Subject: shorter field name --- libeufin/api-nexus.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index e2f97f35..d7651fbe 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -279,7 +279,7 @@ to the real bank. // Data to create a fresh bank transport without // restoring any backup. - newTransport?: TransportNew; + data?: TransportNew; } -- cgit v1.2.3 From 84aaedffc6ab612595e724103a1b7b3311b23417 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Wed, 13 May 2020 10:18:31 -0300 Subject: Add TransactionError to transaction API --- taler-wallet.rst | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/taler-wallet.rst b/taler-wallet.rst index beae2068..e7351fd8 100644 --- a/taler-wallet.rst +++ b/taler-wallet.rst @@ -127,6 +127,9 @@ Transactions are all operations or events that are affecting the balance. // but its transactionId will remain unchanged pending: boolean; + // if present, the transaction encountered a fatal error that needs to be shown to the user + error?: TransactionError; + // Raw amount of the transaction (exclusive of fees or other extra costs) amountRaw: Amount; @@ -144,6 +147,20 @@ Transactions are all operations or events that are affecting the balance. TransactionRefresh ) + .. ts:def:: TransactionError + + interface TransactionError { + // TALER_EC_* unique error code. + // The action(s) offered and message displayed on the transaction item depend on this code. + ec: number; + + // English-only error hint, if available. + hint?: string; + + // Error details specific to "ec", if applicable/available + details?: any; + } + .. ts:def:: TransactionWithdrawal // This should only be used for actual withdrawals -- cgit v1.2.3 From c8db85cc9900c42a84ad0d09456f2e6e9931c672 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 13 May 2020 20:38:59 +0530 Subject: EBICS bank transport doc --- libeufin/bank-transport-ebics.rst | 48 +++++++++++++++++++++++++++++++++++++++ libeufin/index.rst | 7 ++++++ 2 files changed, 55 insertions(+) create mode 100644 libeufin/bank-transport-ebics.rst diff --git a/libeufin/bank-transport-ebics.rst b/libeufin/bank-transport-ebics.rst new file mode 100644 index 00000000..1363fa3e --- /dev/null +++ b/libeufin/bank-transport-ebics.rst @@ -0,0 +1,48 @@ +The EBICS Bank Transport +======================== + +An EBICS bank transport in LibEuFin conceptually corresponds +to the "EBICS Subscriber" in EBICS terminology. + + +Bank Transport Setup +-------------------- + +The following steps are required to set up an EBICS bank transport: + +1. The bank must set up the EBICS access for the user. + The bank will notify the user of the following parameters: + + * the URL of the EBICS server used by the bank + * the HostID of the bank within the EBICS server (sometimes one EBICS server hosts multiple banks) + * the PartnerID (typically identifies the owner of the bank account within the banking system) + * the UserID (typically identifies the person that accesses the bank account, can be different from the owner) + * the SystemID (optional and rarely used, basically a "sub-identity" of a subscriber when multiple technical + systems have access to the account via EBICS) + +2. The user enters the information from the list above in the setup dialog in the LibEuFin nexus (UI/CLI). +3. The LibEuFin nexus generates cryptographic key material (3 RSA key pairs) +5. The nexus sends the public keys electronically to the bank's EBICS server, together with the information + identifying the subscriber (PartnerID, UserID, SystemID). +6. The user print a document that contains the public key and hashes for all three key pairs. + The user then signs this document sends it to the bank (physically/scanned). +7. The bank receives the letter and verifies that the keys from the letter correspond + to the electronically sent keys. If they match, the bank sets the state of the + subscriber to "ready". +8. The user now has to wait until the bank has set the EBICS subscriber state to "ready". + There is no in-band notification for this, but the Nexus can try downloading the bank's + cryptographic parameters. This will only succeed once the EBICS subscriber is set to "ready" + by the bank. +9. The user should confirm the public keys of the bank received in the previous step. + Typically the bank gives the value of these public keys in an out-of-band channel. +10. Now the user can finally use the EBICS bank transport. The first step after finishing + the setup should be to import the bank accounts accessible for this EBICS subscriber. + + +Alternative ways of setting up the EBICS bank transport are: + +* Importing from a backup. The backup contains metadata (EBICS URL, HostID, + UserId, ...) and the three passphrase-protected subscriber keys. +* Certificate-based setup (currently not supported by LibEuFin, only used in France) + + diff --git a/libeufin/index.rst b/libeufin/index.rst index bc00b964..f8d3a985 100644 --- a/libeufin/index.rst +++ b/libeufin/index.rst @@ -7,7 +7,14 @@ LibEuFin is a project providing free software tooling for European FinTech. :glob: concepts +<<<<<<< Updated upstream ebics api-sandbox api-nexus +======= + bank-transport-ebics + api-nexus2 + api-sandbox + ebics +>>>>>>> Stashed changes iso20022 -- cgit v1.2.3 From c6e6ea0d7e0253e7e395465db188c3c315399cb2 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 13 May 2020 20:44:02 +0530 Subject: resolve merge, oops --- libeufin/index.rst | 6 ------ 1 file changed, 6 deletions(-) diff --git a/libeufin/index.rst b/libeufin/index.rst index f8d3a985..35dc7814 100644 --- a/libeufin/index.rst +++ b/libeufin/index.rst @@ -7,14 +7,8 @@ LibEuFin is a project providing free software tooling for European FinTech. :glob: concepts -<<<<<<< Updated upstream - ebics - api-sandbox - api-nexus -======= bank-transport-ebics api-nexus2 api-sandbox ebics ->>>>>>> Stashed changes iso20022 -- cgit v1.2.3 From 4830df09a3b00355db5c91c1c9dcebf9fec41f90 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 13 May 2020 20:50:22 +0530 Subject: fix markup --- libeufin/bank-transport-ebics.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libeufin/bank-transport-ebics.rst b/libeufin/bank-transport-ebics.rst index 1363fa3e..0d06f83b 100644 --- a/libeufin/bank-transport-ebics.rst +++ b/libeufin/bank-transport-ebics.rst @@ -21,20 +21,27 @@ The following steps are required to set up an EBICS bank transport: systems have access to the account via EBICS) 2. The user enters the information from the list above in the setup dialog in the LibEuFin nexus (UI/CLI). + 3. The LibEuFin nexus generates cryptographic key material (3 RSA key pairs) + 5. The nexus sends the public keys electronically to the bank's EBICS server, together with the information identifying the subscriber (PartnerID, UserID, SystemID). + 6. The user print a document that contains the public key and hashes for all three key pairs. The user then signs this document sends it to the bank (physically/scanned). + 7. The bank receives the letter and verifies that the keys from the letter correspond to the electronically sent keys. If they match, the bank sets the state of the subscriber to "ready". + 8. The user now has to wait until the bank has set the EBICS subscriber state to "ready". There is no in-band notification for this, but the Nexus can try downloading the bank's cryptographic parameters. This will only succeed once the EBICS subscriber is set to "ready" by the bank. + 9. The user should confirm the public keys of the bank received in the previous step. Typically the bank gives the value of these public keys in an out-of-band channel. + 10. Now the user can finally use the EBICS bank transport. The first step after finishing the setup should be to import the bank accounts accessible for this EBICS subscriber. -- cgit v1.2.3 From 780ccf432fd46ed0a38f6ce79543f611343490a5 Mon Sep 17 00:00:00 2001 From: Dennis Neufeld Date: Thu, 14 May 2020 10:41:33 +0000 Subject: modified db schema --- anastasis-db.png | Bin 51727 -> 52516 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/anastasis-db.png b/anastasis-db.png index 3681fa4e..4a2fc5c1 100644 Binary files a/anastasis-db.png and b/anastasis-db.png differ -- cgit v1.2.3 From eb48a3d22cd50764d771ec23c8b3927fae633cfc Mon Sep 17 00:00:00 2001 From: MS Date: Thu, 14 May 2020 19:27:25 +0200 Subject: adapt docs to code --- libeufin/api-nexus.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index d7651fbe..0c2d6536 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -203,7 +203,7 @@ Bank Account Management interface CollectedTransaction { // Optional field to specify the bank transport to // use for such operation. - bankTransport?: string; + bankTransport?: Transport; // dashed date (YYYY-MM-DD) of the earliest payment // in the result. Optional, defaults to "earliest // possible" date. -- cgit v1.2.3 From 00c3426e88f315f796ce2592c90991fc7307b067 Mon Sep 17 00:00:00 2001 From: MS Date: Thu, 14 May 2020 19:29:27 +0200 Subject: remove unused value from spec --- libeufin/api-nexus.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index 0c2d6536..d2d65486 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -191,10 +191,9 @@ Bank Account Management uuid: string; } -.. http:post:: /bank-accounts//collected-transactions +.. http:post:: /bank-accounts/collected-transactions - Ask the default transport to download the latest transactions - related to ``my-acct`` and store them locally. + Nexus will download bank transactions from the given transport. **Request:** -- cgit v1.2.3 From fda16ec44a8f422b2556082e4882f8e941881cee Mon Sep 17 00:00:00 2001 From: MS Date: Thu, 14 May 2020 20:48:10 +0200 Subject: adapt docs to code --- libeufin/api-nexus.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index d2d65486..681811aa 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -82,7 +82,7 @@ Bank Account Management holder: string; } -.. http:post:: /bank-accounts//prepared-payments/submit +.. http:post:: /bank-accounts/prepared-payments/submit Ask nexus to submit one prepare payment at the bank. -- cgit v1.2.3 From 7b26800e473211ca8e8682b60f3f38e2a70e6e60 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Thu, 14 May 2020 16:28:44 -0300 Subject: Add proposal for wallet balances API --- taler-wallet.rst | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/taler-wallet.rst b/taler-wallet.rst index e7351fd8..1c27d827 100644 --- a/taler-wallet.rst +++ b/taler-wallet.rst @@ -81,12 +81,51 @@ APIs and Data Formats These APIs are still a work in progress and *not* final. +Balances +-------- + +Balances are the amounts of digital cash held by the wallet. + +:name: ``"getBalances"`` +:description: Get a list of balances per currency. +:response: + .. ts:def:: BalancesResponse + + interface BalancesResponse { + // a list of balances sorted by currency. + // (currencies with shorter names first, then lexically ascending). + balances: Balance[]; + } + + .. ts:def:: Balance + + interface Balance { + currency?: string; + + // the total Amount that is currently available to be spent + available: Amount; + + // the total incoming amount that will be added to the available balance + // when all pending transactions succeed + pendingIncoming: Amount; + + // the total outgoing amount that will be subtracted from the available balance + // when all pending transactions succeed + pendingOutgoing: Amount; + + // true if the balance has pending transactions + hasPendingTransactions: boolean; + + // true if the balance requires user-interaction, e.g. accepting a tip + requiresUserInput: boolean; + } + Transactions ------------ Transactions are all operations or events that are affecting the balance. -:name: ``"transactions"`` +:name: ``"getTransactions"`` :description: Get a list of past and pending transactions. :request: .. ts:def:: TransactionsRequest -- cgit v1.2.3 From 1bb63b8e3b56c9a036ae6a1988c289505f21675d Mon Sep 17 00:00:00 2001 From: MS Date: Thu, 14 May 2020 21:51:57 +0200 Subject: include document --- libeufin/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libeufin/index.rst b/libeufin/index.rst index 35dc7814..49d44ded 100644 --- a/libeufin/index.rst +++ b/libeufin/index.rst @@ -8,7 +8,7 @@ LibEuFin is a project providing free software tooling for European FinTech. concepts bank-transport-ebics - api-nexus2 + api-nexus api-sandbox ebics iso20022 -- cgit v1.2.3 From 5b063910962c6cc971f2d76a8add56ef11f79dcf Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 15 May 2020 12:17:28 +0200 Subject: build developers manual --- conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf.py b/conf.py index a1a653af..c4415c9e 100644 --- a/conf.py +++ b/conf.py @@ -336,7 +336,7 @@ texinfo_documents = [ "DESCRIPTION", "CATEGORY"), ("taler-bank-manual", "taler-bank", "Taler Bank Manual", "GNU Taler team", "MENU ENTRY", "DESCRIPTION", "CATEGORY"), - ("onboarding", "onboarding", "Taler Onboarding Manual", "GNU Taler team", + ("developers-manual", "developers-manual", "Taler Developer Onboarding Manual", "GNU Taler team", "MENU ENTRY", "DESCRIPTION", "CATEGORY"), ] -- cgit v1.2.3 From 367a3c9f53d673fdacd3c978245292b13375adf6 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 15 May 2020 13:28:37 +0200 Subject: dev --- conf.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/conf.py b/conf.py index c4415c9e..9fd6009b 100644 --- a/conf.py +++ b/conf.py @@ -229,6 +229,8 @@ latex_elements = { # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ + ('taler-auditor-manual', 'taler-auditor-manual.tex', + 'GNU Taler Auditor Manual', 'GNU Taler team', 'manual'), ('taler-exchange-manual', 'taler-exchange-manual.tex', 'GNU Taler Exchange Manual', 'GNU Taler team', 'manual'), ('taler-merchant-manual', 'taler-merchant-manual.tex', @@ -239,7 +241,7 @@ latex_documents = [ 'GNU Taler team', 'manual'), ('taler-backoffice-manual', 'taler-backoffice-manual.tex', 'GNU Taler Back Office Manual', 'GNU Taler team', 'manual'), - ('onboarding', 'onboarding.tex', 'GNU Taler Developer Onboarding Manual', + ('developers-manual', 'developers-manual.tex', 'GNU Taler Developer Onboarding Manual', 'GNU Taler team', 'manual'), ] @@ -327,6 +329,8 @@ man_pages = [ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ + ("taler-auditor-manual", "taler-auditor", "Taler Auditor Manual", + "GNU Taler team", "MENU ENTRY", "DESCRIPTION", "CATEGORY"), ("taler-exchange-manual", "taler-exchange", "Taler Exchange Manual", "GNU Taler team", "MENU ENTRY", "DESCRIPTION", "CATEGORY"), ("taler-merchant-manual", "taler-merchant", "Taler Merchant Manual", -- cgit v1.2.3 From 0f050670c8f0f6a4e4afc74c4f966f455dbdebc6 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Fri, 15 May 2020 09:36:47 -0300 Subject: Clarify hiding internal refreshes from user-facing balance --- taler-wallet.rst | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/taler-wallet.rst b/taler-wallet.rst index 1c27d827..7d0e98a6 100644 --- a/taler-wallet.rst +++ b/taler-wallet.rst @@ -102,21 +102,25 @@ Balances are the amounts of digital cash held by the wallet. interface Balance { currency?: string; - // the total Amount that is currently available to be spent + // The total Amount that is currently available to be spent + // excluding amounts tied up in ongoing refresh operations. These are hidden from the user. + // If the user tries to spend coins locked up this way, + // the wallet will give an error message different from "insufficient balance". available: Amount; // the total incoming amount that will be added to the available balance - // when all pending transactions succeed + // when all pending transactions succeed (excluding internal refreshes) pendingIncoming: Amount; // the total outgoing amount that will be subtracted from the available balance - // when all pending transactions succeed + // when all pending transactions succeed (excluding internal refreshes) pendingOutgoing: Amount; // true if the balance has pending transactions hasPendingTransactions: boolean; // true if the balance requires user-interaction, e.g. accepting a tip + // (DEV: can be left out of a first implementation) requiresUserInput: boolean; } -- cgit v1.2.3 From 66a657b3220b1dbf0d0718d7f2c908755448f935 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Fri, 15 May 2020 09:39:48 -0300 Subject: Clarify when to show zero balance currencies in new balance API --- taler-wallet.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/taler-wallet.rst b/taler-wallet.rst index 7d0e98a6..82296e5f 100644 --- a/taler-wallet.rst +++ b/taler-wallet.rst @@ -94,6 +94,9 @@ Balances are the amounts of digital cash held by the wallet. interface BalancesResponse { // a list of balances sorted by currency. // (currencies with shorter names first, then lexically ascending). + // + // Note: Even when a currency has no balance, but pending or past transactions, + // it should be included in this list with a balance of zero. balances: Balance[]; } -- cgit v1.2.3 From b4e641db6d18897018f198834e731574b2770084 Mon Sep 17 00:00:00 2001 From: MS Date: Mon, 18 May 2020 10:56:59 +0200 Subject: update API --- libeufin/api-sandbox.rst | 196 +++++++---------------------------------------- 1 file changed, 28 insertions(+), 168 deletions(-) diff --git a/libeufin/api-sandbox.rst b/libeufin/api-sandbox.rst index ee298d85..015b8d59 100644 --- a/libeufin/api-sandbox.rst +++ b/libeufin/api-sandbox.rst @@ -1,189 +1,49 @@ + Sandbox API ########### -Entities -======== - -Bank Account - ... - -EBICS Host - -EBICS Subscriber - ... - -EBICS Partner - ... - - - HTTP API ======== +.. + Payments. -.. http:post:: /ebicsweb +.. http:post:: /admin/payments + + Adds a new payment to the book. - Submit an EBICS request to the sandbox. +.. + Host management. +.. http:post:: /admin/ebics/hosts + + Creates a new Ebics host. -.. http:post:: /admin/customers +.. http:get:: /admin/ebics/hosts + + Shows the list of all the hosts existing + in the system. - Create a new customer. A customer identifies a human that - may own multiple bank accounts. +.. + Subscriber management. - When creating a customer, one EBICS subscriber is automatically - created for the customer. +.. http:post:: /admin/ebics/subscribers - In the future, we might add an API to create multiple additional subscribers for - a customer. + Creates a new subscriber. - When creating a new customer, an ID will be assigned automatically. +.. http:get:: /admin/ebics/subscribers - .. code-block:: tsref + Shows the list of all the subscribers existing + in the system. - interface CustomerCreationRequest { - // human-readable name for the customer - name: string; - } +.. http:post:: /admin/ebics/bank-accounts -.. http:get:: /admin/customers/:id + Associates a new bank account to an existing subscriber. - Get information about a customer. +.. + Main EBICS service. - .. ts:def:: CustomerInfo +.. http:post:: /ebicsweb - interface CustomerInfo { - ebicsInfo?: CustomerEbicsInfo; - finTsInfo?: CustomerFinTsInfo; - } - - .. ts:def:: CustomerEbicsInfo - - interface CustomerEbicsInfo { - ebicsHostId: string; - ebicsParterId: string; - ebicsUserId: string; - - // Info for the customer's "main subscriber" - subscriberInitializationState: "NEW" | "PARTIALLY_INITIALIZED_INI" | "PARTIALLY_INITIALIZED_HIA" | "READY" | "INITIALIZED"; - } - - .. ts:def:: CustomerFinTsInfo - - // TODO - -.. http:post:: /admin/customers/:id/ebics/keyletter - - Accept the information from the customer's ("virtual") INI-Letter and HIA-Letter - and change the key's state as required. - - .. code-block:: tsref - - interface KeyLetterRequest { - - ini: { - // The user ID that participates in a EBICS subscriber. - userId: string; - - // The customer ID specific to the bank (therefore not - // participating in a EBICS subscriber). - customerId: string; - - // Human name of the user - name: string; - - // As per specification, this value is: - // "Date of processing of the corresponding EBICS order". DD.MM.YYYY format. - date: string; - - // As per specification, this value is: - // "Time of processing of the corresponding EBICS order". HH:MM:SS format. - time: string; - - // Identification token of the bank. Not required to obey to any particular standard. - recipient: string; - - // Electronic signature version. Admitted values: A005, A006. - version: string; - - // Length in bits of the key exponent. - public_exponent_length: number; - // RSA key exponent in hexadecimaml notation. - public_exponent: string; - - // Length in bits of the key modulus. - public_modulus_length: number; - // RSA key modulus in hexadecimaml notation. - public_modulus: string; - - // RSA key hash. - // - // A005, A005 versions require hash type SHA-256. - hash: string; - } - - hia: { - // The user ID that participates in a EBICS subscriber. - userId: string; - - // The customer ID specific to the bank (therefore not - // participating in a EBICS subscriber). - customerId: string; - - // Human name of the user - name: string; - - // As per specification, this value is: - // "Date of processing of the corresponding EBICS order". DD.MM.YYYY format. - date: string; - - // As per specification, this value is: - // "Time of processing of the corresponding EBICS order". HH:MM:SS format. - time: string; - - // Identification token of the bank. Not required to obey to any particular standard. - recipient: string; - - //////////////////////////////////////////////////// - // Identification and Authentication key details. // - //////////////////////////////////////////////////// - - // Identification and authentication signature version. - // Admitted value: X002. - ia_version: string; - - // length of the exponent, in bits. - ia_public_exponent_length: number; - // RSA key exponent in hexadecimaml notation. - ia_public_exponent: string; - - // length of the modulus, in bits. - ia_public_modulus_length: number; - // RSA key modulus in hexadecimaml notation. - ia_public_modulus: string; - - // SHA-256 hash of the identification and authentication key. - ia_hash: string; - - ///////////////////////////// - // Encryption key details. // - ///////////////////////////// - - // Encryption version. Admitted value: E002. - enc_version: string; - - // length of the exponent, in bits. - enc_public_exponent_length: number; - // RSA key exponent in hexadecimaml notation. - enc_public_exponent: string; - - // length of the modulus, in bits. - enc_public_modulus_length: number; - // RSA key modulus in hexadecimaml notation. - enc_public_modulus: string; - - // SHA-256 hash of the encryption key. - enc_hash: string; - } - } + Serves all the Ebics requests. -- cgit v1.2.3 From 07b15dd14a52805b8c7c6f2621182c750e1dcc62 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Mon, 18 May 2020 09:53:06 -0300 Subject: wallet API clarifications --- taler-wallet.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/taler-wallet.rst b/taler-wallet.rst index 82296e5f..0308e572 100644 --- a/taler-wallet.rst +++ b/taler-wallet.rst @@ -106,17 +106,17 @@ Balances are the amounts of digital cash held by the wallet. currency?: string; // The total Amount that is currently available to be spent - // excluding amounts tied up in ongoing refresh operations. These are hidden from the user. + // including amounts tied up in ongoing refresh operations. These are hidden from the user. // If the user tries to spend coins locked up this way, // the wallet will give an error message different from "insufficient balance". available: Amount; // the total incoming amount that will be added to the available balance - // when all pending transactions succeed (excluding internal refreshes) + // when all pending transactions succeed (including internal refreshes) pendingIncoming: Amount; // the total outgoing amount that will be subtracted from the available balance - // when all pending transactions succeed (excluding internal refreshes) + // when all pending transactions succeed (including internal refreshes) pendingOutgoing: Amount; // true if the balance has pending transactions @@ -151,7 +151,8 @@ Transactions are all operations or events that are affecting the balance. // a list of past and pending transactions sorted by pending, timestamp and transactionId. // In case two events are both pending and have the same timestamp, // they are sorted by the transactionId - // (lexically ascending and locale-independent comparison). + // (i.e. pending before non-pending transactions, newer before older + // and if all equal transactionId lexically ascending). transactions: Transaction[]; } -- cgit v1.2.3 From 16466dd547243332ad1284827f34369442e1bc3c Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Mon, 18 May 2020 10:21:13 -0300 Subject: clarify amounts in transactions API --- taler-wallet.rst | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/taler-wallet.rst b/taler-wallet.rst index 0308e572..ce369002 100644 --- a/taler-wallet.rst +++ b/taler-wallet.rst @@ -230,6 +230,7 @@ Transactions are all operations or events that are affecting the balance. amountRaw: Amount; // Amount that actually was (or will be) added to the wallet's balance. + // Should always be shown as a positive amount. amountEffective: Amount; } @@ -248,6 +249,7 @@ Transactions are all operations or events that are affecting the balance. amountRaw: Amount; // Amount that was paid, including deposit, wire and refresh fees. + // Should always be shown as a negative amount. amountEffective: Amount; } @@ -310,7 +312,8 @@ Transactions are all operations or events that are affecting the balance. // Amount that has been refunded by the merchant amountRaw: Amount; - // Amount will be added to the wallet's balance after fees and refreshing + // Amount will be added to the wallet's balance after fees and refreshing. + // Should always be shown as a positive amount. amountEffective: Amount; } @@ -331,7 +334,8 @@ Transactions are all operations or events that are affecting the balance. // Raw amount of the tip, without extra fees that apply amountRaw: Amount; - // Amount will be (or was) added to the wallet's balance after fees and refreshing + // Amount will be (or was) added to the wallet's balance after fees and refreshing. + // Should always be shown as a positive amount. amountEffective: Amount; } @@ -365,7 +369,8 @@ Transactions are all operations or events that are affecting the balance. // Raw amount that is refreshed amountRaw: Amount; - // Amount that will be paid as fees for the refresh + // Amount that will be paid as fees for the refresh. + // Should always be shown as a negative amount. amountEffective: Amount; } -- cgit v1.2.3 From 66b09780c1911e90c5b702f0374ef71dfbaa9f8a Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 18 May 2020 19:29:05 +0200 Subject: specify error cases --- core/api-merchant.rst | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index d1563da1..ea1750cf 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -1370,9 +1370,7 @@ Tracking Wire Transfers :status 200 OK: The wire transfer is known to the exchange, details about it follow in the body. - The body of the response is a `TrackTransferResponse`. Note that - the similarity to the response given by the exchange for a "GET /transfer" - is completely intended. + The body of the response is a `TrackTransferResponse`. :status 202 Accepted: The exchange provided conflicting information about the transfer. Namely, there is at least one deposit among the deposits aggregated by ``wtid`` @@ -1411,7 +1409,7 @@ Tracking Wire Transfers payto_uri: string; // base URL of the exchange that made the wire transfer - exchange: string; + exchange_url: string; } .. ts:def:: TrackTransferResponse @@ -1592,6 +1590,11 @@ Tracking Wire Transfers // False if we have an answer and are unhappy, missing if we // do not have an answer from the exchange. verified?: boolean; + + // True if the merchant uses the POST /transfer API to confirm + // that this wire transfer took place (and it is thus not + // something merely claimed by the exchange). + confirmed?: boolean; } @@ -1621,6 +1624,8 @@ Giving Customer Tips :status 200 OK: The backend is waiting for the reserve to be established. The merchant must now perform the wire transfer indicated in the `ReserveCreateConfirmation`. + :status 409 Conflict: + The exchange does not support the requested wire method. :status 424 Failed Dependency: We could not obtain /wire details from the specified exchange base URL. @@ -1628,10 +1633,13 @@ Giving Customer Tips interface ReserveCreateRequest { // Amount that the merchant promises to put into the reserve - initial_amount: Amount; + initial_balance: Amount; // Exchange the merchant intends to use for tipping - exchange_base_url: string; + exchange_url: string; + + // Desired wire method, for example "iban" or "x-taler-bank" + wire_method: string; } -- cgit v1.2.3 From a073c127d324bb0667bacff1f94499340c3f6385 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Tue, 19 May 2020 18:24:46 +0530 Subject: libeufin docs --- libeufin/api-nexus.rst | 111 +++++++++++++++++++++++-------------------------- libeufin/concepts.rst | 56 ++++++++++++------------- 2 files changed, 79 insertions(+), 88 deletions(-) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index 681811aa..f175c9d9 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -36,7 +36,7 @@ Users Management .. http:post:: /users - Create a new user. Only the super-user can call this API. + Create a new user. Only a superuser can call this API. **Request:** @@ -59,6 +59,11 @@ Users Management password: string; } + +.. http:get:: /users + + Return list of users. + Bank Account Management ----------------------- @@ -95,27 +100,13 @@ Bank Account Management // to submit at the bank. uuid: string; - // Specify the bank transport to use for the submission. - transport?: Transport; + // Specify the bank connectionto use for the submission. + connection?: string; } - .. ts:def:: Transport - - interface Transport { - - // Transport type: 'ebics', 'local', 'fints' (forthcoming). - // It must match one of the types actually implemented by - // nexus. - type: string; - - // A mnemonic identifier given by the user to one particular - // transport instance. - name: string; - } - :status 404 Not Found: the unique identifier **or** - the bank transport could not be found in the system + the bank connection could not be found in the system .. http:get:: /bank-accounts//prepared-payments/$uuid @@ -193,16 +184,16 @@ Bank Account Management .. http:post:: /bank-accounts/collected-transactions - Nexus will download bank transactions from the given transport. + Nexus will download bank transactions using the given connection. **Request:** .. ts:def:: CollectedTransaction interface CollectedTransaction { - // Optional field to specify the bank transport to + // Optional field to specify the bank connection to // use for such operation. - bankTransport?: Transport; + bankConnection: connection; // dashed date (YYYY-MM-DD) of the earliest payment // in the result. Optional, defaults to "earliest // possible" date. @@ -254,57 +245,58 @@ Bank Account Management subject: string; } -Bank Transports + +Bank Connections --------------- -Bank transports connect the local LibEuFin bank account +Bank connections connect the local LibEuFin bank account to the real bank. -.. http:post:: /bank-transports +.. http:post:: /bank-connections - Activate a new bank transport for the requesting user. + Activate a new bank connection for the requesting user. **Request:** - .. ts:def:: BankTransport + .. ts:def:: BankConnectionRestoreRequest - interface BankTransport { + interface BankConnectionRestoreRequest { - transport: Transport; + name: string; - // Restore a previous transport. Take precedence + // Restore a previous connection. Take precedence // over the 'new' field. - backup?: TransportBackup; + backup?: BankConnectionBackup; - // Data to create a fresh bank transport without + // Data to create a fresh bank connection without // restoring any backup. - data?: TransportNew; + data?: BankConnectionNew; } - .. ts:def:: TransportNew + .. ts:def:: ConnectionNew - interface TransportNew { + interface ConnectionNew { // This type is strictly dependent on - // the transport being created. For Ebics, + // the connection being created. For Ebics, // it will contain the required fields (as strings): // 'ebicsURL', 'userID', 'partnerID', 'hostID', and // the optional 'systemID'. - // Other transport types, like 'local' (used for testing + // Other connection types, like 'local' (used for testing // purposes skipping any interaction with the bank service) // and 'fints' are all work in progress! } - .. ts:def:: TransportBackup + .. ts:def:: BankConnectionBackup - interface TransportBackup { + interface BankConnectionBackup { // The information needed in this type depend entirely - // on which transport is being restored. + // on which connectionis being restored. } @@ -313,30 +305,29 @@ to the real bank. :status 409 Conflict: The ``name`` field exists already for the requesting user. -.. http:post:: /bank-transports/sendMSG. - - Perform the ``MSG`` operation offered by ``transport-name`` - **without** affecting the nexus database. - **Request:** - - A `Transport` object. +.. http:post:: /bank-connections - **Response:** + List available bank connections. - :status 404 Not Found: ``transport-name`` doesn't exist for - the requesting user. -.. http:post:: /bank-transports//syncMSG. - - Some transports **do** have operations that aren't semantically - related to a bank account but need to be stored locally at the nexus. - One typical example is the downloading of the bank's keys vie the - EBICS transport. This API lets the user perform the ``MSG`` - operation that should result in new data being stored locally - at the nexus. +EBICS-specific APIs +------------------- - **Response:** +The following endpoints are only available for EBICS bank connections. +They are namespaced under the ``/ebics/`` sub-resource. - :status 404 Not Found: ``transport-name`` doesn't exist for - the requesting user. +.. http:post:: /bank-connections//ebics/download/ + + + Perform an EBICS download transaction of type ``msg``. + This request will not affect any bank account or other state + in the nexus database. It will just make a request to the bank + and return the answer. + +.. http:post:: /bank-connections//ebics/upload/ + + Perform an EBICS upload transaction of type ``msg``. + This request will not affect any bank account or other state + in the nexus database. It will just make a request to the bank + and return the answer. diff --git a/libeufin/concepts.rst b/libeufin/concepts.rst index 00afe9a6..da48d7f8 100644 --- a/libeufin/concepts.rst +++ b/libeufin/concepts.rst @@ -57,42 +57,42 @@ The information stored about it includes: with their state (sent or not sent, acknowledged in bank statement or not). * Error reports (e.g. failed payment requests, bank statement items that were not understood by LibEuFin) -* A default bank transport (if configured) that is used by default +* A default bank connection (if configured) that is used by default for operations on the account -* Other connected bank transports +* Other enabled bank connections Examples: .. code:: none - # Download latest transactions via the default bank transport and store them locally + # Download latest transactions via the default bank connection and store them locally curl -XPOST $AUTHEADER https://example1.libeufin.tech/bank-accounts/my-acct/collect-transactions -Bank Transports ---------------- +Bank Connections +---------------- -Bank transports connect the local LibEuFin bank account to the real bank. -The bank transport includes the following data: +Bank connections connect the local LibEuFin bank account to the real bank. +The bank connection includes the following data: -* Local alias ("nickname") of the bank transport -* the type of transport (EBICS, FinTS, loopback, sandbox) -* credentials to use the transport (e.g. password, EBICS subscriber keys) +* Local alias ("nickname") of the bank connection +* the type of connection, i.e. the protocol used (EBICS, FinTS, loopback, sandbox) * protocol configuration (hostname, port, protocol sub-version/flags) +* credentials to use the connection (e.g. password, EBICS subscriber keys) -Bank transports provide the following actions: +Bank connections provide the following actions: -* Initial setup of the transport +* Initial setup of the connection * Execute protocol-specific actions (e.g. EBICS: C53, C52, CCT, CRZ) * These actions do not have any effect on the LibEuFin local bank account. To persist changes to the local bank account (transaction history, payment request status), - the bank transport must be invoked via the bank account. + the bank connection must be invoked via the bank account. * Import bank accounts - * Some bank transport protocols allow LibEuFin to query a list of bank - accounts that the transport has access to. This makes setup easier, + * Some bank connection protocols allow LibEuFin to query a list of bank + accounts that the connection has access to. This makes setup easier, as the user doesn't have to create the local bank account manually. Examples: @@ -100,22 +100,22 @@ Examples: .. code:: none # Manually request the inter-day account report via the EBICS C52 order - curl -XPOST $AUTHEADER https://example1.libeufin.tech/bank-transports/my-ebics-testacct/send-c52 + curl -XPOST $AUTHEADER https://example1.libeufin.tech/bank-connections/my-ebics-testacct/send-c52 - # Download available bank accounts that can be accessed through this transport, + # Download available bank accounts that can be accessed through this connection, # according to the bank server (with EBICS, does a HTD request). # For each of them, create a bank account resource in LibEuFin. - curl -XPOST $AUTHEADER https://example1.libeufin.tech/bank-transports/my-ebics-testacct/import-accounts + curl -XPOST $AUTHEADER https://example1.libeufin.tech/bank-connection/my-ebics-testacct/import-accounts Facades ------- Facades allow extra domain-specific functionality to be implemented on top of users, bank accounts -and bank transports. Facades store the following information: +and bank connections. Facades store the following information: * Local name of the facade * Facade type and options specific to the type -* Associated bank accounts and bank transports that can be accessed by the layer +* Associated bank accounts and bank connections that can be accessed by the layer * Internal tables used by the facade (i.e. facades are stateful) The only facade currently supported by LibEuFin is the "Taler Wire Gateway API" layer. @@ -135,7 +135,7 @@ Access Control The goal of access control in LibEuFin is to allow the following scenarios: -* The Nexus can be used by multiple clients for different bank accounts/transports, +* The Nexus can be used by multiple clients for different bank accounts/connections and these users can't access each other's bank accounts * For monitoring / dashboard (e.g. Taler rejected transactions, blacklists), some users should only be able to have read-only access. @@ -146,15 +146,15 @@ spending limits or more fine-grained read/write permissions. Users can be normal users or superusers. Permission checks do not apply to superusers, and only superusers can create other users. -Each top-level object (bank account, bank transport, layer) has a list of +Each top-level object (bank account, bank connection, facade) has a list of nexus users with write access, and a list of users with read access. -When using a bank transport through a bank account, permission checks must -succeed for both the bank account and the bank transport. +When using a bank connection through a bank account, permission checks must +succeed for both the bank account and the bank connection -This works differently for layers: A layer has a set of associated bank transports +This works differently for facades: A facade has a set of associated bank connections and bank accounts it can access. Permissions on these associated objects -are checked when the layer is *created*. When invoking operations on the layer, -the nexus only checks if the current nexus user can access the layer and *not* the -underlying objects abstracted by the layer. +are checked when the facade is *created*. When invoking operations on the facade, +the nexus only checks if the current nexus user can access the facade and *not* the +underlying objects abstracted by the facade. -- cgit v1.2.3 From 1fd82382d882ad68dbcbfca5e4c0b797be715326 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Tue, 19 May 2020 18:32:01 +0530 Subject: libeufin docs --- libeufin/api-nexus.rst | 50 ++++++++++++++++++++++---------------------------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index f175c9d9..a4cc9ac7 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -16,7 +16,7 @@ be supported in the future. Users Management ---------------- -.. http:get:: /user +.. http:get:: {nexusBase}/user Get information about the current user (based on the authentication information in this request). @@ -34,7 +34,7 @@ Users Management superuser: boolean; } -.. http:post:: /users +.. http:post:: {nexusBase}/users Create a new user. Only a superuser can call this API. @@ -60,14 +60,14 @@ Users Management } -.. http:get:: /users +.. http:get:: {nexusBase}/users Return list of users. Bank Account Management ----------------------- -.. http:get:: /bank-accounts +.. http:get:: {nexusBase}/bank-accounts **Response:** @@ -87,29 +87,15 @@ Bank Account Management holder: string; } -.. http:post:: /bank-accounts/prepared-payments/submit +.. http:post:: {nexusBase}/bank-accounts/{acctid}/prepared-payments/{pmtid}/submit Ask nexus to submit one prepare payment at the bank. - **Request:** - - .. ts:def:: SubmitPayment - - interface SubmitPayment { - // Unique identifier of the (previously) prepared payment - // to submit at the bank. - uuid: string; - - // Specify the bank connectionto use for the submission. - connection?: string; - } - - :status 404 Not Found: the unique identifier **or** the bank connection could not be found in the system -.. http:get:: /bank-accounts//prepared-payments/$uuid +.. http:get:: {nexus}/bank-accounts/{my-acct}/prepared-payments/{uuid} Ask the status of payment ``$uuid``. @@ -147,7 +133,7 @@ Bank Account Management preparationDate: string; } -.. http:post:: /bank-accounts//prepared-payments +.. http:post:: {nexusBase}/bank-accounts/{my-acct}/prepared-payments Ask nexus to prepare instructions for a new payment. Note that ``my-acct`` is the bank account that will be @@ -182,7 +168,7 @@ Bank Account Management uuid: string; } -.. http:post:: /bank-accounts/collected-transactions +.. http:post:: {nexus}/bank-accounts/{acctid}/download-transactions Nexus will download bank transactions using the given connection. @@ -204,7 +190,7 @@ Bank Account Management end: string; } -.. http:get:: /bank-accounts//collected-transactions +.. http:get:: /bank-accounts//transactions Shows which transactions are stored locally at nexus. @@ -247,7 +233,7 @@ Bank Account Management Bank Connections ---------------- +---------------- Bank connections connect the local LibEuFin bank account to the real bank. @@ -306,7 +292,7 @@ to the real bank. the requesting user. -.. http:post:: /bank-connections +.. http:post:: {nexusBase}/bank-connections List available bank connections. @@ -317,17 +303,25 @@ EBICS-specific APIs The following endpoints are only available for EBICS bank connections. They are namespaced under the ``/ebics/`` sub-resource. -.. http:post:: /bank-connections//ebics/download/ +.. http:post:: {nexusBase}/bank-connections//ebics/download/{msg} + + .. warning:: + + Use with care. Typically only necessary for testing and debugging. - Perform an EBICS download transaction of type ``msg``. This request will not affect any bank account or other state in the nexus database. It will just make a request to the bank and return the answer. -.. http:post:: /bank-connections//ebics/upload/ +.. http:post:: {nexusBase}/bank-connections//ebics/upload/{msg} + + .. warning:: + + Use with care. Typically only necessary for testing and debugging. Perform an EBICS upload transaction of type ``msg``. This request will not affect any bank account or other state in the nexus database. It will just make a request to the bank and return the answer. + -- cgit v1.2.3 From 5f6914013ddb7e074d9cbaa170b9e895c43f2081 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Tue, 19 May 2020 18:43:52 +0530 Subject: libeufin docs --- libeufin/api-nexus.rst | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index a4cc9ac7..88ddde3d 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -292,11 +292,34 @@ to the real bank. the requesting user. -.. http:post:: {nexusBase}/bank-connections +.. http:get:: {nexusBase}/bank-connections List available bank connections. +.. http:get:: {nexusBase}/bank-connections/{connid} + + Get information about one bank connection. + + .. ts:def:: BankConnectionInfo + + interface BankConnectionInfo { + name: string; + + connectionType: string; + + ready: boolean; + + // Did the user review the bank's keys? + bankKeysReviewed: boolean; + } + + +.. http:post:: {nexusBase}/bank-connections/{connid}/connect + + Initialize the connection by talking to the bank. + + EBICS-specific APIs ------------------- -- cgit v1.2.3 From c28e9e12cf6e05214b1716dd492dde1cd272085e Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Tue, 19 May 2020 18:52:04 +0530 Subject: libeufin docs --- libeufin/api-nexus.rst | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index 88ddde3d..4b721eea 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -168,7 +168,7 @@ Bank Account Management uuid: string; } -.. http:post:: {nexus}/bank-accounts/{acctid}/download-transactions +.. http:post:: {nexusBase}/bank-accounts/{acctid}/transactions/fetch Nexus will download bank transactions using the given connection. @@ -179,7 +179,7 @@ Bank Account Management interface CollectedTransaction { // Optional field to specify the bank connection to // use for such operation. - bankConnection: connection; + bankConnection?: string; // dashed date (YYYY-MM-DD) of the earliest payment // in the result. Optional, defaults to "earliest // possible" date. @@ -190,7 +190,7 @@ Bank Account Management end: string; } -.. http:get:: /bank-accounts//transactions +.. http:get:: {nexusBase}/bank-accounts/{acctid}/transactions Shows which transactions are stored locally at nexus. @@ -319,6 +319,19 @@ to the real bank. Initialize the connection by talking to the bank. +.. http:post:: {nexusBase}/bank-connections/{connid}/export-backup + + Make a passphrase-encrypted backup of this connection. + +.. http:post:: {nexusBase}/bank-connections/{connid}/accounts/fetch + + Update accounts that are accessible via this bank connection. + +.. http:get:: {nexusBase}/bank-connections/{connid}/accounts + + list accounts that are accessible via this bank connection and what + LibEuFin accounts they are connected to. + EBICS-specific APIs ------------------- @@ -326,7 +339,7 @@ EBICS-specific APIs The following endpoints are only available for EBICS bank connections. They are namespaced under the ``/ebics/`` sub-resource. -.. http:post:: {nexusBase}/bank-connections//ebics/download/{msg} +.. http:post:: {nexusBase}/bank-connections/{connection-name}/ebics/download/{msg} .. warning:: @@ -337,7 +350,7 @@ They are namespaced under the ``/ebics/`` sub-resource. in the nexus database. It will just make a request to the bank and return the answer. -.. http:post:: {nexusBase}/bank-connections//ebics/upload/{msg} +.. http:post:: {nexusBase}/bank-connections/{connection-name}/ebics/upload/{msg} .. warning:: -- cgit v1.2.3 From 6a6d05514267cd04fdd10bc1414a327f7aa273e8 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Tue, 19 May 2020 19:45:06 +0530 Subject: facades docs --- libeufin/api-nexus.rst | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index 4b721eea..b0ea56c1 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -333,6 +333,47 @@ to the real bank. LibEuFin accounts they are connected to. +Facades +------- + +.. http:get:: /facades + + List available facades. + +.. http:get:: /facade/${fcid} + + Get details about a facade. + + .. ts:def:: FacadeInfo + + interface FacadeInfo { + // Name of the facade, same as the "fcid" parameter. + name: string; + + // Type of the facade. + // For example, "taler-wire-gateway". + type: string; + + // Name of the user that created the facade. + // Whenever the facade accesses a resource it is allowed to + // access, the creator must *also* have access to that resource. + creator: string; + + // Bank accounts that the facade has read/write + // access to. + bankAccountsRead: string[]; + bankAccountsWrite: string[]; + + // Bank connections that the facade has read/write + // access to. + bankConnectionsRead: string[]; + bankConnectionsWrite: string[]; + + // Facade-specific configuration details. + config: any; + } + + EBICS-specific APIs ------------------- -- cgit v1.2.3 From a961cdbb00cbf70b1fa112d6636ba820696b79f5 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Tue, 19 May 2020 19:54:28 +0530 Subject: facades docs --- libeufin/api-nexus.rst | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index b0ea56c1..16f59977 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -402,3 +402,27 @@ They are namespaced under the ``/ebics/`` sub-resource. in the nexus database. It will just make a request to the bank and return the answer. + +The taler-wire-gateway facade +----------------------------- + +The ``taler-wire-gateway`` facade has the following configuration: + + +.. ts:def:: TalerWireGatewayFacadeConfig + + interface TalerWireGatewayFacadeConfig { + // Bank account and connection that is + // abstracted over. + bankAccount: string; + bankConnection: string; + + // Corresponds to whether we trust C52, C53 or C54 (SEPA ICT) + // for incoming transfers. + reserveTransferLevel: "statement" | "report" | "notification"; + + // Time between incremental requests + intervalIncremental: string; + + // FIXME: maybe more scheduling parameters? + } -- cgit v1.2.3 From 9339ceac3a570f958593ba25ded5f352887a0450 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 20 May 2020 15:01:32 +0530 Subject: nexus protocol query --- libeufin/api-nexus.rst | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index 16f59977..7624e9a6 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -340,7 +340,7 @@ Facades List available facades. -.. http:get:: /facade/${fcid} +.. http:get:: {nexus}/facade/${fcid} Get details about a facade. @@ -374,6 +374,28 @@ Facades } +Bank Connection Protocols +------------------------- + +.. http:get:: {nexus}/bank-connection-protocols + + List supported bank connection protocols. + +.. http:post:: {nexus}/bank-connection-protocols/ebics/test-host + + Check if the nexus can talk to an EBICS host. + This doesn't create a new connection in the database, + and is useful during setup when the user hasn't entered + the full details for the connection yet. + + .. ts:def:: EbicsHostTestRequest + + interface EbicsHostTestRequest { + ebicsBaseUrl: string; + ebicsHostId: string; + } + + EBICS-specific APIs ------------------- -- cgit v1.2.3 From 26182fa8f045ee79ad95211543610704f8d702f3 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 20 May 2020 12:01:15 +0200 Subject: fix link --- core/api-merchant.rst | 26 ++++++++++++++------------ developers-manual.rst | 2 +- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index ea1750cf..9aeb50a5 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -1624,6 +1624,8 @@ Giving Customer Tips :status 200 OK: The backend is waiting for the reserve to be established. The merchant must now perform the wire transfer indicated in the `ReserveCreateConfirmation`. + :status 408 Timeout: + The exchange did not respond on time. :status 409 Conflict: The exchange does not support the requested wire method. :status 424 Failed Dependency: @@ -1658,13 +1660,13 @@ Giving Customer Tips Obtain list of reserves that have been created for tipping. - **Request:** + **Request:** - :query after: *Optional*. Only return reserves created after the given timestamp in milliseconds - :query active: *Optional*. Only return active/inactive reserves depending on the boolean given - :query failures: *Optional*. Only return reserves where we disagree with the exchange about the initial balance. + :query after: *Optional*. Only return reserves created after the given timestamp in milliseconds + :query active: *Optional*. Only return active/inactive reserves depending on the boolean given + :query failures: *Optional*. Only return reserves where we disagree with the exchange about the initial balance. - **Response:** + **Response:** :status 200 OK: Returns a list of known tipping reserves. @@ -1712,13 +1714,13 @@ Giving Customer Tips .. http:get:: /private/reserves/$RESERVE_PUB - Obtain information about a specific reserve that have been created for tipping. + Obtain information about a specific reserve that have been created for tipping. - **Request:** + **Request:** - :query tips: *Optional*. If set to "yes", returns also information about all of the tips created + :query tips: *Optional*. If set to "yes", returns also information about all of the tips created - **Response:** + **Response:** :status 200 OK: Returns the `ReserveDetail`. @@ -1876,11 +1878,11 @@ Giving Customer Tips Obtain information about a particular tip. - **Request:** + **Request:** - :query pickups: if set to "yes", returns also information about all of the pickups + :query pickups: if set to "yes", returns also information about all of the pickups - **Response:** + **Response:** :status 200 OK: The tip is known. The backend responds with a `TipDetails` message diff --git a/developers-manual.rst b/developers-manual.rst index 8dd83037..70d92f28 100644 --- a/developers-manual.rst +++ b/developers-manual.rst @@ -810,7 +810,7 @@ Components written in C These are the general coding style rules for Taler. * Baseline rules are to follow GNU guidelines, modified or extended - by the GNUnet style: https://gnunet.org/style + by the GNUnet style: https://docs.gnunet.org/handbook/gnunet.html#Coding-style Naming conventions ^^^^^^^^^^^^^^^^^^ -- cgit v1.2.3 From 99886fe02ecf625f4d48202b3d796bd03e090ed8 Mon Sep 17 00:00:00 2001 From: MS Date: Wed, 20 May 2020 16:36:59 +0200 Subject: align docs to code --- libeufin/api-sandbox.rst | 118 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 116 insertions(+), 2 deletions(-) diff --git a/libeufin/api-sandbox.rst b/libeufin/api-sandbox.rst index 015b8d59..bbb7568f 100644 --- a/libeufin/api-sandbox.rst +++ b/libeufin/api-sandbox.rst @@ -13,6 +13,25 @@ HTTP API Adds a new payment to the book. + **Request:** + + .. ts:def:: PaymentRequest + + interface PaymentRequest { + + // IBAN that will reveice the payment. + creditorIban: string; + + // IBAN that will send the payment. + debitorIban: string; + + // amount in the CURRENCY:X.Y form. + amount: string; + + // subject of the payment. + subject: string; + } + .. Host management. @@ -20,26 +39,121 @@ HTTP API Creates a new Ebics host. + **Request:** + + .. ts:def:: EbicsHostRequest + + interface EbicsHostRequest { + + // Ebics version. + hostID: string; + + // Name of the host. + ebicsVersion: string; + } + + .. http:get:: /admin/ebics/hosts Shows the list of all the hosts existing in the system. + **Response:** + + .. ts:def:: EbicsHostResponse + + interface EbicsHostResponse { + + // shows the host IDs that are active in the system. + // The Ebics version *is* missing, but it's still available + // via the HEV message. + ebicsHosts: string[]; + } + + .. Subscriber management. .. http:post:: /admin/ebics/subscribers - Creates a new subscriber. + Creates a new Ebics subscriber. + + **Request:** + + .. ts:def:: SubscriberRequest + + interface SubscriberRequest { + + // hostID + hostID: string; + + // userID + userID: string; + + // partnerID + partnerID: string; + + // systemID + systemID: string; + + } + .. http:get:: /admin/ebics/subscribers Shows the list of all the subscribers existing in the system. + **Response:** + + .. ts:def:: SubscribersResponse + + interface SubscribersResponse { + + subscribers: Subscriber[] + } + + .. ts:def:: Subscriber + + interface Subscriber { + + // userID + userID: string; + + // partnerID + partnerID: string; + + // hostID + hostID: string; + + } + .. http:post:: /admin/ebics/bank-accounts - Associates a new bank account to an existing subscriber. + Associates a new bank account to an existing subscriber. + + **Request:** + + .. ts:def:: BankAccountRequest + + interface BankAccountRequest { + + // Ebics subscriber + subscriber: string; + + // IBAN + iban: string; + + // BIC + bic: string; + + // human name + name: string; + + // bank account label + label: string; + + } .. Main EBICS service. -- cgit v1.2.3 From a21799279d4b059e1867dba1e4fa468c36ee08fe Mon Sep 17 00:00:00 2001 From: MS Date: Wed, 20 May 2020 16:39:24 +0200 Subject: note --- libeufin/api-sandbox.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libeufin/api-sandbox.rst b/libeufin/api-sandbox.rst index bbb7568f..6a970962 100644 --- a/libeufin/api-sandbox.rst +++ b/libeufin/api-sandbox.rst @@ -11,7 +11,8 @@ HTTP API .. http:post:: /admin/payments - Adds a new payment to the book. + Adds a new payment to the book. Mainly used for testing + purposes. **Request:** -- cgit v1.2.3 From 35fcd5e889e3a4578e1090c5fb8c1254342363b1 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Thu, 21 May 2020 02:22:31 +0530 Subject: nexus fetch --- libeufin/api-nexus.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index 7624e9a6..7c11c2c9 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -168,7 +168,7 @@ Bank Account Management uuid: string; } -.. http:post:: {nexusBase}/bank-accounts/{acctid}/transactions/fetch +.. http:post:: {nexusBase}/bank-accounts/{acctid}/fetch-transactions Nexus will download bank transactions using the given connection. -- cgit v1.2.3 From 95fa4f624ecce81fdc3b330fd713185001f2f957 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Thu, 21 May 2020 11:14:22 -0300 Subject: Add more questions to design doc 5 --- design-documents/005-wallet-backup-sync.rst | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/design-documents/005-wallet-backup-sync.rst b/design-documents/005-wallet-backup-sync.rst index d91c3ff5..db463585 100644 --- a/design-documents/005-wallet-backup-sync.rst +++ b/design-documents/005-wallet-backup-sync.rst @@ -111,7 +111,7 @@ Multiple sync servers When a wallet is connected to multiple sync servers, it automatically propagates changes it received from one sync server to the others. Local -changes made by the wallet are propoagated to all sync servers. The goal of +changes made by the wallet are propagated to all sync servers. The goal of this is to make the state of the sync servers converge. The different sync servers one wallet is enrolled with do not necessarily @@ -133,6 +133,9 @@ Discussion / Q&A * For privacy reasons, we can't use some interactive sync service. Thus we use the backup blob as a CRDT that also synchronization for us. +* Do we need to handle backup/sync state becoming very large e.g. by many transactions + and embedded product images potentially exceeding service quota? + * Do we synchronize the list of other backup enrollments? How do we handle distributing the different private keys for them? @@ -145,16 +148,40 @@ Discussion / Q&A * How do we handle a synced wallet that becomes malicious deleting all coins or purchased products? * This needs to balance the genuine need to permanently delete data. + * Should the sync server allow to fetch previous versions of the sync blob? + (If not, how to provide backup functionality?) + * Should the individual wallets keep tombstones (i.e. entities just marked as deleted) around for some time, or should they delete and "sanitize" (delete data not needed for the CRDT) tombstones as soon as possible? +* How do we make it easy to remove compromised devices from the sync group + and prevent them from getting access to future funds and transactions? + + * We need to remove all sync connections on all connected devices + and then individually (and manually) add all devices to the new backup account. + + * If we encrypted the key with each wallet's private sync key, + we could choose which wallets we want to migrate to the new sync account. + + * Can we then roll-over wallets to the new account automatically + or does it have to be manually on each device to prevent an attacker to roll us over? + * How are wallets identified for backup/sync? * UUID / EdDSA pub and nick name? When nickname clashes, some number is added based on lexical sort of the random id ("phone#1", "phone#2"). +* How do we explain users that it can take days for wallet state to synchronize to all devices? + +* How are people supposed to securely store their backup account key(s)? + + * There can be an option to print/export the QR code + * They can manually write down the taler:// Uri containing the key. + * Maybe encode the key in a different format such as + `BIP39 `__? + * Do we have a passphrase for our backup account key(s)? * ??? -- cgit v1.2.3 From be62971d6d8ba546f1099a5a183e3d3c1ed51d3b Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Thu, 21 May 2020 13:40:39 -0300 Subject: Add user flow of backup feature to design doc 5 --- design-documents/004-wallet-withdrawal-flow.rst | 2 +- design-documents/005-wallet-backup-sync.rst | 76 +++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 1 deletion(-) diff --git a/design-documents/004-wallet-withdrawal-flow.rst b/design-documents/004-wallet-withdrawal-flow.rst index b13896a6..f6382446 100644 --- a/design-documents/004-wallet-withdrawal-flow.rst +++ b/design-documents/004-wallet-withdrawal-flow.rst @@ -73,7 +73,7 @@ The user flow between these screens is described in the following graph: ]; transactions [ label = "List of\nTransactions"; - shape = circle; + shape = oval; ]; default_exchange -> tos_changed [label="Yes"]; diff --git a/design-documents/005-wallet-backup-sync.rst b/design-documents/005-wallet-backup-sync.rst index db463585..25213c80 100644 --- a/design-documents/005-wallet-backup-sync.rst +++ b/design-documents/005-wallet-backup-sync.rst @@ -118,6 +118,82 @@ The different sync servers one wallet is enrolled with do not necessarily have the same set of other wallet enrolled. Each sync server has a separate Lamport clock and contains a separate CRDT. +Backup user flow +================ + +.. graphviz:: + + digraph G { + nodesep=0.5; + withdrawal [ + label = "First\nWithdrawal"; + shape = oval; + ]; + has_backup [ + label = "Has backup\nconfigured?"; + shape = diamond; + ]; + app_settings [ + label = "App\nSettings"; + shape = rect; + ]; + backup_onboarding [ + label = "Backup\nOnboarding"; + shape = rect; + ]; + backup_settings [ + label = "Backup Settings\n\n* time of last backup\n* current service"; + shape = rect; + ]; + choose_backup_service [ + label = "Choose\nBackup Service"; + shape = rect; + ]; + tos_accepted [ + label = "Current ToS\naccepted?"; + shape = diamond; + ]; + tos [ + label = "ToS"; + shape = rect; + ]; + payment_required [ + label = "Payment\nrequired?"; + shape = diamond; + ]; + payment_confirmation [ + label = "Payment\nConfirmation"; + shape = rect; + ]; + backup_secret [ + label = "Backup Secret\n\nStore or write down!"; + shape = rect; + ]; + + withdrawal -> has_backup; + has_backup -> backup_onboarding [label="No"]; + backup_onboarding -> backup_settings; + app_settings -> backup_settings; + backup_settings -> backup_settings [label="Disable Backup"]; + backup_settings:w -> backup_settings:w [label="Sync now"]; + backup_settings -> choose_backup_service; + choose_backup_service -> tos_accepted [label="Select Service"]; + tos_accepted -> tos [label="No"]; + tos_accepted -> payment_required [label="Yes"]; + choose_backup_service:w -> choose_backup_service [label="Remove current service"]; + choose_backup_service:n -> choose_backup_service:n [headlabel="Add new service", labeldistance=3.5]; + tos -> payment_required [label="Accept"]; + payment_required -> payment_confirmation [label="Yes"]; + payment_confirmation -> backup_secret [label="Paid"]; + backup_secret -> backup_settings [label="Stored"]; + payment_required:s -> backup_secret:w [label="No"]; + + { rank=same; has_backup; backup_onboarding; } + { rank=same; withdrawal; app_settings; } + { rank=same; tos_accepted; tos; } + { rank=same; payment_required; payment_confirmation; } + } + References ========== -- cgit v1.2.3 From 510d563bdf14457bc5dd3cc6e1288b6131b886ea Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 21 May 2020 22:40:20 +0200 Subject: specify GET /tips/ID endpoint --- core/api-merchant.rst | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index 9aeb50a5..4d728baa 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -1817,15 +1817,13 @@ Giving Customer Tips // Unique tip identifier for the tip that was created. tip_id: HashCode; - // Token that will be handed to the wallet, - // contains all relevant information to accept - // a tip. - tip_token: string; - // URL that will directly trigger processing // the tip when the browser is redirected to it tip_redirect_url: string; + // when does the tip expire + tip_expiration: Timestamp; + } @@ -1932,6 +1930,34 @@ Giving Customer Tips } + +.. http:get:: /tips/$TIP_ID/pickup + + Handle request from wallet to provide details about a tip. + + **Response:** + + :status 200 OK: + A tip is being returned. The backend responds with a `TipInformation` + :status 404 Not Found: + The tip identifier is unknown. + + .. ts:def:: TipInformation + + interface TipInformation { + + // Exchange from which the tip will be withdrawn. Needed by the + // wallet to determine denominations, fees, etc. + exchange_url: string; + + // Amount of the tip (including fees). + tip_amount: Amount; + + // Timestamp indicating when the tip is set to expire (may be in the past). + // Note that tips that have expired MAY also result in a 404 response. + expiration: Timestamp; + } + .. http:post:: /tips/$TIP_ID/pickup Handle request from wallet to pick up a tip. @@ -1955,9 +1981,6 @@ Giving Customer Tips interface TipPickupRequest { - // Identifier of the tip. - tip_id: HashCode; - // List of planches the wallet wants to use for the tip planchets: PlanchetDetail[]; } -- cgit v1.2.3 From 4cafdfcd932bd52284a9002263eff964b4c6dc81 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 22 May 2020 11:17:01 +0200 Subject: clarify doc --- core/api-merchant.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index 4d728baa..5b0f9355 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -1931,7 +1931,7 @@ Giving Customer Tips -.. http:get:: /tips/$TIP_ID/pickup +.. http:get:: /tips/$TIP_ID Handle request from wallet to provide details about a tip. @@ -1950,7 +1950,7 @@ Giving Customer Tips // wallet to determine denominations, fees, etc. exchange_url: string; - // Amount of the tip (including fees). + // (remaining) amount of the tip (including fees). tip_amount: Amount; // Timestamp indicating when the tip is set to expire (may be in the past). -- cgit v1.2.3 From 4986512202f436c52ed0c55d9f36f6e6f1371e82 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 22 May 2020 12:16:43 +0200 Subject: new GNUnet dependencies --- taler-exchange-manual.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/taler-exchange-manual.rst b/taler-exchange-manual.rst index d7a6c21e..2e29dbe3 100644 --- a/taler-exchange-manual.rst +++ b/taler-exchange-manual.rst @@ -180,6 +180,10 @@ exchange compilation. - GNU libgcrypt >= 1.6 +- libsodium >= 1.0 + +- libargon2 >= 20171227 (GNUnet 0.13 needs it to build, not actively used by GNU Taler) + - libjansson >= 2.7 - Postgres >= 9.6, including libpq -- cgit v1.2.3 From 8af00dec7fb5743b343d8a212aff0f1224f7338a Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 22 May 2020 12:17:14 +0200 Subject: new GNUnet dependencies --- taler-merchant-manual.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/taler-merchant-manual.rst b/taler-merchant-manual.rst index 825c7149..6959e311 100644 --- a/taler-merchant-manual.rst +++ b/taler-merchant-manual.rst @@ -205,9 +205,13 @@ backend: - GNU libgcrypt >= 1.6 +- libsodium >= 1.0 + +- libargon2 >= 20171227 (GNUnet 0.13 needs it to build, not actively used by GNU Taler) + - libjansson >= 2.7 -- Postgres >= 9.4, including libpq +- Postgres >= 9.6, including libpq - libgnunetutil (from Git) -- cgit v1.2.3 From ce1034a12e0e1857a13c696384fc5dd41c3e3b4d Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 22 May 2020 12:17:34 +0200 Subject: new GNUnet dependencies --- taler-merchant-manual.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/taler-merchant-manual.rst b/taler-merchant-manual.rst index 6959e311..ca952d29 100644 --- a/taler-merchant-manual.rst +++ b/taler-merchant-manual.rst @@ -201,7 +201,7 @@ backend: - libcurl >= 7.26 (or libgnurl >= 7.26) -- GNU libmicrohttpd >= 0.9.39 +- GNU libmicrohttpd >= 0.9.59 - GNU libgcrypt >= 1.6 -- cgit v1.2.3 From 875a6a5bd3ba991050e459aa79f1bde808a1618a Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Fri, 22 May 2020 08:31:06 -0300 Subject: Fix taler://sync Uri in sync core API section --- core/api-sync.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/core/api-sync.rst b/core/api-sync.rst index 0b692b2d..2add73ef 100644 --- a/core/api-sync.rst +++ b/core/api-sync.rst @@ -374,11 +374,11 @@ Synchronization user experience The menu should include three entries for synchronization: * "synchronize" to manually trigger synchronization, - insensitive if no synchronization provider is available + insensitive if no synchronization provider is available * "export backup configuration" to re-display (and possibly - print) the synchronization and backup parameters (URL and - private key), insensitive if no synchronization - provider is available, and + print) the synchronization and backup parameters (URL and + private key), insensitive if no synchronization + provider is available, and * "import backup configuration" to: * import another devices' synchronization options @@ -397,10 +397,10 @@ private key. It is likely better to map private keys to trustwords (PEP-style). Also, when putting private keys into a QR code, there is the danger of the QR code being scanned and interpreted as a "public" URL. Thus, the QR code should use the schema -"taler-sync://$SYNC-DOMAIN/$SYNC-PATH#private-key" where -"$SYNC-DOMAIN" is the domainname of the synchronization service and -$SYNC-PATH the (usually empty) path. By putting the private key after -"#", we may succeed in disclosing the value even to eager Web-ish +``taler://sync/$SYNC-DOMAIN/$SYNC-PATH#private-key`` where +``$SYNC-DOMAIN`` is the domainname of the synchronization service and +``$SYNC-PATH`` the (usually empty) path. By putting the private key after +``#``, we may succeed in disclosing the value even to eager Web-ish interpreters of URLs. Note that the actual synchronization service must use the HTTPS protocol, which means we can leave out this prefix. -- cgit v1.2.3 From d53ef4d579de76e8f15d24abf288d748219ec308 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Fri, 22 May 2020 13:47:14 -0300 Subject: Add information about backup UI screens to design doc 5 --- design-documents/005-wallet-backup-sync.rst | 70 ++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/design-documents/005-wallet-backup-sync.rst b/design-documents/005-wallet-backup-sync.rst index 25213c80..26dbbf17 100644 --- a/design-documents/005-wallet-backup-sync.rst +++ b/design-documents/005-wallet-backup-sync.rst @@ -185,7 +185,7 @@ Backup user flow tos -> payment_required [label="Accept"]; payment_required -> payment_confirmation [label="Yes"]; payment_confirmation -> backup_secret [label="Paid"]; - backup_secret -> backup_settings [label="Stored"]; + backup_secret -> backup_settings [dir=both, label="Stored"]; payment_required:s -> backup_secret:w [label="No"]; { rank=same; has_backup; backup_onboarding; } @@ -194,6 +194,74 @@ Backup user flow { rank=same; payment_required; payment_confirmation; } } +Backup Settings Screen +---------------------- + +* **Backup my wallet** [on/off] +* **Backup services** + No service active + (shows time of last backup per service) +* **Show backup secret** + You need this secret to restore from backup +* option to sync/backup now (hidden in action bar overflow menu) + +Choose Backup Service Screen +---------------------------- +This screen can be reached by pressing the **Backup services** setting +in the Backup Settings Screen. +It lists the currently active service and other services that can be used. +The user has the option to add new services to the list. + +A backup service has + +* a name +* a base URL +* a fee per year in an explicit currency + +Clicking an active service shows the above service information as well as: + +* the service secret that is required to restore from backup +* last payment date and next scheduled payment date +* option to deactivate the backup service + +Clicking an inactive service allows the user to use the backup service +(after accepting ToS and making the payment). + +Terms of Service Screen +----------------------- +This screen always appears when a backup provider is selected +and the user did not yet accept the current version of its terms of service. + +It shows the terms of service text and an accept checkbox, +as well as the usual back button. + +Payment Confirmation Screen +--------------------------- +This is the same screen that the user sees when doing other purchases. +The only difference is that after successful payment, +the user will be shown the service secret instead of the transaction list. + +Backup Secret Screen +-------------------- +After setting up a backup service, +the user needs to securely store the secret needed to restore from backup. +The secret will be shown as a Taler URI in plain text. +This has the form: ``taler://sync/$SYNC-DOMAIN/$SYNC-PATH#$PRIVATE-KEY`` +Additionally, the URI will be encoded as a QRcode. +Depending on the platform, there should be an option to print or export (PDF) the secret. + +Backup Onboarding +----------------- +If no backup service was selected when the user makes the first withdrawal, +an onboarding screen will be shown that takes the user to the backup configuration screen. + + Don't loose your money, use a backup service! + + Your wallet comes with a list of backup services + that can store an encrypted copy of your wallet. + Use one to keep your money safe! + + [Set backup up now] References ========== -- cgit v1.2.3 From 55ce2359ed861547e880ae4af8ac6aa23d4feea2 Mon Sep 17 00:00:00 2001 From: MS Date: Thu, 28 May 2020 14:01:29 +0200 Subject: Prefer plural for a resource's name. --- libeufin/api-nexus.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index 7c11c2c9..67e9066f 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -340,7 +340,7 @@ Facades List available facades. -.. http:get:: {nexus}/facade/${fcid} +.. http:get:: {nexus}/facades/${fcid} Get details about a facade. -- cgit v1.2.3 From 38099c07f134cc00f8ec942fe0c3794435404f85 Mon Sep 17 00:00:00 2001 From: MS Date: Thu, 28 May 2020 14:05:28 +0200 Subject: spec facade creation --- libeufin/api-nexus.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index 67e9066f..32c7a3c6 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -340,6 +340,10 @@ Facades List available facades. +.. http:post:: {nexus}/facades + + Create a new facade; it requires a `FacadeInfo` as the request's body. + .. http:get:: {nexus}/facades/${fcid} Get details about a facade. -- cgit v1.2.3 From bf3edadb156997de7ee36466db65bacc9c6ad99e Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Thu, 28 May 2020 15:50:04 -0300 Subject: Add design doc 6 for anastasis UX --- anastasis.rst | 1 + design-documents/006-anastasis-ux.rst | 180 ++++++++++++++++++++++++++++++++++ design-documents/index.rst | 1 + 3 files changed, 182 insertions(+) create mode 100644 design-documents/006-anastasis-ux.rst diff --git a/anastasis.rst b/anastasis.rst index 0140e336..b849751a 100644 --- a/anastasis.rst +++ b/anastasis.rst @@ -790,6 +790,7 @@ charge per truth operation using GNU Taler. } +.. _anastasis-auth-methods: ---------------------- Authentication Methods diff --git a/design-documents/006-anastasis-ux.rst b/design-documents/006-anastasis-ux.rst new file mode 100644 index 00000000..9921f994 --- /dev/null +++ b/design-documents/006-anastasis-ux.rst @@ -0,0 +1,180 @@ +Design Doc 006: Anastasis User Experience +######################################### + +Summary +======= + +This document describes the recommended way of implementing the user experience +of setting up and making use of :doc:`../anastasis` account recovery. + +Motivation +========== + +Wallet state consisting of digital cash, transaction history etc. should not be lost. +Taler provides a backup mechanism to prevent that. +As an additional protection measure Anastasis can be used to provide access to the backup, +even if all devices and offline secrets have been lost. + +Access to the backup key is shared with escrow providers that can be chosen by the user. + +Setup Steps +=========== + +.. graphviz:: + + digraph G { + rankdir=LR; + nodesep=0.5; + settings [ + label = "Backup\nSettings"; + shape = oval; + ]; + backup_is_setup [ + label = "Backup\nsetup?"; + shape = diamond; + ]; + provide_id [ + label = "Provide\nIdentification"; + shape = rectangle; + ]; + select_auth [ + label = "Select\nAuthentication Methods\n\nProvide\nAuthentication Data"; + shape = rectangle; + ]; + select_providers [ + label = "Select\nService Providers"; + shape = rectangle; + ]; + threshold [ + label = "Define\nRecovery Threshold"; + shape = rectangle; + ]; + pay [ + label = "Payment"; + shape = oval; + ]; + settings -> backup_is_setup; + backup_is_setup -> provide_id [label="Yes: Setup Recovery"]; + backup_is_setup -> settings [label="No"]; + provide_id -> select_auth; + select_auth -> select_providers; + select_providers -> threshold; + threshold -> pay; + } + +Entry point: Settings +--------------------- + +The app settings should have a section for Anastasis +using a different more universally understood name +like Wallet Recovery. + +The section should have an option to setup Anastasis initially. +This option should be disabled as long as no backup has been set up. +The section could maybe be integrated into the backup settings. + +.. image:: https://git.taler.net/anastasis.git/plain/doc/wireframe/png-export/menu.png + :width: 800 +.. image:: https://git.taler.net/anastasis.git/plain/doc/wireframe/png-export/settings.png + :width: 800 +.. image:: https://git.taler.net/anastasis.git/plain/doc/wireframe/png-export/backupsettings.png + :width: 800 + +Providing Identification +------------------------ + +Instead of a forgettable freely chosen user name, +Anastasis collects various static information from the user +to generate a unique user identifier from that. +Examples for such identifier would be a concatenation +of the full name of the user and their social security or passport number(s). + +The information that can reasonably used here various from cultural context and jurisdiction. +Therefore, one idea is to start by asking for continent +and then the country of primary legal residence, +and then continue from there with country-specific attributes +(and also offer a stateless person option). + +Special care should be taken to avoid that information can later be provided ambiguously +thus changing the user identifier and not being able to restore the user's data. +This can be typographic issues like someone providing "Seestr." +and later "Seestrasse" or "Seestraße" or "seestrasse". +But it can also be simple typos that we can only prevent in some instances +like when checking checksums in passport numbers. + +The user should be made aware that this data will not leave the app +and that it is only used to compute a unique identifier that can not be forgotten. + +If possible, we should guide the user in the country selection +by accessing permission-less information such as the currently set language/locale +and the country of the SIM card. +But nothing invasive like the actual GPS location. + +.. image:: https://git.taler.net/anastasis.git/plain/doc/wireframe/png-export/userid.png + :width: 800 + +Select Authentication Methods +----------------------------- + +After creating a unique identifier, +the user can chose one or more :ref:`anastasis-auth-methods` +supported by Anastasis. + +Ideally when selecting a method, +the user is already asked to provide the information +required for the recovery with that method. +For example, a photo of themselves, their phone number or mailing address. + +.. image:: https://git.taler.net/anastasis.git/plain/doc/wireframe/png-export/truth.png + :width: 800 +.. image:: https://git.taler.net/anastasis.git/plain/doc/wireframe/png-export/addtruth.png + :width: 800 +.. image:: https://git.taler.net/anastasis.git/plain/doc/wireframe/png-export/addtruthmail.png + :width: 800 + + +Confirm/Change Service Providers +-------------------------------- + +Taler should propose a mapping of authentication methods to providers +by minimizing cost (tricky: sign-up vs. recovery costs) +and distributing the selected authentication methods across as many providers as possible. + +The user should be able to change the proposed default selection +and add more than one provider to each chosen method. + +It should also be possible to add providers +that are not included in the default list provided by the wallet. + +.. image:: https://git.taler.net/anastasis.git/plain/doc/wireframe/png-export/policy.png + :width: 800 +.. image:: https://git.taler.net/anastasis.git/plain/doc/wireframe/png-export/addpolicy.png + :width: 800 +.. image:: https://git.taler.net/anastasis.git/plain/doc/wireframe/png-export/addpolicymethod.png + :width: 800 + +Defining Recovery Threshold +--------------------------- + +After mapping authentication methods to providers, +the user needs select which combinations are sufficient to recover the secret. +The default could be ``n-1`` out of ``n``. + +Maybe the `Dark Crystal UI Recommendations `__ +can be an inspiration here. + +Pay for Setup +------------- + +As the last step when all information has been properly provided, +the user is asked to pay for the service with the regular wallet payment confirmation screen. + +Show Service Status After Setup +=============================== + +TODO + +Recovery Steps +============== + +TODO diff --git a/design-documents/index.rst b/design-documents/index.rst index 590cd451..37f81bd4 100644 --- a/design-documents/index.rst +++ b/design-documents/index.rst @@ -15,3 +15,4 @@ and protocol. 003-tos-rendering 004-wallet-withdrawal-flow 005-wallet-backup-sync + 006-anastasis-ux -- cgit v1.2.3 From a7ca300846ba7d94cb8d2660299977bb26a6ce0f Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 30 May 2020 18:58:09 +0200 Subject: update manual to reference DB schema --- core/api-merchant.rst | 5 +- merchant-db.png | Bin 0 -> 459305 bytes taler-exchange-manual.rst | 2 +- taler-merchant-manual.rst | 146 +++++++++++++++++++++++++++++----------------- 4 files changed, 95 insertions(+), 58 deletions(-) create mode 100644 merchant-db.png diff --git a/core/api-merchant.rst b/core/api-merchant.rst index 5b0f9355..517faeef 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -1924,9 +1924,6 @@ Giving Customer Tips // Total amount requested for this pickup_id. requested_amount: Amount; - // Total amount processed by the exchange for this pickup. - exchange_amount: Amount; - } @@ -1976,6 +1973,8 @@ Giving Customer Tips The tip identifier is unknown. :status 409 Conflict: Some of the denomination key hashes of the request do not match those currently available from the exchange (hence there is a conflict between what the wallet requests and what the merchant believes the exchange can provide). + :status 410 Gone: + The tip has expired. .. ts:def:: TipPickupRequest diff --git a/merchant-db.png b/merchant-db.png new file mode 100644 index 00000000..cd5f7bd6 Binary files /dev/null and b/merchant-db.png differ diff --git a/taler-exchange-manual.rst b/taler-exchange-manual.rst index 2e29dbe3..2e84ab54 100644 --- a/taler-exchange-manual.rst +++ b/taler-exchange-manual.rst @@ -776,7 +776,7 @@ useful for test cases but should never be used in production. Finally, taler-exchange-dbinit has a function to garbage collect a database, allowing administrators to purge records that are no longer required. -The database scheme used by the exchange look as follows: +The database scheme used by the exchange looks as follows: .. image:: exchange-db.png diff --git a/taler-merchant-manual.rst b/taler-merchant-manual.rst index ca952d29..245e29b9 100644 --- a/taler-merchant-manual.rst +++ b/taler-merchant-manual.rst @@ -112,60 +112,6 @@ Installation This chapter describes how to install the GNU Taler merchant backend. -Installing Taler using Docker ------------------------------ - -This section provides instructions for the merchant backend installation -using ‘Docker‘. - -For security reasons, we run Docker against a VirtualBox instance, so -the ``docker`` command should connect to a ``docker-machine`` instance -that uses the VirtualBox driver. - -Therefore, the needed tools are: “docker“, “docker-machine“, and -“docker-compose“. Please refer to Docker’s official [1]_ documentation -in order to get those components installed, as that is not in this -manual’s scope. - -Before starting to build the merchant’s image, make sure a -“docker-machine“ instance is up and running. - -Because all of the Docker source file are kept in our “deployment“ -repository, we start by checking out the ``git://taler.net/deployment`` -codebase: - -:: - - $ git clone git://taler.net/deployment - -Now we actually build the merchant’s image. From the same directory as -above: - -:: - - $ cd deployment/docker/merchant/ - $ docker-compose build - -If everything worked as expected, the merchant is ready to be launched. -From the same directory as the previous step: - -:: - - # Recall: the docker-machine should be up and running. - $ docker-compose up - -You should see some live logging from all the involved containers. At -this stage of development, you should also ignore some (harmless) error -message from postresql about already existing roles and databases. - -To test if everything worked as expected, it suffices to issue a simple -request to the merchant, as: - -:: - - $ curl http://$(docker-machine ip)/ - # A greeting message should be returned by the merchant. - .. _Generic-instructions: Generic instructions @@ -329,6 +275,8 @@ commands: libtool \ libltdl-dev \ libunistring-dev \ + libsodium-dev \ + libargon2-dev \ libcurl4-gnutls-dev \ libgcrypt20-dev \ libjansson-dev \ @@ -353,6 +301,8 @@ For more recent versions of Debian, you should instead run: libtool \ libltdl-dev \ libunistring-dev \ + libsodium-dev \ + libargon2-dev \ libcurl4-gnutls-dev \ libgcrypt20-dev \ libjansson-dev \ @@ -1172,3 +1122,91 @@ options: .. [2] Supporting SEPA is still work in progress; the backend will accept this configuration, but the exchange will not work with SEPA today. + + + +Diagnostics +=========== + +This chapter includes various (very unpolished) sections on specific +topics that might be helpful to understand how the exchange operates, +which files should be backed up. The information may also be helpful for +diagnostics. + +.. _Database-Scheme: + +Database Scheme +--------------- + +The merchant database must be initialized using taler-merchant-dbinit. +This tool creates the tables required by the Taler merchant to operate. +The tool also allows you to reset the Taler merchant database, which is +useful for test cases but should never be used in production. Finally, +taler-merchant-dbinit has a function to garbage collect a database, +allowing administrators to purge records that are no longer required. + +The database scheme used by the merchant looks as follows: + +.. image:: merchant-db.png + + + +Legacy +====== + +This chapter contains some legacy documentation we need to update +before it can be considered even reasonably accurate. + +Installing Taler using Docker +----------------------------- + +This section provides instructions for the merchant backend installation +using ‘Docker‘. + +For security reasons, we run Docker against a VirtualBox instance, so +the ``docker`` command should connect to a ``docker-machine`` instance +that uses the VirtualBox driver. + +Therefore, the needed tools are: “docker“, “docker-machine“, and +“docker-compose“. Please refer to Docker’s official [1]_ documentation +in order to get those components installed, as that is not in this +manual’s scope. + +Before starting to build the merchant’s image, make sure a +“docker-machine“ instance is up and running. + +Because all of the Docker source file are kept in our “deployment“ +repository, we start by checking out the ``git://taler.net/deployment`` +codebase: + +:: + + $ git clone git://taler.net/deployment + +Now we actually build the merchant’s image. From the same directory as +above: + +:: + + $ cd deployment/docker/merchant/ + $ docker-compose build + +If everything worked as expected, the merchant is ready to be launched. +From the same directory as the previous step: + +:: + + # Recall: the docker-machine should be up and running. + $ docker-compose up + +You should see some live logging from all the involved containers. At +this stage of development, you should also ignore some (harmless) error +message from postresql about already existing roles and databases. + +To test if everything worked as expected, it suffices to issue a simple +request to the merchant, as: + +:: + + $ curl http://$(docker-machine ip)/ + # A greeting message should be returned by the merchant. -- cgit v1.2.3 From 150fc76e5560f40cad5a94c8d28883f535cb156f Mon Sep 17 00:00:00 2001 From: MS Date: Mon, 1 Jun 2020 07:01:37 -1100 Subject: typo --- libeufin/api-sandbox.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libeufin/api-sandbox.rst b/libeufin/api-sandbox.rst index 6a970962..eedf68af 100644 --- a/libeufin/api-sandbox.rst +++ b/libeufin/api-sandbox.rst @@ -20,7 +20,7 @@ HTTP API interface PaymentRequest { - // IBAN that will reveice the payment. + // IBAN that will receive the payment. creditorIban: string; // IBAN that will send the payment. -- cgit v1.2.3 From 40dbb90fda78439cb1e638fa7b25e821e7ce856f Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 1 Jun 2020 23:44:47 +0200 Subject: fix typo --- core/api-merchant.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index 517faeef..317480f3 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -1042,7 +1042,7 @@ Receiving Payments -.. http:get:: /private/orders/$ORDER_ID/ +.. http:get:: /private/orders/$ORDER_ID Merchant checks the payment status of an order. If the order exists but is not payed yet, the response provides a redirect URL. When the user goes to this URL, -- cgit v1.2.3 From 9553ad5d8bb130500c68f0216e91ff06f8537214 Mon Sep 17 00:00:00 2001 From: Dennis Neufeld Date: Tue, 2 Jun 2020 08:31:29 +0000 Subject: SCrypt to Argon2 --- anastasis.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/anastasis.rst b/anastasis.rst index b849751a..c27b66df 100644 --- a/anastasis.rst +++ b/anastasis.rst @@ -133,10 +133,10 @@ be a social security number together with their full name. Specifics may depend on the cultural context, in this document we will simply refer to this information as the **identifier**. -This identifier will be first hashed with SCrypt, to provide a **kdf_id** +This identifier will be first hashed with Argon2, to provide a **kdf_id** which will be used to derive other keys later. The Hash must also include the respective **server_salt**. This also ensures that the **kdf_id** is different -on each server. The use of SCrypt and the respective server_salt is intended +on each server. The use of Argon2 and the respective server_salt is intended to make it difficult to brute-force **kdf_id** values and help protect user's privacy. Also this ensures that the kdf_ids on every server differs. However, we do not assume that the **identifier** or the **kdf_id** cannot be @@ -147,7 +147,7 @@ likely also be available to other actors. :: - kdf_id := SCrypt( identifier, server_salt, keysize ) + kdf_id := Argon2( identifier, server_salt, keysize ) **identifier**: The secret defined from the user beforehand. -- cgit v1.2.3 From 23ee9f63af1e7fccb0ba7fe81b7f6d0dc1b9e1d3 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 3 Jun 2020 13:46:59 +0530 Subject: nexus: document source field --- libeufin/api-nexus.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index 32c7a3c6..3d5781bf 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -248,11 +248,15 @@ to the real bank. interface BankConnectionRestoreRequest { + source: "new" | "backup"; + name: string; // Restore a previous connection. Take precedence // over the 'new' field. backup?: BankConnectionBackup; + + passphrase?: string; // Data to create a fresh bank connection without // restoring any backup. -- cgit v1.2.3 From 29fbce7e64abba671d539b4e1cb99fcce1b52133 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 3 Jun 2020 14:08:49 +0530 Subject: start with SEPA docs --- libeufin/index.rst | 1 + libeufin/sepa.rst | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 libeufin/sepa.rst diff --git a/libeufin/index.rst b/libeufin/index.rst index 49d44ded..a6d9162e 100644 --- a/libeufin/index.rst +++ b/libeufin/index.rst @@ -11,4 +11,5 @@ LibEuFin is a project providing free software tooling for European FinTech. api-nexus api-sandbox ebics + sepa iso20022 diff --git a/libeufin/sepa.rst b/libeufin/sepa.rst new file mode 100644 index 00000000..9555256a --- /dev/null +++ b/libeufin/sepa.rst @@ -0,0 +1,24 @@ +SEPA Payments +############# + +This page collects reference materials and details for specifics of SEPA payments. + +SEPA Credit Transfer (SCT) +========================== + +SCT is a "normal" bank transfer. Details (terminology, data definitions, flow diagrams) can be found in the EPC's +`SCT rulebook `__. + + +Reject vs Return vs Recall +-------------------------- + +* A **rejected** payment is refused by the originator bank or the + clearing and settlement layer. +* A **returned** payment is refused by the beneficiary's bank via a + counter-transaction over the settlement layer. +* A payment is **recalled** when the originator's bank (potentially + requested by the originator) wants to "undo" a SCT. + +SEPA currently does **not** directly support a mechanism for the **beneficiary** to return +a payment. -- cgit v1.2.3 From 5c7d6d620cf14dbcd626ce5c3e3301ced8c846cc Mon Sep 17 00:00:00 2001 From: MS Date: Thu, 4 Jun 2020 17:56:18 +0200 Subject: no Taler amount format for Sandbox. --- libeufin/api-sandbox.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libeufin/api-sandbox.rst b/libeufin/api-sandbox.rst index eedf68af..f75c76e0 100644 --- a/libeufin/api-sandbox.rst +++ b/libeufin/api-sandbox.rst @@ -26,8 +26,8 @@ HTTP API // IBAN that will send the payment. debitorIban: string; - // amount in the CURRENCY:X.Y form. amount: string; + currency: string; // subject of the payment. subject: string; -- cgit v1.2.3 From c028b2d151aaacb446035638379f565e8e5c30cd Mon Sep 17 00:00:00 2001 From: Jonathan Buchanan Date: Fri, 5 Jun 2020 13:29:09 -0400 Subject: spec for GET /tips --- core/api-merchant.rst | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index 317480f3..3bde039d 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -1955,6 +1955,50 @@ Giving Customer Tips expiration: Timestamp; } + + +.. http:get:: /tips + + Return the list of all tips. + + **Request:** + + :query expired: *Optional*. If set to "yes", the response also includes + tips that have expired. Otherwise only unexpired tips are returned. + + **Response:** + + :status 200 OK: + The backend has successfully found the list of tips. The backend responds + with a `TipsResponse`. + + .. ts:def:: TipsResponse + + interface TipsResponse { + + // List of tips that are present in the backend. + tips: Tip[]; + } + + .. ts:def:: Tip + + interface Tip { + + // Unique identifier for the tip. + tip_id: HashCode; + + // Exchange from which the tip will be withdrawn. + exchange_url: string; + + // (remaining) amount of the tip (including fees). + tip_amount: Amount; + + // Timestamp indicating when the tip is set to expire (may be in the past). + expiration: Timestamp; + } + + + .. http:post:: /tips/$TIP_ID/pickup Handle request from wallet to pick up a tip. -- cgit v1.2.3 From a8a4774c1abec363cc7f178804ac56c558b069f0 Mon Sep 17 00:00:00 2001 From: Jonathan Buchanan Date: Fri, 5 Jun 2020 20:31:41 -0400 Subject: change GET /tips to GET /private/tips --- core/api-merchant.rst | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index 3bde039d..03aefed7 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -1957,14 +1957,17 @@ Giving Customer Tips -.. http:get:: /tips +.. http:get:: /private/tips Return the list of all tips. **Request:** - :query expired: *Optional*. If set to "yes", the response also includes - tips that have expired. Otherwise only unexpired tips are returned. + :query include_expired: *Optional*. If set to "yes", the result includes expired tips also. Otherwise, only active tips are returned. + + :query limit: *Optional*. At most return the given number of results. Negative for descending in database row id, positive for ascending in database row id. + + :query offset: *Optional*. Starting row_id for an iteration. **Response:** @@ -1984,17 +1987,14 @@ Giving Customer Tips interface Tip { + // id of the tip in the backend database + row_id: number; + // Unique identifier for the tip. tip_id: HashCode; - // Exchange from which the tip will be withdrawn. - exchange_url: string; - // (remaining) amount of the tip (including fees). tip_amount: Amount; - - // Timestamp indicating when the tip is set to expire (may be in the past). - expiration: Timestamp; } -- cgit v1.2.3 From 1d396d031a03e12501bb9b06b642366c7fbe4313 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 7 Jun 2020 21:58:00 +0200 Subject: work on spec for GET /private/orders/ID --- core/api-merchant.rst | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index 03aefed7..2110a897 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -1079,19 +1079,32 @@ Receiving Payments .. ts:def:: CheckPaymentPaidResponse interface CheckPaymentPaidResponse { + // did the customer pay for this contract paid: true; // Was the payment refunded (even partially) refunded: boolean; - // Amount that was refunded, only present if refunded is true. + // Total amount the exchange deposited into our bank account + // for this contract, excluding fees. + deposits_total: Amount; + + // Total value of the coins the exchange deposited into our bank account + // for this contract, includes the fees (which the exchange charged). + transfer_value_total: Amount; + + // Total amount that was refunded, only present if refunded is true. refund_amount?: Amount; // Contract terms contract_terms: ContractTerms; // If available, the wire transfer status from the exchange for this order - wire_details?: TransactionWireTransfer; + wire_details?: TransactionWireTransfer[]; + + // If available, the refund details for this order. One entry per + // refunded coin. + refund_details?: RefundDetails[]; } .. ts:def:: CheckPaymentUnpaidResponse @@ -1110,6 +1123,20 @@ Receiving Payments // exist in case the wallet did not yet claim them. } + .. ts:def:: RefundDetails + + interface RefundDetails { + + // Reason given for the refund + reason: string; + + // when was the refund approved + timestamp: Timestamp; + + // Total amount that was refunded (minus a refund fee). + amount: Amount; + } + .. ts:def:: TransactionWireTransfer interface TransactionWireTransfer { -- cgit v1.2.3 From 8c94d1268d3523663941813e53e939d6e43fb010 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Tue, 9 Jun 2020 13:56:08 +0530 Subject: banking protocol docs --- libeufin/banking-protocols.rst | 84 ++++++++++++++++++++++++++++++++++++++++++ libeufin/index.rst | 1 + 2 files changed, 85 insertions(+) create mode 100644 libeufin/banking-protocols.rst diff --git a/libeufin/banking-protocols.rst b/libeufin/banking-protocols.rst new file mode 100644 index 00000000..91c0f599 --- /dev/null +++ b/libeufin/banking-protocols.rst @@ -0,0 +1,84 @@ +Banking Protocols +################# + +This page collects information we have about banking protocols available around +the world. + + +Open Financial Exchange (OFX) Direct Connect +============================================ + +`OFX `__ is widely used in the US. It defines a completely +custom protocol (based on HTTP) and data formats (**not** based on ISO20022) for banking. + + +Electronic Banking Internet Communication Standard (EBICS) +========================================================== + +EBICS is used primarily in Germany, France and Switzerland. Some banks (such as BNPParibas +with their `Global Ebics offering`__) +also allow EBICS access to accounts in other countries. + +EBICS is just a transfer layer for communicating with banks. Banks define what +messages they support. In practice, EBICS is very often used to transfer +ISO20022 messages. + +German banks that are part of the German Banking Industry Committee all must offer EBICS access. +Thus this protocol is a good choice for the German market. + + +FinTS / HBCI +============ + +German home-banking standard. Only some banks allow authentication based on key pairs. +Due to different interpretation of PSD2, other banks now only allow authentication +methods that require interaction from the customer (SCA / Strong Customer Authentication). + +Payloads these days can be ISO20022 messages. + + +PSD2 +==== + +PSD2 is not a technical standard, but high-level legal requirements on (amongst other things) APIs +that banks have to offer. + +There are many implementations of PSD2 APIs. The `Berlin Group `__ +provides a framework that somewhat standardizes technical details, but the use of this standard +is by no means necessary. + +Unfortunately, it focuses on *other* parties accessing *your* bank account. It +does not give customers access to their own bank account. Customers can manage +third party access they give to their bank account in their online banking +system. That mechanism is conceptually similar to OAuth2. In fact, some +implementations of PSD2 even use OAuth2 directly. + +PSD2 requires two main services to be available via an API: + +* AIS (Account Information Service). +* PIS (Payment Initiation Service). + +Together, they're often called XS2A ("access to account"). + +An entity that wants to use AIS has to be registered with the financial +oversight authority in its country (BAFIN in Germany). PIS has even stronger +legal prerequisites. + +On a technical level, using PSD2 APIs usually requires having an `EIDAS +`__ certificate. + + +Bank-Proprietary APIs +===================== + +Some banks offer completely custom APIs to access services of the bank. These often include services +not available via more standardized APIs, such as account creation. + +Often banks frame PSD2 as just another API available in their portfolio of API offerings. + +Examples: + +* `Deutsche Bank `__ +* `ING Group `__ + + diff --git a/libeufin/index.rst b/libeufin/index.rst index a6d9162e..a54d2949 100644 --- a/libeufin/index.rst +++ b/libeufin/index.rst @@ -13,3 +13,4 @@ LibEuFin is a project providing free software tooling for European FinTech. ebics sepa iso20022 + banking-protocols -- cgit v1.2.3 From 643502a2d28c785830ac13c2c6a128e66b0d4276 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Tue, 9 Jun 2020 14:05:13 +0530 Subject: protocols: some more information --- libeufin/banking-protocols.rst | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/libeufin/banking-protocols.rst b/libeufin/banking-protocols.rst index 91c0f599..5e6f94ec 100644 --- a/libeufin/banking-protocols.rst +++ b/libeufin/banking-protocols.rst @@ -30,12 +30,22 @@ Thus this protocol is a good choice for the German market. FinTS / HBCI ============ -German home-banking standard. Only some banks allow authentication based on key pairs. +German home-banking standard. FinTS is the successor of the Home Banking +Computer Interface (HBCI), but older versions of FinTS are often still called +HBCI. + +The current version, FinTS 4.0, is not widely supported by banks yet. Starting with FinTS, +XML is used as a data format. Previous versions used a custom text/binary format. + +Only some banks allow authentication based on key pairs. Due to different interpretation of PSD2, other banks now only allow authentication methods that require interaction from the customer (SCA / Strong Customer Authentication). Payloads these days can be ISO20022 messages. +Examples: + * `GLS `__ + PSD2 ==== @@ -67,6 +77,9 @@ legal prerequisites. On a technical level, using PSD2 APIs usually requires having an `EIDAS `__ certificate. +Examples: + * `Sparkasse `__ + Bank-Proprietary APIs ===================== -- cgit v1.2.3 From 2bb2aa40538acccfdad48f0ec05abb388eeedf2e Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Tue, 9 Jun 2020 14:07:30 +0530 Subject: more examples --- libeufin/banking-protocols.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libeufin/banking-protocols.rst b/libeufin/banking-protocols.rst index 5e6f94ec..1ae08baa 100644 --- a/libeufin/banking-protocols.rst +++ b/libeufin/banking-protocols.rst @@ -93,5 +93,6 @@ Examples: * `Deutsche Bank `__ * `ING Group `__ - +* `Revolut `__ +* `PayPal `__ -- cgit v1.2.3 From 33e98c5a011ffb7c6f3fa5e9640518ccca08020d Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Tue, 9 Jun 2020 14:14:52 +0530 Subject: even more examples --- libeufin/banking-protocols.rst | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libeufin/banking-protocols.rst b/libeufin/banking-protocols.rst index 1ae08baa..dd8c4740 100644 --- a/libeufin/banking-protocols.rst +++ b/libeufin/banking-protocols.rst @@ -63,6 +63,9 @@ third party access they give to their bank account in their online banking system. That mechanism is conceptually similar to OAuth2. In fact, some implementations of PSD2 even use OAuth2 directly. +PSD2 APIs usually use JSON as a data format. Often the schema and terminology is "inspired" by ISO20022 +messages, but no actual ISO20022 XML message formats are used. + PSD2 requires two main services to be available via an API: * AIS (Account Information Service). @@ -77,8 +80,13 @@ legal prerequisites. On a technical level, using PSD2 APIs usually requires having an `EIDAS `__ certificate. -Examples: - * `Sparkasse `__ +Examples (bank offerings): + * `Sparkasse `__ (Berlin Group based) + * `Deutsche Bank `__ + +Examples (standards): + * `STET PSD2 API `__ + * `Berlin Group NextGenPSD2 `__ Bank-Proprietary APIs -- cgit v1.2.3 From fdd8b85830267db8435c03841079ef8ecbd19efb Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Tue, 9 Jun 2020 14:21:38 +0530 Subject: open bank project --- libeufin/banking-protocols.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libeufin/banking-protocols.rst b/libeufin/banking-protocols.rst index dd8c4740..f2dee9e4 100644 --- a/libeufin/banking-protocols.rst +++ b/libeufin/banking-protocols.rst @@ -89,6 +89,7 @@ Examples (standards): * `Berlin Group NextGenPSD2 `__ + Bank-Proprietary APIs ===================== @@ -104,3 +105,11 @@ Examples: * `Revolut `__ * `PayPal `__ + +Open Bank Project +================= + +The `Open Bank Project `__ provides a free software implementation of +banking middleware that supports various APIs, including PSD2-compatible APIs (based on Berlin Group). + +API Docs: https://github.com/OpenBankProject/OBP-API/wiki/Open-Bank-Project-Architecture -- cgit v1.2.3 From 41dca730c5c5f24607fd6f35387829d6f5b1ed02 Mon Sep 17 00:00:00 2001 From: MS Date: Tue, 9 Jun 2020 15:52:15 +0200 Subject: typo --- developers-manual.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/developers-manual.rst b/developers-manual.rst index 70d92f28..19825122 100644 --- a/developers-manual.rst +++ b/developers-manual.rst @@ -1045,7 +1045,7 @@ Anonymous E-Cash the customer. Also some people are scared of anonymity (which as a term is also way too absolute, as anonymity is hardly ever perfect). - **Use instead**: "Privacy-preserving", "Privacy-friedly" + **Use instead**: "Privacy-preserving", "Privacy-friendly" Payment Replay The process of proving to the merchant that the customer is entitled -- cgit v1.2.3 From 54a3dfad4a4f5d0462b61a5b6b4b7818741bf85b Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 10 Jun 2020 13:16:54 +0530 Subject: link to iso20022 data repo --- libeufin/iso20022.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libeufin/iso20022.rst b/libeufin/iso20022.rst index a7d90586..bc9f5901 100644 --- a/libeufin/iso20022.rst +++ b/libeufin/iso20022.rst @@ -5,6 +5,8 @@ ISO 20022 is the standard that defines many XML messages for FinTech. It is very general, and often countries/orgs define subsets (TVS, technical validation subset) of the schema. +Documentation for message fields can be viewed at https://www.iso20022.org/standardsrepository + Cash Management (camt) ====================== -- cgit v1.2.3 From 13f339060c4b475227214cb000df02db7592aa1a Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 12 Jun 2020 10:15:36 +0200 Subject: update spec --- core/api-merchant.rst | 64 ++++++++++++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index 2110a897..407dd46f 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -1063,14 +1063,8 @@ Receiving Payments Returns a `MerchantOrderStatusResponse`, whose format can differ based on the status of the payment. :status 404 Not Found: The order or instance is unknown to the backend. - :status 409 Conflict: - The exchange previously claimed that a deposit was not included in a wire - transfer, and now claims that it is. This means that the exchange is - dishonest. The response contains the cryptographic proof that the exchange - is misbehaving in the form of a `TransactionConflictProof`. :status 424 Failed dependency: - We failed to obtain a response from the exchange about the - wire transfer status. + We failed to obtain a response from the exchange (about the wire transfer status). .. ts:def:: MerchantOrderStatusResponse @@ -1085,26 +1079,39 @@ Receiving Payments // Was the payment refunded (even partially) refunded: boolean; + // Did the exchange wire us the funds + wired: boolean; + // Total amount the exchange deposited into our bank account // for this contract, excluding fees. - deposits_total: Amount; + deposit_total: Amount; + + // Numeric `error code ` indicating errors the exchange + // encountered tracking the wire transfer for this purchase (before + // we even got to specific coin issues). + // 0 if there were no issues. + exchange_ec: number; - // Total value of the coins the exchange deposited into our bank account - // for this contract, includes the fees (which the exchange charged). - transfer_value_total: Amount; + // HTTP status code returned by the exchange when we asked for + // information to track the wire transfer for this purchase. + // 0 if there were no issues. + exchange_hc: number; - // Total amount that was refunded, only present if refunded is true. - refund_amount?: Amount; + // Total amount that was refunded, 0 if refunded is false. + refund_amount: Amount; // Contract terms contract_terms: ContractTerms; - // If available, the wire transfer status from the exchange for this order - wire_details?: TransactionWireTransfer[]; + // Ihe wire transfer status from the exchange for this order if available, otherwise empty array + wire_details: TransactionWireTransfer[]; + + // Reports about trouble obtaining wire transfer details, empty array if no trouble were encountered. + wire_reports: TransactionWireReport[]; - // If available, the refund details for this order. One entry per - // refunded coin. - refund_details?: RefundDetails[]; + // The refund details for this order. One entry per + // refunded coin; empty array if there are no refunds. + refund_details: RefundDetails[]; } .. ts:def:: CheckPaymentUnpaidResponse @@ -1159,33 +1166,28 @@ Receiving Payments confirmed: boolean; } - .. ts:def:: TransactionConflictProof + .. ts:def:: TransactionWireReport - interface TransactionConflictProof { + interface TransactionWireReport { // Numerical `error code ` code: number; // Human-readable error description hint: string; - // A claim by the exchange about the transactions associated - // with a given wire transfer; it does not list the - // transaction that ``transaction_tracking_claim`` says is part - // of the aggregate. This is - // a ``/track/transfer`` response from the exchange. - wtid_tracking_claim: TrackTransferResponse; + // Numerical `error code ` from the exchange. + exchange_ec: number; - // The current claim by the exchange that the given - // transaction is included in the above WTID. - // (A response from ``/track/order``). - transaction_tracking_claim: TrackTransactionResponse; + // HTTP status code received from the exchange. + exchange_hc: number; - // Public key of the coin for which we got conflicting information. + // Public key of the coin for which we got the exchange error. coin_pub: CoinPublicKey; } + .. http:get:: /orders/$ORDER_ID/ Query the payment status of an order. This endpoint is for the wallet. -- cgit v1.2.3 From fc95b0ec29f4c0d7db5542cb2b9e28b85875ba6c Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Fri, 12 Jun 2020 14:43:23 +0530 Subject: transaction identification --- libeufin/index.rst | 1 + libeufin/transaction-identification.rst | 85 +++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 libeufin/transaction-identification.rst diff --git a/libeufin/index.rst b/libeufin/index.rst index a54d2949..766410e2 100644 --- a/libeufin/index.rst +++ b/libeufin/index.rst @@ -14,3 +14,4 @@ LibEuFin is a project providing free software tooling for European FinTech. sepa iso20022 banking-protocols + transaction-identification diff --git a/libeufin/transaction-identification.rst b/libeufin/transaction-identification.rst new file mode 100644 index 00000000..7c737fc2 --- /dev/null +++ b/libeufin/transaction-identification.rst @@ -0,0 +1,85 @@ +Transaction Identification +########################## + +This page describes how bank transactions are **identified** in various banking protocols and +data formats. + +**Why is transaction identification necessary?** +When a client downloads the transaction history from some data source, it has to know +whether a transaction is new, or whether the transaction is already part of the +client's local records. + +Protocol-specific Details +========================= + +ISO 20022 camt.05X +------------------ + +The camt52/53/54 messages defined by ISO 20022 do not have a mandatory transaction +identifier. Instead if defines a handful of optional references. + +Two identifiers seem to be used in practice: The *Account Servicer Reference* and the +*Entry Reference*. Of these, only the *Account Servicer Reference* seems to be useful +for transaction identification. + +The Account Servicer Reference is assigned by the bank to a transaction. In +practice, all banks assign the **same** Account Servicer Reference to the same +transaction showing up in camt52 (the account report), camt53 (the account +statement) and camt53 (credit notifications). + +The Account Servicer Reference is assigned by the bank that reports the transaction, +and does **not** serve as a globally unique identifier for the transaction. + +However, in rare cases, a transaction can be reported that does not yet have an +Account Servicer Reference assigned to it by the bank yet. This can happen +when the bank only received a (SWIFT) pre-notification for the transaction, but decides +to already pass on this information to the customer. In this case, banks seem to +assign an *Entry Reference* to the corresponding entry. + +Most other transactions, however, do **not** have an *Entry Reference* assigned to it. +Some banks document that the *Entry Reference* is only unique within one report for one account. + +OFX +--- + +OFX assigns a transaction identifier to each reported transactions, allowing the client +to know which transactions it has already seen. + +Problems and Possible Solutions +=============================== + +Sometimes the same bank can offer **multiple** ways to download transactions. +In Germany, most banks offer EBICS and FinTS access, which delivers transactions +in the camt.52/53 format. However, some also offer access via PSD2 APIs and completely custom APIs. + +Two APIs from the same bank do not necessarily need to support the same transaction identification scheme. +This could lead to the same transaction showing up multiple times in the account transaction history, which +is clearly bad! + +LibEuFin intends to solve this problem in the following ways: + +1. Each local account has a single "transaction identification scheme". + Importing transactions via a bank connection that has a different transaction + identifier scheme will fail. +2. When a bank connection reports a transaction that is missing the expected transaction identifier, + the status (booked, pending, info) is examined: + + 1. When the status is booked, an error is reported, and corresponding bank message + will be made available for review + 2. When the status is "pending" or "info", the entry will simply be ignored. + +In the future, this might be extended to be less restrictive: + +* An account could be configured to do transaction identification based on a "core attributes hash", + i.e. a cryptographic hash of core attributes of the transactions that are expected to not change. + This should only apply to booked transactions. +* Un-identifiable pending/info transactions could be managed in a separate + "informational" transactions table that is purged as soon as a *booked statement closing transaction* + is reported with a higher booking date. + +Others +====== + +* `UETR `__ is + a unique identifier used on the SWIFT level. It doesn't help for transaction identification + as not every transaction goes over SWIFT, even for SEPA accounts. -- cgit v1.2.3 From 31ac79afe1dc097419fa7ced2c245f0c56758e66 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 13 Jun 2020 18:46:11 +0200 Subject: fix #5957 --- core/api-merchant.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index 407dd46f..f8858376 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -650,6 +650,8 @@ Receiving Payments The request must be a `PostOrderRequest`. + :query refund_delay: *Optional*. If set, must be a relative time. The backend will then set the refund deadline to the current time plus the specified delay. + **Response:** :status 200 OK: @@ -1573,7 +1575,7 @@ Tracking Wire Transfers :query after: *Optional*. Filter for transfers executed after the given timestamp - :query limit: *Optional*. At most return the given number of results. Negative for descending in execution time, positive for ascending in execution time. + :query limit: *Optional*. At most return the given number of results. Negative for descending in execution time, positive for ascending in execution time. Default is -20. :query offset: *Optional*. Starting transfer_serial_id for an iteration. -- cgit v1.2.3 From e942c6941340eaa2f5762a734d985ff9900a154d Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 13 Jun 2020 23:47:33 +0200 Subject: must include merchant public key --- core/api-merchant.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index f8858376..4737e0a1 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -1234,6 +1234,9 @@ Receiving Payments // Successful refunds for this payment, empty array for none. refunds: RefundStatus[]; + // Public key of the merchant. + merchant_pub: EddsaPublicKey; + } .. ts:def:: StatusUnpaid -- cgit v1.2.3 From f136f335fb8ba3d4077b7ac4557e9f77099d976c Mon Sep 17 00:00:00 2001 From: buckE Date: Sun, 14 Jun 2020 05:17:43 +0000 Subject: buildbot five magic sentences added --- developers-manual.rst | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/developers-manual.rst b/developers-manual.rst index 19825122..e84b3d45 100644 --- a/developers-manual.rst +++ b/developers-manual.rst @@ -315,6 +315,35 @@ run the following script from ``deployment/bin``: Environments and Builders on taler.net ====================================== +Buildbot implementation +----------------------- + +GNU Taler uses a buildbot implementation (front end at https://buildbot.taler.net) to manage continuous integration. Buildbot documentation is at https://docs.buildbot.net/. + +Here are some highlights: + +- The WORKER is the config that that lives on a shell account on a +localhost which has buildbot-worker. The WORKER executes the commands +that perform all end-functions of buildbot. + +- The WORKER running buildbot-worker receives these commands by +authenticating and communicating with the buildbot server. + +- The buildbot server's master.cfg file contains FACTORY declarations +which specify the commands to run on localhost. + +- The FACTORY is tied to the WORKER in master.cfg by a BUILDER. + +- The master.cfg also allows for SCHEDULER that defines how and when the +BUILDER is executed. + +- The master.cfg file is checked into git, and then periodically updated on the local account on taler.net (ask Christian for access if needed). Do not edit this file directly/locally for permanent changes. + +Best Practices: + +When creating a new WORKER in the `master.cfg` file, leave a comment specifying the server and user account that this WORKER is called from. (At this time, taler.net is the only server used by this implementation, but it's still good practice.) + + Documentation Builder --------------------- -- cgit v1.2.3 From aa5ea1c5a6f08fa3769f0786a76cf5120b26dd73 Mon Sep 17 00:00:00 2001 From: buckE Date: Sun, 14 Jun 2020 05:22:00 +0000 Subject: buildbot five magic sentences updated --- developers-manual.rst | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/developers-manual.rst b/developers-manual.rst index e84b3d45..145b3223 100644 --- a/developers-manual.rst +++ b/developers-manual.rst @@ -322,26 +322,22 @@ GNU Taler uses a buildbot implementation (front end at https://buildbot.taler.ne Here are some highlights: -- The WORKER is the config that that lives on a shell account on a -localhost which has buildbot-worker. The WORKER executes the commands -that perform all end-functions of buildbot. +- The WORKER is the config that that lives on a shell account on a localhost (taler.net), where this host has buildbot-worker installed. The WORKER executes the commands that perform all end-functions of buildbot. -- The WORKER running buildbot-worker receives these commands by -authenticating and communicating with the buildbot server. +- The WORKER running buildbot-worker receives these commands by authenticating and communicating with the buildbot server using parameters that were specified when the worker was created in that shell account with the `buildbot-worker` command. -- The buildbot server's master.cfg file contains FACTORY declarations -which specify the commands to run on localhost. +- The buildbot server's master.cfg file contains FACTORY declarations which specify the commands that the WORKER will run on localhost. - The FACTORY is tied to the WORKER in master.cfg by a BUILDER. -- The master.cfg also allows for SCHEDULER that defines how and when the -BUILDER is executed. +- The master.cfg also allows for SCHEDULER that defines how and when the BUILDER is executed. + +- Our master.cfg file is checked into git, and then periodically updated on a particular account on taler.net (ask Christian for access if needed). Do not edit this file directly/locally on taler.net, but check changes into Git. -- The master.cfg file is checked into git, and then periodically updated on the local account on taler.net (ask Christian for access if needed). Do not edit this file directly/locally for permanent changes. Best Practices: -When creating a new WORKER in the `master.cfg` file, leave a comment specifying the server and user account that this WORKER is called from. (At this time, taler.net is the only server used by this implementation, but it's still good practice.) +- When creating a new WORKER in the `master.cfg` file, leave a comment specifying the server and user account that this WORKER is called from. (At this time, taler.net is the only server used by this implementation, but it's still good practice.) Documentation Builder -- cgit v1.2.3 From 970db87dcbaed1d8cb2f672689489a584ca5ac92 Mon Sep 17 00:00:00 2001 From: buckE Date: Sun, 14 Jun 2020 05:44:29 +0000 Subject: buildbot command add --- developers-manual.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/developers-manual.rst b/developers-manual.rst index 145b3223..b67ceeb6 100644 --- a/developers-manual.rst +++ b/developers-manual.rst @@ -339,6 +339,9 @@ Best Practices: - When creating a new WORKER in the `master.cfg` file, leave a comment specifying the server and user account that this WORKER is called from. (At this time, taler.net is the only server used by this implementation, but it's still good practice.) +- Create a worker from a shell account with this command: `buildbot-worker create-worker localhost ` + +Then make sure there is a WORKER defined in master.cfg like: `worker.Worker("", "")`` Documentation Builder --------------------- -- cgit v1.2.3 From cd74008d47fd9231bd57e77c87a2d36dc07d4b45 Mon Sep 17 00:00:00 2001 From: buckE Date: Thu, 18 Jun 2020 05:49:33 +0000 Subject: added -W --keep-going to provide exit 1 on sphinx warnings --- Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index e15550e5..e94ea203 100644 --- a/Makefile +++ b/Makefile @@ -60,7 +60,8 @@ diagrams: arch-api.png # The html-linked builder does not support caching, so we # remove all cached state first. html: diagrams - $(SPHINXBUILD) -b html-linked $(ALLSPHINXOPTS) $(BUILDDIR)/html + # -W = exit 1 on warning; --keep-going = complete build anyway + $(SPHINXBUILD) -W --keep-going -b html-linked $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." @@ -121,7 +122,8 @@ latex: "(use \`make latexpdf' here to do that automatically)." latexpdf: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + # -W = exit 1 on warning; --keep-going = complete build anyway + $(SPHINXBUILD) -W --keep-going -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." -- cgit v1.2.3 From 6680f37efc13cb16dbf13a3f7561b48a4a207b07 Mon Sep 17 00:00:00 2001 From: buckE Date: Thu, 18 Jun 2020 05:51:29 +0000 Subject: verify build failure is due to new option --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index e94ea203..305de63e 100644 --- a/Makefile +++ b/Makefile @@ -61,7 +61,7 @@ diagrams: arch-api.png # remove all cached state first. html: diagrams # -W = exit 1 on warning; --keep-going = complete build anyway - $(SPHINXBUILD) -W --keep-going -b html-linked $(ALLSPHINXOPTS) $(BUILDDIR)/html + $(SPHINXBUILD) -b html-linked $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." @@ -123,7 +123,7 @@ latex: latexpdf: # -W = exit 1 on warning; --keep-going = complete build anyway - $(SPHINXBUILD) -W --keep-going -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." -- cgit v1.2.3 From 4860d7c536ec75938faeabf616c396bc6c4988c5 Mon Sep 17 00:00:00 2001 From: buckE Date: Thu, 18 Jun 2020 05:53:16 +0000 Subject: re-add options to cause exit 1 on warnings --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 305de63e..e94ea203 100644 --- a/Makefile +++ b/Makefile @@ -61,7 +61,7 @@ diagrams: arch-api.png # remove all cached state first. html: diagrams # -W = exit 1 on warning; --keep-going = complete build anyway - $(SPHINXBUILD) -b html-linked $(ALLSPHINXOPTS) $(BUILDDIR)/html + $(SPHINXBUILD) -W --keep-going -b html-linked $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." @@ -123,7 +123,7 @@ latex: latexpdf: # -W = exit 1 on warning; --keep-going = complete build anyway - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + $(SPHINXBUILD) -W --keep-going -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." -- cgit v1.2.3 From 48e5bddaec721fa55ffe4bca42fe21e35077d03c Mon Sep 17 00:00:00 2001 From: buckE Date: Thu, 18 Jun 2020 05:55:09 +0000 Subject: write warning messages to ~/warnings.log --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index e94ea203..3aff632b 100644 --- a/Makefile +++ b/Makefile @@ -61,7 +61,7 @@ diagrams: arch-api.png # remove all cached state first. html: diagrams # -W = exit 1 on warning; --keep-going = complete build anyway - $(SPHINXBUILD) -W --keep-going -b html-linked $(ALLSPHINXOPTS) $(BUILDDIR)/html + $(SPHINXBUILD) -W --keep-going -w /home/docbuilder/warnings.log -b html-linked $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." @@ -123,7 +123,7 @@ latex: latexpdf: # -W = exit 1 on warning; --keep-going = complete build anyway - $(SPHINXBUILD) -W --keep-going -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + $(SPHINXBUILD) -W --keep-going -w /home/docbuilder/warnings.log -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." -- cgit v1.2.3 From 5d1416bd0f1b3056f9c871ba3073b4fe10721891 Mon Sep 17 00:00:00 2001 From: buckE Date: Thu, 18 Jun 2020 05:58:21 +0000 Subject: testing e-mail report --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3aff632b..51fbf3d8 100644 --- a/Makefile +++ b/Makefile @@ -60,7 +60,7 @@ diagrams: arch-api.png # The html-linked builder does not support caching, so we # remove all cached state first. html: diagrams - # -W = exit 1 on warning; --keep-going = complete build anyway + # -W = exit 1 on warning; --keep-going = complete build anyway; write log to ~/warnings.log $(SPHINXBUILD) -W --keep-going -w /home/docbuilder/warnings.log -b html-linked $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." -- cgit v1.2.3 From 6ac61177814bfb61a91ff5649131999c76f83c78 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Fri, 19 Jun 2020 00:10:32 +0530 Subject: new terminology --- libeufin/api-nexus.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index 3d5781bf..5eb8044b 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -87,7 +87,7 @@ Bank Account Management holder: string; } -.. http:post:: {nexusBase}/bank-accounts/{acctid}/prepared-payments/{pmtid}/submit +.. http:post:: {nexusBase}/bank-accounts/{acctid}/payment-initiations/{pmtid}/submit Ask nexus to submit one prepare payment at the bank. @@ -95,7 +95,7 @@ Bank Account Management the bank connection could not be found in the system -.. http:get:: {nexus}/bank-accounts/{my-acct}/prepared-payments/{uuid} +.. http:get:: {nexus}/bank-accounts/{my-acct}/payment-initiations/{uuid} Ask the status of payment ``$uuid``. @@ -133,7 +133,7 @@ Bank Account Management preparationDate: string; } -.. http:post:: {nexusBase}/bank-accounts/{my-acct}/prepared-payments +.. http:post:: {nexusBase}/bank-accounts/{my-acct}/payment-initiations Ask nexus to prepare instructions for a new payment. Note that ``my-acct`` is the bank account that will be -- cgit v1.2.3 From 85d3ea16e81e040f5dbd94b1e154b666b420fece Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Fri, 19 Jun 2020 00:43:23 +0530 Subject: open banking --- libeufin/banking-protocols.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libeufin/banking-protocols.rst b/libeufin/banking-protocols.rst index f2dee9e4..6c3fd037 100644 --- a/libeufin/banking-protocols.rst +++ b/libeufin/banking-protocols.rst @@ -113,3 +113,14 @@ The `Open Bank Project `__ provides a free sof banking middleware that supports various APIs, including PSD2-compatible APIs (based on Berlin Group). API Docs: https://github.com/OpenBankProject/OBP-API/wiki/Open-Bank-Project-Architecture + + +UK Open Banking +=============== + +Open Banking is the (quite confusing!) name of a UK-based open banking initiative. + +What's nice about Open Banking is that their APIs are really close to ISO 20022, unlike many +similar HTTP+JSON APIs. + +https://openbanking.atlassian.net/wiki/spaces/DZ/pages/16385802/Specifications -- cgit v1.2.3 From d521aaacc36d9f2df11a9d5e88f653e467d1a9ee Mon Sep 17 00:00:00 2001 From: buckE Date: Fri, 19 Jun 2020 07:17:07 +0000 Subject: changed logfile name --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 51fbf3d8..60745923 100644 --- a/Makefile +++ b/Makefile @@ -61,7 +61,7 @@ diagrams: arch-api.png # remove all cached state first. html: diagrams # -W = exit 1 on warning; --keep-going = complete build anyway; write log to ~/warnings.log - $(SPHINXBUILD) -W --keep-going -w /home/docbuilder/warnings.log -b html-linked $(ALLSPHINXOPTS) $(BUILDDIR)/html + $(SPHINXBUILD) -W --keep-going -w /home/docbuilder/sphinx-warnings.log -b html-linked $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." @@ -123,7 +123,7 @@ latex: latexpdf: # -W = exit 1 on warning; --keep-going = complete build anyway - $(SPHINXBUILD) -W --keep-going -w /home/docbuilder/warnings.log -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + $(SPHINXBUILD) -W --keep-going -w /home/docbuilder/sphinx-warnings.log -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." -- cgit v1.2.3 From 8a27f027a2ffe42b1ebb4c29aae1dccdcf362cf9 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 19 Jun 2020 12:13:11 +0200 Subject: clarify CodeBlau op sec question --- taler-auditor-manual.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/taler-auditor-manual.rst b/taler-auditor-manual.rst index 82b206ec..f5cca273 100644 --- a/taler-auditor-manual.rst +++ b/taler-auditor-manual.rst @@ -59,7 +59,11 @@ to other parties. To perform this duty, you will need at least (read-only) access to the bank transactions of the exchange, as well as a continuously synchronized replica -of the exchange's database. +of the exchange's database. The general assumption for running the auditor +is that this is done on a separate system controlled by the auditor. After +all, the goal is to detect nerfarious activity of the exchange operator, +which cannot be effectively done on a machine controlled by the exchange +operator. For this, every auditor needs to operate a Postgres database. The data collected will include sensitive information about Taler users, including -- cgit v1.2.3 From 9609a023ee62932eaa42c1e3db8bda4ddb359c00 Mon Sep 17 00:00:00 2001 From: MS Date: Fri, 19 Jun 2020 14:13:06 +0200 Subject: importing bank accounts API --- libeufin/api-nexus.rst | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index 5eb8044b..0a56843a 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -327,6 +327,9 @@ to the real bank. Make a passphrase-encrypted backup of this connection. +.. + not implemented. + .. http:post:: {nexusBase}/bank-connections/{connid}/accounts/fetch Update accounts that are accessible via this bank connection. @@ -336,6 +339,22 @@ to the real bank. list accounts that are accessible via this bank connection and what LibEuFin accounts they are connected to. +.. http:post:: {nexusBase}/bank-connections/{connid}/accounts/import + + Import one bank account, allowing the user to name it. + + .. ts:def:: ImportBankAccount + + interface ImportBankAccount { + + // alphanumeric identifier given by the bank to + // the bank account to import. + accountId: string; + + // alphanumeric name chosen by the user to identify + // locally such imported bank account. + localName: string; + } Facades ------- -- cgit v1.2.3 From 16d342d5adbef75e2182d0668f9ecbf97b70aa02 Mon Sep 17 00:00:00 2001 From: MS Date: Sun, 21 Jun 2020 00:17:54 +0200 Subject: account import API --- libeufin/api-nexus.rst | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index 0a56843a..1e713fd9 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -336,8 +336,47 @@ to the real bank. .. http:get:: {nexusBase}/bank-connections/{connid}/accounts - list accounts that are accessible via this bank connection and what - LibEuFin accounts they are connected to. + List the bank accounts that are downloaded into this bank connection + but aren't imported yet: + + .. ts:def:: BankAccount + + interface BankAccount { + + // iban + iban: string; + + // bic + bic: string; + + // account holder + holder: string; + + // account label as given by the bank + account: string; + } + +.. http:get:: {nexusBase}/bank-connections/{connid}/accounts/imported + + List the bank accounts that were imported under this bank connection: + + .. ts:def:: BankAccount + + interface BankAccount { + + // iban + iban: string; + + // bic + bic: string; + + // account holder + holder: string; + + // custom account label as given by the user + account: string; + } + .. http:post:: {nexusBase}/bank-connections/{connid}/accounts/import -- cgit v1.2.3 From 2f947a75e1f88be116325702be5f27ba473a3af4 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 21 Jun 2020 23:54:09 +0200 Subject: update docs to follow v8 protocol evolution, disambiguate struct names --- core/api-merchant.rst | 104 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 76 insertions(+), 28 deletions(-) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index 4737e0a1..0d3f983c 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -808,15 +808,10 @@ Receiving Payments .. ts:def:: OrderHistoryEntry interface OrderHistoryEntry { - // The serial number this entry has in the merchant's DB. - row_id: number; // order ID of the transaction related to this entry. order_id: string; - // Transaction's timestamp - timestamp: Timestamp; - } @@ -1151,7 +1146,7 @@ Receiving Payments interface TransactionWireTransfer { // Responsible exchange - exchange_uri: string; + exchange_url: string; // 32-byte wire transfer identifier wtid: Base32; @@ -1404,13 +1399,13 @@ Tracking Wire Transfers :status 200 OK: The wire transfer is known to the exchange, details about it follow in the body. - The body of the response is a `TrackTransferResponse`. + The body of the response is a `MerchantTrackTransferResponse`. :status 202 Accepted: The exchange provided conflicting information about the transfer. Namely, there is at least one deposit among the deposits aggregated by ``wtid`` that accounts for a coin whose details don't match the details stored in merchant's database about the same keyed coin. - The response body contains the `TrackTransferConflictDetails`. + The response body contains the `ExchangeConflictDetails`. This is indicative of a malicious exchange that claims one thing, but did something else. (With respect to the HTTP specficiation, it is not precisely that we did not act upon the request, more that the usual @@ -1446,9 +1441,9 @@ Tracking Wire Transfers exchange_url: string; } - .. ts:def:: TrackTransferResponse + .. ts:def:: MerchantTrackTransferResponse - interface TrackTransferResponse { + interface MerchantTrackTransferResponse { // Total amount transferred total: Amount; @@ -1459,13 +1454,13 @@ Tracking Wire Transfers execution_time: Timestamp; // details about the deposits - deposits_sums: TrackTransferDetail[]; + deposits_sums: MerchantTrackTransferDetail[]; } - .. ts:def:: TrackTransferDetail + .. ts:def:: MerchantTrackTransferDetail - interface TrackTransferDetail { + interface MerchantTrackTransferDetail { // Business activity associated with the wire transferred amount // ``deposit_value``. order_id: string; @@ -1478,19 +1473,67 @@ Tracking Wire Transfers } + .. ts:def:: ExchangeConflictDetails + + type ExchangeConflictDetails = WireFeeConflictDetails | TrackTransferConflictDetails + + + .. ts:def:: WireFeeConflictDetails + + // Note: this is not the full 'proof' of missbehavior, as + // the bogus message from the exchange with a signature + // over the 'different' wire fee is missing. + // + // This information is NOT provided by the current implementation, + // because this would be quite expensive to generate and is + // hardly needed _here_. Once we add automated reports for + // the Taler auditor, we need to generate this data anyway + // and should probably return it here as well. + interface WireFeeConflictDetails { + // Numerical `error code `: + code: TALER_EC_POST_TRANSFERS_JSON_BAD_WIRE_FEE; + + // Text describing the issue for humans. + hint: string; + + + // Wire fee (wrongly) charged by the exchange, breaking the + // contract affirmed by the exchange_sig. + wire_fee: Amount; + + // Timestamp of the wire transfer + execution_time: Timestamp; + + // The expected wire fee (as signed by the exchange) + expected_wire_fee: Amount; + + // Expected closing fee (needed to verify signature) + expected_closing_fee: Amount; + + // Start date of the expected fee structure + start_date: Timestamp; + + // End date of the expected fee structure + end_date: Timestamp; + + // Signature of the exchange affirming the expected fee structure + master_sig: EddsaSignature; + + // Master public key of the exchange + master_pub: EddsaPublicKey; + + } + + .. ts:def:: TrackTransferConflictDetails interface TrackTransferConflictDetails { // Numerical `error code ` - code: number; + code: TALER_EC_POST_TRANSFERS_CONFLICTING_REPORTS; // Text describing the issue for humans. hint: string; - // A /deposit response matching ``coin_pub`` showing that the - // exchange accepted ``coin_pub`` for ``amount_with_fee``. - exchange_deposit_proof: DepositSuccess; - // Offset in the ``exchange_transfer`` where the // exchange's response fails to match the ``exchange_deposit_proof``. conflict_offset: number; @@ -1498,13 +1541,21 @@ Tracking Wire Transfers // The response from the exchange which tells us when the // coin was returned to us, except that it does not match // the expected value of the coin. - exchange_transfer: TrackTransferResponse; + // + // This field is NOT provided by the current implementation, + // because this would be quite expensive to generate and is + // hardly needed _here_. Once we add automated reports for + // the Taler auditor, we need to generate this data anyway + // and should probably return it here as well. + exchange_transfer: TrackTransferResponse?; - // Public key of the exchange used to sign the response - exchange_pub: EdDSAPublicKey; + // Public key of the exchange used to sign the response to + // our deposit request. + deposit_exchange_pub: EdDSAPublicKey; - // Signature of the exchange signing the (conflicting) response - exchange_sig: EdDSASignature; + // Signature of the exchange signing the (conflicting) response. + // Signs over a `struct TALER_DepositConfirmationPS`. + deposit_exchange_sig: EdDSASignature; // Hash of the merchant's bank account the wire transfer went to h_wire: HashCode; @@ -1512,7 +1563,8 @@ Tracking Wire Transfers // Hash of the contract terms with the conflicting deposit. h_contract_terms: HashCode; - // At what time the exchange received the deposit. + // At what time the exchange received the deposit. Needed + // to verify the `exchange_sig`. deposit_timestamp: Timestamp; // At what time the refund possibility expired (needed to verify ``exchange_sig``). @@ -1521,10 +1573,6 @@ Tracking Wire Transfers // Public key of the coin for which we have conflicting information. coin_pub: EddsaPublicKey; - // Merchant transaction in which ``coin_pub`` was involved for which - // we have conflicting information. - transaction_id: number; - // Amount the exchange counted the coin for in the transfer. amount_with_fee: Amount; -- cgit v1.2.3 From 8216acf41a9deef5a3334d5b3bf629410926fdf5 Mon Sep 17 00:00:00 2001 From: MS Date: Mon, 22 Jun 2020 14:26:11 +0200 Subject: instructions for manual withdrawals --- taler-wallet.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/taler-wallet.rst b/taler-wallet.rst index ce369002..ed081363 100644 --- a/taler-wallet.rst +++ b/taler-wallet.rst @@ -52,6 +52,11 @@ To use the wallet as a library in your own project, run: $ npm install taler-wallet +Manual withdrawing +================== + +taler-wallet-cli advanced withdraw-manually --exchange https://exchange.eurint.taler.net/ --amount EUR:5 + WebExtension Wallet =================== -- cgit v1.2.3 From b454dab174ce9b13a8480703bcd4b3d9df229cd7 Mon Sep 17 00:00:00 2001 From: buckE Date: Tue, 23 Jun 2020 05:50:11 +0000 Subject: added ` to ` re: "verbatim" --- developers-manual.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/developers-manual.rst b/developers-manual.rst index b67ceeb6..14e2a13d 100644 --- a/developers-manual.rst +++ b/developers-manual.rst @@ -667,10 +667,10 @@ What follows is a sort of Wizard. You can find detailed docs at https://docs.we Under *https://weblate.taler.net/create/component/vcs/*: -* **Source code repository** - Generally `git+ssh://git@git.taler.net/`. Check with `git remote -v`. +* **Source code repository** - Generally ``git+ssh://git@git.taler.net/```. Check with ``git remote -v``. * **Repository branch** - Choose the correct branch to draw from and commit to. -* **Repository push URL** - This is generally `git+ssh://git@git.taler.net/` Check with `git remote -v`. -* **Repository browser** - This is the www URL of the Git repo's file browser. Example `https://git.taler.net/.git/tree/{{filename}}?h={{branch}}#n{{line}}` where gets replaced but *{{filename}}* and other items in braces are actual variables in the string. +* **Repository push URL** - This is generally ``git+ssh://git@git.taler.net/``` Check with ``git remote -v``. +* **Repository browser** - This is the www URL of the Git repo's file browser. Example ``https://git.taler.net/.git/tree/{{filename}}?h={{branch}}#n{{line}}`` where gets replaced but *{{filename}}* and other items in braces are actual variables in the string. * **Merge style** - *Rebase*, in line with GNU Taler development procedures * **Translation license** - *GNU General Public License v3.0 or Later* -- cgit v1.2.3 From dc84dc2fdbee220db6a160267bd563a517fdf550 Mon Sep 17 00:00:00 2001 From: buckE Date: Tue, 23 Jun 2020 05:52:48 +0000 Subject: more rst formatting --- developers-manual.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/developers-manual.rst b/developers-manual.rst index 14e2a13d..0d2ae1c1 100644 --- a/developers-manual.rst +++ b/developers-manual.rst @@ -670,7 +670,7 @@ Under *https://weblate.taler.net/create/component/vcs/*: * **Source code repository** - Generally ``git+ssh://git@git.taler.net/```. Check with ``git remote -v``. * **Repository branch** - Choose the correct branch to draw from and commit to. * **Repository push URL** - This is generally ``git+ssh://git@git.taler.net/``` Check with ``git remote -v``. -* **Repository browser** - This is the www URL of the Git repo's file browser. Example ``https://git.taler.net/.git/tree/{{filename}}?h={{branch}}#n{{line}}`` where gets replaced but *{{filename}}* and other items in braces are actual variables in the string. +* **Repository browser** - This is the www URL of the Git repo's file browser. Example ``https://git.taler.net/.git/tree/{{filename}}?h={{branch}}#n{{line}}`` where ```` gets replaced but ``{{filename}}`` and other items in braces are actual variables in the string. * **Merge style** - *Rebase*, in line with GNU Taler development procedures * **Translation license** - *GNU General Public License v3.0 or Later* -- cgit v1.2.3 From 7a937ebaf0966e6940d586021a4a28686b004281 Mon Sep 17 00:00:00 2001 From: buckE Date: Tue, 23 Jun 2020 05:55:25 +0000 Subject: more added `s --- developers-manual.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/developers-manual.rst b/developers-manual.rst index 0d2ae1c1..85bf257f 100644 --- a/developers-manual.rst +++ b/developers-manual.rst @@ -324,7 +324,7 @@ Here are some highlights: - The WORKER is the config that that lives on a shell account on a localhost (taler.net), where this host has buildbot-worker installed. The WORKER executes the commands that perform all end-functions of buildbot. -- The WORKER running buildbot-worker receives these commands by authenticating and communicating with the buildbot server using parameters that were specified when the worker was created in that shell account with the `buildbot-worker` command. +- The WORKER running buildbot-worker receives these commands by authenticating and communicating with the buildbot server using parameters that were specified when the worker was created in that shell account with the ``buildbot-worker`` command. - The buildbot server's master.cfg file contains FACTORY declarations which specify the commands that the WORKER will run on localhost. @@ -337,9 +337,9 @@ Here are some highlights: Best Practices: -- When creating a new WORKER in the `master.cfg` file, leave a comment specifying the server and user account that this WORKER is called from. (At this time, taler.net is the only server used by this implementation, but it's still good practice.) +- When creating a new WORKER in the ``master.cfg`` file, leave a comment specifying the server and user account that this WORKER is called from. (At this time, taler.net is the only server used by this implementation, but it's still good practice.) -- Create a worker from a shell account with this command: `buildbot-worker create-worker localhost ` +- Create a worker from a shell account with this command: ``buildbot-worker create-worker localhost `` Then make sure there is a WORKER defined in master.cfg like: `worker.Worker("", "")`` -- cgit v1.2.3 From d2a97ad1f7b4d5b91ff4e34acc4dbcdf53291f4f Mon Sep 17 00:00:00 2001 From: buckE Date: Tue, 23 Jun 2020 05:57:20 +0000 Subject: another ` --- developers-manual.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/developers-manual.rst b/developers-manual.rst index 85bf257f..36a2ee27 100644 --- a/developers-manual.rst +++ b/developers-manual.rst @@ -341,7 +341,7 @@ Best Practices: - Create a worker from a shell account with this command: ``buildbot-worker create-worker localhost `` -Then make sure there is a WORKER defined in master.cfg like: `worker.Worker("", "")`` +Then make sure there is a WORKER defined in master.cfg like: ``worker.Worker("", "")`` Documentation Builder --------------------- -- cgit v1.2.3 From 41fa2bc416217ff750d85f503c095cbba89edfa3 Mon Sep 17 00:00:00 2001 From: buckE Date: Tue, 23 Jun 2020 08:20:01 +0000 Subject: test addittion --- developers-manual.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/developers-manual.rst b/developers-manual.rst index 36a2ee27..8c3a3501 100644 --- a/developers-manual.rst +++ b/developers-manual.rst @@ -28,7 +28,7 @@ Developer's Manual .. note:: - This manual contains information for developers working on GNU Taler + This manual contains information for developers working on GNU Taler and related components. It is not intended for a general audience. .. contents:: Table of Contents -- cgit v1.2.3 From 1a97c102696ff76d25fd1cc83eaee2110f114df5 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 23 Jun 2020 10:30:47 +0200 Subject: clarify with/without wire fee issue, sanity checks on currencies --- core/api-exchange.rst | 2 +- core/api-merchant.rst | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/core/api-exchange.rst b/core/api-exchange.rst index ea735edc..979eca86 100644 --- a/core/api-exchange.rst +++ b/core/api-exchange.rst @@ -1224,7 +1224,7 @@ typically also view the balance.) .. ts:def:: TrackTransferResponse interface TrackTransferResponse { - // Total amount transferred + // Actual amount of the wire transfer, excluding the wire fee. total: Amount; // Applicable wire fee that was charged diff --git a/core/api-merchant.rst b/core/api-merchant.rst index 0d3f983c..fddaea57 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -1844,6 +1844,8 @@ Giving Customer Tips // Only present if asked for explicitly. tips?: TipStatusEntry[]; + // Is this reserve active (false if it was deleted but not purged) + active: boolean; } .. ts:def:: TipStatusEntry -- cgit v1.2.3 From b07451724f826c8c33630055814516d9fb520e1a Mon Sep 17 00:00:00 2001 From: MS Date: Tue, 23 Jun 2020 15:09:40 +0200 Subject: remove deprecated endpoint --- libeufin/api-nexus.rst | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index 1e713fd9..56b82343 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -356,28 +356,6 @@ to the real bank. account: string; } -.. http:get:: {nexusBase}/bank-connections/{connid}/accounts/imported - - List the bank accounts that were imported under this bank connection: - - .. ts:def:: BankAccount - - interface BankAccount { - - // iban - iban: string; - - // bic - bic: string; - - // account holder - holder: string; - - // custom account label as given by the user - account: string; - } - - .. http:post:: {nexusBase}/bank-connections/{connid}/accounts/import Import one bank account, allowing the user to name it. -- cgit v1.2.3 From a6d5ecd3530d3ca8a92c7f0bcd86640bd35d8377 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 23 Jun 2020 18:55:47 +0200 Subject: better section title --- core/api-merchant.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index fddaea57..d1fa3406 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -626,7 +626,7 @@ management. ------------------ -Receiving Payments +Payment processing ------------------ .. _post-order: -- cgit v1.2.3 From 3e8ca50bb60de1f47cc3380dc3db331399ce1178 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 23 Jun 2020 19:51:32 +0200 Subject: document status codes used that were missing --- core/api-merchant.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index d1fa3406..1c99a79e 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -868,15 +868,26 @@ Payment processing Either the client request is malformed or some specific processing error happened that may be the fault of the client as detailed in the JSON body of the response. + :status 402 Payment required: + There used to be a sufficient payment, but due to refunds the amount effectively + paid is no longer sufficient. (If the amount is generally insufficient, we + return "406 Not Acceptable", only if this is because of refunds we return 402.) :status 403 Forbidden: One of the coin signatures was not valid. :status 404 Not found: The merchant backend could not find the order or the instance and thus cannot process the payment. + :status 406 Not Acceptable: + The payment is insufficient (sum is below the required total amount). + :status 408 Request Timeout: + The backend took too long to process the request. Likely the merchant's connection + to the exchange timed out. Try again. :status 409 Conflict: The exchange rejected the payment because a coin was already spent before. The response will include the ``coin_pub`` for which the payment failed, in addition to the response from the exchange to the ``/deposit`` request. + :status 410 Gone: + The offer has expired and is no longer available. :status 412 Precondition Failed: The given exchange is not acceptable for this merchant, as it is not in the list of accepted exchanges and not audited by an approved auditor. -- cgit v1.2.3 From ccf586100520ea3c56651403d005c78115f42497 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 23 Jun 2020 22:36:50 +0200 Subject: do NOT hardcode paths like /home/docbuilder in Makefile --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 60745923..76a2198e 100644 --- a/Makefile +++ b/Makefile @@ -60,8 +60,8 @@ diagrams: arch-api.png # The html-linked builder does not support caching, so we # remove all cached state first. html: diagrams - # -W = exit 1 on warning; --keep-going = complete build anyway; write log to ~/warnings.log - $(SPHINXBUILD) -W --keep-going -w /home/docbuilder/sphinx-warnings.log -b html-linked $(ALLSPHINXOPTS) $(BUILDDIR)/html +# -W = exit 1 on warning; --keep-going = complete build anyway; write log to ~/warnings.log + $(SPHINXBUILD) -W --keep-going -w warnings.log -b html-linked $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." -- cgit v1.2.3 From 5d3aef5d035c1a78c930b44d19485396d190e09e Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 23 Jun 2020 23:12:59 +0200 Subject: fix RST warnings --- anastasis.rst | 29 ++++++++++++++--------------- core/api-common.rst | 8 ++++++++ core/api-exchange.rst | 3 ++- core/api-merchant.rst | 37 ++++++++++++++++++------------------- core/api-sync.rst | 4 +++- developers-manual.rst | 31 ++++++++++++++++++------------- taler-auditor-manual.rst | 22 +++++++++++----------- taler-merchant-manual.rst | 6 +----- taler-nfc-guide.rst | 13 ++++++------- 9 files changed, 81 insertions(+), 72 deletions(-) diff --git a/anastasis.rst b/anastasis.rst index c27b66df..d0012c7a 100644 --- a/anastasis.rst +++ b/anastasis.rst @@ -255,16 +255,16 @@ individual **key share**, we use different salts ("erd" and "eks" respectively). (iv_i, key_i) = HKDF(key_id, nonce_i, "eks", [optional data], keysize + ivsize) (encrypted_key_share_i, aes_gcm_tag_i) = AES256_GCM(key_share_i, key_i, iv_i) -**encrypted_recovery_document**: The encrypted **recovery document** which contains the escrow methods, policies +**encrypted_recovery_document**: The encrypted **recovery document** which contains the escrow methods, policies and the encrypted **core secret**. -**nonce0**: Nonce which is used to generate *key0* and *iv0* which are used for the encryption of the *recovery document*. +**nonce0**: Nonce which is used to generate *key0* and *iv0* which are used for the encryption of the *recovery document*. Nonce must contain the string "ERD". **optional data**: Key material that optionally is contributed from the authentication method to further obfuscate the key share from the escrow provider. -**encrypted_key_share_i**: The encrypted **key_share** which the escrow provider must release upon successful authentication. -Here, **i** must be a positive number used to iterate over the various **key shares** used for the various **escrow methods** +**encrypted_key_share_i**: The encrypted **key_share** which the escrow provider must release upon successful authentication. +Here, **i** must be a positive number used to iterate over the various **key shares** used for the various **escrow methods** at the various providers. **nonce_i**: Nonce which is used to generate *key_i* and *iv_i* which are used for the encryption of the *key share*. **i** must be @@ -356,7 +356,7 @@ Obtain salt **Response:** Returns a `SaltResponse`_. - + .. _SaltResponse: .. ts:def:: SaltResponse @@ -509,7 +509,7 @@ In the following, UUID is always defined and used according to `RFC 4122`_. Upload a new version of the customer's encrypted recovery document. While the document's structure is described in JSON below, the upload should just be the bytestream of the raw data (i.e. 32 bytes nonce followed - by 16 bytes tag followed by the encrypted document). + by 16 bytes tag followed by the encrypted document). If request has been seen before, the server should do nothing, and otherwise store the new version. The body must begin with a nonce, an AES-GCM tag and continue with the ciphertext. The format is the same as specified for the response of the GET method. The @@ -644,8 +644,7 @@ In the following, UUID is always defined and used according to `RFC 4122`_. } -.. _manage-truth: - +.. _Truth: Managing truth ^^^^^^^^^^^^^^ @@ -692,7 +691,7 @@ charge per truth operation using GNU Taler. // Contains the information of an interface `EncryptedKeyShare`, but simply // as one binary block (in Crockford Base32 encoding for JSON). key_share_data: []; //bytearray - + // Key share method, i.e. "security question", "SMS", "e-mail", ... method: string; @@ -720,7 +719,7 @@ charge per truth operation using GNU Taler. .. http:get:: /truth/$UUID[?response=$RESPONSE] Get the stored encrypted key share. If $RESPONSE is specified by the client, the server checks - if $RESPONSE matches the expected response specified before within the TruthUploadRequest_ (see encrypted_truth). + if $RESPONSE matches the expected response specified before within the TruthUploadRequest_ (see encrypted_truth). Also, the user has to provide the correct *truth_encryption_key* with every get request (see below). When $RESPONSE is correct, the server responses with the encrypted key share. The encrypted key share is returned simply as a byte array and not in JSON format. @@ -768,7 +767,7 @@ charge per truth operation using GNU Taler. // // HKDF for the key generation must include the // string "eks" as salt. - // Depending on the method, + // Depending on the method, // the HKDF may additionally include // bits from the response (i.e. some hash over the // answer to the security question) @@ -811,10 +810,10 @@ FIXME: details! Video identification (vid) ^^^^^^^^^^^^^^^^^^^^^^^^^^ -Requires the user to identify via video-call. The user is expected to delete all metadata revealing -information about him/her from the images before uploading them. Since the respective images must -be passed on to the video identification service in the event of password recovery, it must be -ensured that no further information about the user can be derived from them. +Requires the user to identify via video-call. The user is expected to delete all metadata revealing +information about him/her from the images before uploading them. Since the respective images must +be passed on to the video identification service in the event of password recovery, it must be +ensured that no further information about the user can be derived from them. FIXME: details! diff --git a/core/api-common.rst b/core/api-common.rst index 93d6d09e..272dfd6c 100644 --- a/core/api-common.rst +++ b/core/api-common.rst @@ -267,6 +267,14 @@ Integers // JavaScript numbers restricted to integers type Integer = number; +Objects +^^^^^^^ + +.. ts:def:: Object + + // JavaScript objects, no further restrictions + type Object = object; + Keys ^^^^ diff --git a/core/api-exchange.rst b/core/api-exchange.rst index 979eca86..9b18a18d 100644 --- a/core/api-exchange.rst +++ b/core/api-exchange.rst @@ -1330,11 +1330,12 @@ typically also view the balance.) } +.. _exchange_refund: + ------- Refunds ------- -.. _refund: .. http:POST:: /coins/$COIN_PUB/refund Undo deposit of the given coin, restoring its value. diff --git a/core/api-merchant.rst b/core/api-merchant.rst index 1c99a79e..5c50709a 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -325,8 +325,7 @@ Dynamic Merchant Instances **Response** :status 204 No content: - The backend has successfully removed the instance. The response is a - `PostInstanceRemoveResponse`. + The backend has successfully removed the instance. The body is empty. :status 404 Not found: The instance is unknown to the backend. :status 409 Conflict: @@ -991,7 +990,7 @@ Payment processing The backend will return an `abort response `, which includes verbatim the error codes received from the exchange's - :ref:`refund <_refund>` API. The frontend should pass the replies verbatim to + :ref:`refund ` API. The frontend should pass the replies verbatim to the browser/wallet. .. ts:def:: AbortRequest @@ -1038,12 +1037,12 @@ Payment processing // can generate a substantially shorter response. interface RefundResult { // HTTP status of the request to the exchange. - exchange_http_status: integer; + exchange_http_status: Integer; // The full reply from the exchange. Note only actually - // a if the `exchange_status` is 200, otherwise + // a if the \exchange_http_status\ is 200, otherwise // the error message as defined by the refund API. For - // aborts, the `rtransaction_id` is always 0. + // aborts, the \rtransaction_id\ is always 0. exchange_reply: RefundSuccess; } @@ -1278,7 +1277,7 @@ Payment processing exchange_code?: Integer; // If available, HTTP reply from the exchange. - exchange_reply?: json; + exchange_reply?: Object; // Refund transaction ID. rtransaction_id: Integer; @@ -1299,8 +1298,8 @@ Payment processing // to the wallet and thus not included. interface RefundConfirmation { - // HTTP status of the exchange request, 200 required for refund confirmations. - exchange_status: 200; + // HTTP status of the exchange request, 200 (integer) required for refund confirmations. + exchange_status: "200"; // the EdDSA :ref:`signature` (binary-only) with purpose // `TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND` using a current signing key of the @@ -1342,7 +1341,7 @@ Payment processing The backend refuses to delete the order. -.. _refund: +.. _merchant_refund: -------------- Giving Refunds @@ -1502,7 +1501,7 @@ Tracking Wire Transfers // and should probably return it here as well. interface WireFeeConflictDetails { // Numerical `error code `: - code: TALER_EC_POST_TRANSFERS_JSON_BAD_WIRE_FEE; + code: "TALER_EC_POST_TRANSFERS_JSON_BAD_WIRE_FEE"; // Text describing the issue for humans. hint: string; @@ -1540,7 +1539,7 @@ Tracking Wire Transfers interface TrackTransferConflictDetails { // Numerical `error code ` - code: TALER_EC_POST_TRANSFERS_CONFLICTING_REPORTS; + code: "TALER_EC_POST_TRANSFERS_CONFLICTING_REPORTS"; // Text describing the issue for humans. hint: string; @@ -1558,15 +1557,15 @@ Tracking Wire Transfers // hardly needed _here_. Once we add automated reports for // the Taler auditor, we need to generate this data anyway // and should probably return it here as well. - exchange_transfer: TrackTransferResponse?; + exchange_transfer?: TrackTransferResponse; // Public key of the exchange used to sign the response to // our deposit request. - deposit_exchange_pub: EdDSAPublicKey; + deposit_exchange_pub: EddsaPublicKey; // Signature of the exchange signing the (conflicting) response. - // Signs over a `struct TALER_DepositConfirmationPS`. - deposit_exchange_sig: EdDSASignature; + // Signs over a \struct TALER_DepositConfirmationPS\. + deposit_exchange_sig: EddsaSignature; // Hash of the merchant's bank account the wire transfer went to h_wire: HashCode; @@ -1575,10 +1574,10 @@ Tracking Wire Transfers h_contract_terms: HashCode; // At what time the exchange received the deposit. Needed - // to verify the `exchange_sig`. + // to verify the \exchange_sig\. deposit_timestamp: Timestamp; - // At what time the refund possibility expired (needed to verify ``exchange_sig``). + // At what time the refund possibility expired (needed to verify \exchange_sig\). refund_deadline: Timestamp; // Public key of the coin for which we have conflicting information. @@ -1717,7 +1716,7 @@ Giving Customer Tips :status 200 OK: The backend is waiting for the reserve to be established. The merchant must now perform the wire transfer indicated in the `ReserveCreateConfirmation`. - :status 408 Timeout: + :status 408 Request Timeout: The exchange did not respond on time. :status 409 Conflict: The exchange does not support the requested wire method. diff --git a/core/api-sync.rst b/core/api-sync.rst index 2add73ef..67d1e214 100644 --- a/core/api-sync.rst +++ b/core/api-sync.rst @@ -411,4 +411,6 @@ Web Security Considerations To ensure that the Taler Web extension (and others) can access the service despite Web "security", all service endpoints must set the -"Access-Control-Allow-Origin: *". +header:: + + Access-Control-Allow-Origin: * diff --git a/developers-manual.rst b/developers-manual.rst index 8c3a3501..6e0bc309 100644 --- a/developers-manual.rst +++ b/developers-manual.rst @@ -28,7 +28,7 @@ Developer's Manual .. note:: - This manual contains information for developers working on GNU Taler + This manual contains information for developers working on GNU Taler and related components. It is not intended for a general audience. .. contents:: Table of Contents @@ -636,13 +636,13 @@ About Privilege Levels This is the breakdown of privilege levels in Weblate: -* **Users**/**Viewers** = Can log in, view Translations (*applies to new users*) + * **Users**/**Viewers** = Can log in, view Translations (*applies to new users*) -* **Reviewers** = Can contribute Translations to existing *Components* + * **Reviewers** = Can contribute Translations to existing *Components* -* **Managers** = Can create new *Components* of existing *Projects* + * **Managers** = Can create new *Components* of existing *Projects* -* **Superusers** = Can create new *Projects* + * **Superusers** = Can create new *Projects* Upgrading Privileges -------------------- @@ -661,20 +661,25 @@ Reference: https://docs.weblate.org/en/weblate-4.0.3/admin/projects.html#compone In Weblate, a *Component* is a subset of a *Project* and each Component contains N translations. A Component is generally associated with a Git repo. -To create a Component, log into https://weblate.taler.net/ with your *Manager* or higher credentials and choose **+ Add* from the upper-right corner. +To create a Component, log into https://weblate.taler.net/ with your *Manager* or higher credentials and choose **+ Add** from the upper-right corner. What follows is a sort of Wizard. You can find detailed docs at https://docs.weblate.org/. Here are some important notes about connecting your Component to the Taler Git repository: Under *https://weblate.taler.net/create/component/vcs/*: -* **Source code repository** - Generally ``git+ssh://git@git.taler.net/```. Check with ``git remote -v``. -* **Repository branch** - Choose the correct branch to draw from and commit to. -* **Repository push URL** - This is generally ``git+ssh://git@git.taler.net/``` Check with ``git remote -v``. -* **Repository browser** - This is the www URL of the Git repo's file browser. Example ``https://git.taler.net/.git/tree/{{filename}}?h={{branch}}#n{{line}}`` where ```` gets replaced but ``{{filename}}`` and other items in braces are actual variables in the string. -* **Merge style** - *Rebase*, in line with GNU Taler development procedures + * **Source code repository** - Generally ``git+ssh://git@git.taler.net/```. Check with ``git remote -v``. -* **Translation license** - *GNU General Public License v3.0 or Later* -* **Adding new translation** - Decide how to handle adding new translations + * **Repository branch** - Choose the correct branch to draw from and commit to. + + * **Repository push URL** - This is generally ``git+ssh://git@git.taler.net/``` Check with ``git remote -v``. + + * **Repository browser** - This is the www URL of the Git repo's file browser. Example ``https://git.taler.net/.git/tree/{{filename}}?h={{branch}}#n{{line}}`` where ```` gets replaced but ``{{filename}}`` and other items in braces are actual variables in the string. + + * **Merge style** - *Rebase*, in line with GNU Taler development procedures + + * **Translation license** - *GNU General Public License v3.0 or Later* + + * **Adding new translation** - Decide how to handle adding new translations How to Create a Translation --------------------------- diff --git a/taler-auditor-manual.rst b/taler-auditor-manual.rst index f5cca273..97ba2a5d 100644 --- a/taler-auditor-manual.rst +++ b/taler-auditor-manual.rst @@ -263,7 +263,7 @@ Taler components. See for example the exchange manual for details on the configuration and the ``taler-config`` configuration tool. This section discusses configuration options related to the auditor. -.. _Keys: +.. _AuditorKeys: Keys ---- @@ -275,7 +275,7 @@ The following values are to be configured in the section [auditor]: - AUDITOR_PRIV_FILE: Path to the auditor’s private key file. -.. _Serving: +.. _AuditorServing: Serving ------- @@ -296,7 +296,7 @@ The following values are to be configured in the section [auditor]: for the unixpath (i.e. 660 = rw-rw—-). -.. _Bank-account: +.. _AuditorBank-account: Bank account ------------ @@ -305,7 +305,7 @@ Bank accounts for the auditor are configured in exactly the same way as bank accounts for the exchange. See the exchange documentation for details. -.. _Database: +.. _AuditorDatabaseConfiguration: Database -------- @@ -338,7 +338,7 @@ tables. After running this tool, the rights to CREATE or DROP tables are no longer required and should be removed. -.. _Deployment: +.. _AuditorDeployment: Deployment ========== @@ -356,7 +356,7 @@ Web page offering the respective pairing. FIXME: explain how that Web page works! -.. _Exchange: +.. _AuditorExchange: Exchange -------- @@ -375,7 +375,7 @@ master public key. taler-auditor-exchange -m $MASTER_PUB -u $EXCHANGE_BASE_URL -.. _Denominations: +.. _AuditorDenominations: Denominations ------------- @@ -417,7 +417,7 @@ response will contain an entry in the ``auditors`` array mentioning the auditor’s URL. -.. _Database: +.. _AuditorDatabaseInitialization: Database -------- @@ -464,7 +464,7 @@ Audit Performing an audit is done by invoking the ``taler-auditor`` and ``taler-wire-auditor`` tools respectively. Both tools generate JSON -files, which can then be combined using the ``contrib/render.py'' +files, which can then be combined using the ``contrib/render.py`` script into the TeX report. :: @@ -487,7 +487,7 @@ anymore), this is not recommended in a production setup. -.. _Database-upgrades: +.. _AuditorDatabaseUpgrades: Database upgrades ----------------- @@ -510,7 +510,7 @@ historic transactions. Hence this should not be done in a production system. -.. _Revocations: +.. _AuditorRevocations: Revocations ----------- diff --git a/taler-merchant-manual.rst b/taler-merchant-manual.rst index 245e29b9..dfa6492e 100644 --- a/taler-merchant-manual.rst +++ b/taler-merchant-manual.rst @@ -1119,10 +1119,6 @@ options: .. [1] https://docs.docker.com/ -.. [2] - Supporting SEPA is still work in progress; the backend will accept - this configuration, but the exchange will not work with SEPA today. - Diagnostics @@ -1133,7 +1129,7 @@ topics that might be helpful to understand how the exchange operates, which files should be backed up. The information may also be helpful for diagnostics. -.. _Database-Scheme: +.. _MerchantDatabaseScheme: Database Scheme --------------- diff --git a/taler-nfc-guide.rst b/taler-nfc-guide.rst index 20239352..88fa13d5 100644 --- a/taler-nfc-guide.rst +++ b/taler-nfc-guide.rst @@ -45,7 +45,7 @@ using `curl `_ to make HTTP(S) requests. can be opened, and give a warning if it is detected that the devices does not have Internet connectivity. - The following :http:post:`/order` request to the merchant backend creates a + The following :http:post:`/private/orders` request to the merchant backend creates a simple order: .. code-block:: sh @@ -63,20 +63,20 @@ using `curl `_ to make HTTP(S) requests. } EOF ) - $ curl -XPOST -H"$auth_header" -d "$order_req" "$backend_base_url"/order + $ curl -XPOST -H"$auth_header" -d "$order_req" "$backend_base_url"/private/orders { "order_id": "2019.255-02YDHMXCBQP6J" } 2. The merchant checks the payment status of the order using - :http:get:`/check-payment`: + :http:get:`/private/orders/$ORDER_ID`: .. code-block:: sh $ backend_base_url=https://backend.demo.taler.net/ $ auth_header='Authorization: ApiKey sandbox' $ curl -XGET -H"$auth_header" \ - "$backend_base_url/check-payment?order_id=2019.255-02YDHMXCBQP6J" + "$backend_base_url/private/orders/2019.255-02YDHMXCBQP6J" # Response: { "taler_pay_uri": "taler://pay/backend.demo.taler.net/-/-/2019.255-02YDHMXCBQP6J", @@ -121,7 +121,7 @@ using `curl `_ to make HTTP(S) requests. $ backend_base_url=https://backend.demo.taler.net/ $ auth_header='Authorization: ApiKey sandbox' $ curl -XGET -H"$auth_header" \ - "$backend_base_url/check-payment?order_id=2019.255-02YDHMXCBQP6J" + "$backend_base_url/private/orders/2019.255-02YDHMXCBQP6J" # Response: { "paid": true, @@ -135,7 +135,7 @@ using `curl `_ to make HTTP(S) requests. before responding with the fulfillment page. For in-store payments, the merchant must periodically check the payment status. - Instead of polling in a busy loop, the ``long_poll_ms`` parameter of :http:get:`/check-payment` + Instead of polling in a busy loop, the ``timeout_ms`` parameter of :http:get:`/private/orders/$ORDER_ID` should be used. @@ -281,4 +281,3 @@ The request tunneling request/response JSON messages have the following schema: // May contain error details if 'status==0' body?: object; } - -- cgit v1.2.3 From 5d8e87703b339cc723bb5a27d20cbd6be1df20c2 Mon Sep 17 00:00:00 2001 From: buckE Date: Wed, 24 Jun 2020 00:06:56 +0000 Subject: ~ instead of full path --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 76a2198e..2fd6b1dd 100644 --- a/Makefile +++ b/Makefile @@ -61,7 +61,7 @@ diagrams: arch-api.png # remove all cached state first. html: diagrams # -W = exit 1 on warning; --keep-going = complete build anyway; write log to ~/warnings.log - $(SPHINXBUILD) -W --keep-going -w warnings.log -b html-linked $(ALLSPHINXOPTS) $(BUILDDIR)/html + $(SPHINXBUILD) -W --keep-going -w ~/sphinx-warnings.log -b html-linked $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." @@ -123,7 +123,7 @@ latex: latexpdf: # -W = exit 1 on warning; --keep-going = complete build anyway - $(SPHINXBUILD) -W --keep-going -w /home/docbuilder/sphinx-warnings.log -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + $(SPHINXBUILD) -W --keep-going -w ~/sphinx-warnings.log -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." -- cgit v1.2.3 From 7b1fbffcba394bcdf9326c6285679b684b98d2d1 Mon Sep 17 00:00:00 2001 From: buckE Date: Wed, 24 Jun 2020 00:19:57 +0000 Subject: no local copy of sphinx error logs --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 2fd6b1dd..6116dcde 100644 --- a/Makefile +++ b/Makefile @@ -61,7 +61,7 @@ diagrams: arch-api.png # remove all cached state first. html: diagrams # -W = exit 1 on warning; --keep-going = complete build anyway; write log to ~/warnings.log - $(SPHINXBUILD) -W --keep-going -w ~/sphinx-warnings.log -b html-linked $(ALLSPHINXOPTS) $(BUILDDIR)/html + $(SPHINXBUILD) -W --keep-going -b html-linked $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." @@ -123,7 +123,7 @@ latex: latexpdf: # -W = exit 1 on warning; --keep-going = complete build anyway - $(SPHINXBUILD) -W --keep-going -w ~/sphinx-warnings.log -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + $(SPHINXBUILD) -W --keep-going -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." -- cgit v1.2.3 From 3b672a34c723d002e0c5727ef508cf4ef332a6cc Mon Sep 17 00:00:00 2001 From: buckE Date: Wed, 24 Jun 2020 00:32:38 +0000 Subject: using $PWD for sphinx warning log --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 6116dcde..c83f8335 100644 --- a/Makefile +++ b/Makefile @@ -61,7 +61,7 @@ diagrams: arch-api.png # remove all cached state first. html: diagrams # -W = exit 1 on warning; --keep-going = complete build anyway; write log to ~/warnings.log - $(SPHINXBUILD) -W --keep-going -b html-linked $(ALLSPHINXOPTS) $(BUILDDIR)/html + $(SPHINXBUILD) -W --keep-going -w $PWD/sphinx-warnings.log -b html-linked $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." @@ -123,7 +123,7 @@ latex: latexpdf: # -W = exit 1 on warning; --keep-going = complete build anyway - $(SPHINXBUILD) -W --keep-going -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + $(SPHINXBUILD) -W --keep-going -w $PWD/sphinx-warnings.log -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." -- cgit v1.2.3 From 6f72059695927efaaa2d67b1cbd82d42ce555c13 Mon Sep 17 00:00:00 2001 From: buckE Date: Wed, 24 Jun 2020 03:39:17 +0000 Subject: $HOME/logs --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index c83f8335..10df8dfe 100644 --- a/Makefile +++ b/Makefile @@ -61,7 +61,7 @@ diagrams: arch-api.png # remove all cached state first. html: diagrams # -W = exit 1 on warning; --keep-going = complete build anyway; write log to ~/warnings.log - $(SPHINXBUILD) -W --keep-going -w $PWD/sphinx-warnings.log -b html-linked $(ALLSPHINXOPTS) $(BUILDDIR)/html + $(SPHINXBUILD) -W --keep-going -w $HOME/logs/sphinx-warnings.log -b html-linked $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." @@ -123,7 +123,7 @@ latex: latexpdf: # -W = exit 1 on warning; --keep-going = complete build anyway - $(SPHINXBUILD) -W --keep-going -w $PWD/sphinx-warnings.log -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + $(SPHINXBUILD) -W --keep-going -w $HOME/logs/sphinx-warnings.log -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." -- cgit v1.2.3 From 46f151a7b4ab0773620107f10a659cd6b79f24bf Mon Sep 17 00:00:00 2001 From: buckE Date: Wed, 24 Jun 2020 03:51:54 +0000 Subject: (HOME)? --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 10df8dfe..45b91a2c 100644 --- a/Makefile +++ b/Makefile @@ -123,7 +123,7 @@ latex: latexpdf: # -W = exit 1 on warning; --keep-going = complete build anyway - $(SPHINXBUILD) -W --keep-going -w $HOME/logs/sphinx-warnings.log -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + $(SPHINXBUILD) -W --keep-going -w $(HOME)/logs/sphinx-warnings.log -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." -- cgit v1.2.3 From 62bac4b03a7d334ec61410dfa4b985ecb39bb33d Mon Sep 17 00:00:00 2001 From: buckE Date: Wed, 24 Jun 2020 04:09:46 +0000 Subject: $(shell echo $HOME) --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 45b91a2c..1d515e27 100644 --- a/Makefile +++ b/Makefile @@ -61,7 +61,7 @@ diagrams: arch-api.png # remove all cached state first. html: diagrams # -W = exit 1 on warning; --keep-going = complete build anyway; write log to ~/warnings.log - $(SPHINXBUILD) -W --keep-going -w $HOME/logs/sphinx-warnings.log -b html-linked $(ALLSPHINXOPTS) $(BUILDDIR)/html + $(SPHINXBUILD) -W --keep-going -w $(shell echo $HOME)/logs/sphinx-warnings.log -b html-linked $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." @@ -123,7 +123,7 @@ latex: latexpdf: # -W = exit 1 on warning; --keep-going = complete build anyway - $(SPHINXBUILD) -W --keep-going -w $(HOME)/logs/sphinx-warnings.log -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + $(SPHINXBUILD) -W --keep-going -w $(shell echo $HOME)/logs/sphinx-warnings.log -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." -- cgit v1.2.3 From a5ac60f15d2d3c64763db06ee554da90a8500fef Mon Sep 17 00:00:00 2001 From: MS Date: Wed, 24 Jun 2020 08:08:03 +0200 Subject: address warnings --- libeufin/api-nexus.rst | 4 ++-- libeufin/banking-protocols.rst | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index 56b82343..d63fbd0b 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -264,9 +264,9 @@ to the real bank. } - .. ts:def:: ConnectionNew + .. ts:def:: BankConnectionNew - interface ConnectionNew { + interface BankConnectionNew { // This type is strictly dependent on // the connection being created. For Ebics, diff --git a/libeufin/banking-protocols.rst b/libeufin/banking-protocols.rst index 6c3fd037..17dda0b9 100644 --- a/libeufin/banking-protocols.rst +++ b/libeufin/banking-protocols.rst @@ -16,7 +16,7 @@ Electronic Banking Internet Communication Standard (EBICS) ========================================================== EBICS is used primarily in Germany, France and Switzerland. Some banks (such as BNPParibas -with their `Global Ebics offering`__) +with their `Global Ebics `__) also allow EBICS access to accounts in other countries. EBICS is just a transfer layer for communicating with banks. Banks define what @@ -77,8 +77,7 @@ An entity that wants to use AIS has to be registered with the financial oversight authority in its country (BAFIN in Germany). PIS has even stronger legal prerequisites. -On a technical level, using PSD2 APIs usually requires having an `EIDAS -`__ certificate. +On a technical level, using PSD2 APIs usually requires having an `EIDAS `__ certificate. Examples (bank offerings): * `Sparkasse `__ (Berlin Group based) -- cgit v1.2.3 From 3ddae00d055d892f1f3d5a839e0ca0761057b9b4 Mon Sep 17 00:00:00 2001 From: buckE Date: Wed, 24 Jun 2020 06:47:17 +0000 Subject: makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 1d515e27..7c23a880 100644 --- a/Makefile +++ b/Makefile @@ -61,7 +61,7 @@ diagrams: arch-api.png # remove all cached state first. html: diagrams # -W = exit 1 on warning; --keep-going = complete build anyway; write log to ~/warnings.log - $(SPHINXBUILD) -W --keep-going -w $(shell echo $HOME)/logs/sphinx-warnings.log -b html-linked $(ALLSPHINXOPTS) $(BUILDDIR)/html + $(SPHINXBUILD) -W --keep-going -w $(shell echo $HOME)/logs/sphinx-warnings.log -b html-linked $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." -- cgit v1.2.3 From aa11d1f76179333ef41879169fb2e4ff824b48e3 Mon Sep 17 00:00:00 2001 From: buckE Date: Wed, 24 Jun 2020 06:54:36 +0000 Subject: test commit --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 7c23a880..1d515e27 100644 --- a/Makefile +++ b/Makefile @@ -61,7 +61,7 @@ diagrams: arch-api.png # remove all cached state first. html: diagrams # -W = exit 1 on warning; --keep-going = complete build anyway; write log to ~/warnings.log - $(SPHINXBUILD) -W --keep-going -w $(shell echo $HOME)/logs/sphinx-warnings.log -b html-linked $(ALLSPHINXOPTS) $(BUILDDIR)/html + $(SPHINXBUILD) -W --keep-going -w $(shell echo $HOME)/logs/sphinx-warnings.log -b html-linked $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." -- cgit v1.2.3 From 9f5b5a7ed93a8f9f42260a524f17a02f6f1d8b66 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 24 Jun 2020 18:06:37 +0530 Subject: un-break doc generation --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 1d515e27..da61fa46 100644 --- a/Makefile +++ b/Makefile @@ -61,7 +61,7 @@ diagrams: arch-api.png # remove all cached state first. html: diagrams # -W = exit 1 on warning; --keep-going = complete build anyway; write log to ~/warnings.log - $(SPHINXBUILD) -W --keep-going -w $(shell echo $HOME)/logs/sphinx-warnings.log -b html-linked $(ALLSPHINXOPTS) $(BUILDDIR)/html + $(SPHINXBUILD) -W --keep-going -b html-linked $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." -- cgit v1.2.3 From e248817bfa27291c9104c7acd92e46f13fc6b52b Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 24 Jun 2020 18:08:25 +0530 Subject: docs --- libeufin/api-nexus.rst | 3 -- libeufin/iso20022.rst | 84 ++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 65 insertions(+), 22 deletions(-) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index d63fbd0b..9c752de1 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -327,9 +327,6 @@ to the real bank. Make a passphrase-encrypted backup of this connection. -.. - not implemented. - .. http:post:: {nexusBase}/bank-connections/{connid}/accounts/fetch Update accounts that are accessible via this bank connection. diff --git a/libeufin/iso20022.rst b/libeufin/iso20022.rst index bc9f5901..304bd0d8 100644 --- a/libeufin/iso20022.rst +++ b/libeufin/iso20022.rst @@ -7,35 +7,81 @@ validation subset) of the schema. Documentation for message fields can be viewed at https://www.iso20022.org/standardsrepository +The primary syntax for ISO 20022 messages is XML. To avoid LibEuFin clients +having to deal with XML, we define a mapping from ISO 20022 messages into JSON. + +The specifics of this mapping are: + + * The JSON should be "idiomatic" and easy to process + * When possible, the highly nested structures of ISO 20022 should be flattened + * It must be possible round-trip between the LibEuFin JSON and ISO 20022 + XML messages. The mapping of message types is not 1-to-1, as some ISO 20022 messages are + very similar and can be mapped to the same JSON structure. + * JSON-mapped messages are not explicitly versioned. Instead, changes + are made in a backwards-compatible way, possibly preserving old versions + of message elements in the same schema. + Cash Management (camt) ====================== -camt.052: Bank to Customer Account Report ------------------------------------------ +LibEuFin combines camt.052, camt.053 and camt.054, as they essentially +have the same structure and serve the same purpose: Reporting transactions +on a customer's bank account. + +.. code-block:: typescript + + interface CashManagementResponseMessage { + // ISO: MessageIdentification + messageId: string; + + messageType: "report" | "statement" | "notification"; + + // ISO: CreationDateTime + creationDateTime: string; + + entries: Entry[]; + + } + + interface Entry { + transactions: Transaction[]; + } + + interface Transaction { + creditDebitIndicator: "credit" | "debit"; + amount: string; + currency: string; + + bookingDate?: string; + valueDate?: string; -* pending and booked transaction + accountServicerRef?: string; -Schema versions: + bankTransactionCode: BankTransactionCode; -* GLS uses camt.052.001.02 + details: TransactionDetails[]; + } -.. code-block:: none + interface TransactionDetails { + creditDebitIndicator: "credit" | "debit"; + amount: string; + currency: string; - + Document/BkToCstmrAcctRpt - ++ GroupHeader [1..1] - ++ Report [1..*] - +++ Account [1..1] - +++ Balance [1..*] - +++ Entry [1..*] - ++++ Amount [1..1] - ++++ Status [1..1] - ++++ EntryDetails [1..1] + // Referenced message ID + messageId: string; + endToEndId: string; + paymentIdentificationId?: string; -camt.053: Bank to Customer Statement ------------------------------------- + bankTransactionCode: BankTransactionCode; + } -* only booked transactions -* only for the last day (?) + interface BankTransactionCode { + domain?: string; + family?: string; + subfamily?: string; + proprietaryIssuer?: string; + proprietaryCode?: string; + } -- cgit v1.2.3 From 5b4bd1812d40c3e40f4650774c034908fc9ee7ff Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 24 Jun 2020 18:11:30 +0530 Subject: squelch warning --- developers-manual.rst | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/developers-manual.rst b/developers-manual.rst index 6e0bc309..2f1fbfd8 100644 --- a/developers-manual.rst +++ b/developers-manual.rst @@ -1340,11 +1340,6 @@ use when talking to end users or even system administrators. a list of :term:`contract terms` that has been completed and signed by the merchant backend. - reserve - Funds set aside for future use; either the balance of a customer at the - exchange ready for withdrawal, or the funds kept in the exchange;s bank - account to cover obligations from coins in circulation. - refresh refreshing operation by which a :term:`dirty coin` is converted into one or more @@ -1371,6 +1366,10 @@ use when talking to end users or even system administrators. :term:`coins` from the reserve, thereby draining the reserve. If a reserve is not drained, the exchange eventually :term:`closes` it. + Other definition: Funds set aside for future use; either the balance of a customer at the + exchange ready for withdrawal, or the funds kept in the exchange;s bank + account to cover obligations from coins in circulation. + reveal revealing step in the :term:`refresh` protocol where some of the transfer private -- cgit v1.2.3 From 6dc6fb4fcba93f3bac3368ed0875205c043e3add Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 24 Jun 2020 21:33:58 +0530 Subject: more docs --- libeufin/api-nexus.rst | 80 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 51 insertions(+), 29 deletions(-) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index 9c752de1..6424e73f 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -1,6 +1,8 @@ Nexus API ########### +.. contents:: Table of Contents + HTTP API ======== @@ -13,8 +15,8 @@ basic auth* mechanism. Other authentication mechanisms (e.g. OpenID Connect) might be supported in the future. -Users Management ----------------- +User Management +--------------- .. http:get:: {nexusBase}/user @@ -64,8 +66,11 @@ Users Management Return list of users. -Bank Account Management ------------------------ +Bank Accounts +------------- + +The LibEuFin maintains a copy of the bank account transaction history and balance information, +manages payment initiations of the account and tracks the of payment initiations. .. http:get:: {nexusBase}/bank-accounts @@ -301,17 +306,20 @@ to the real bank. List available bank connections. -.. http:get:: {nexusBase}/bank-connections/{connid} +.. http:get:: {nexusBase}/bank-connections/{connId} Get information about one bank connection. .. ts:def:: BankConnectionInfo interface BankConnectionInfo { - name: string; + bankConnectionId: string; - connectionType: string; + bankConnectionType: string; + // Is this bank connection ready, or + // are we waiting for the bank to activate + // the connection? ready: boolean; // Did the user review the bank's keys? @@ -319,55 +327,69 @@ to the real bank. } -.. http:post:: {nexusBase}/bank-connections/{connid}/connect +.. http:post:: {nexusBase}/bank-connections/{connId}/connect Initialize the connection by talking to the bank. -.. http:post:: {nexusBase}/bank-connections/{connid}/export-backup +.. http:post:: {nexusBase}/bank-connections/{connId}/export-backup Make a passphrase-encrypted backup of this connection. -.. http:post:: {nexusBase}/bank-connections/{connid}/accounts/fetch +.. http:post:: {nexusBase}/bank-connections/{connId}/fetch-accounts Update accounts that are accessible via this bank connection. -.. http:get:: {nexusBase}/bank-connections/{connid}/accounts +.. http:get:: {nexusBase}/bank-connections/{connId}/accounts - List the bank accounts that are downloaded into this bank connection - but aren't imported yet: + List the bank accounts that this bank connection provides access to. - .. ts:def:: BankAccount + .. ts:def:: OfferedBankAccount - interface BankAccount { - - // iban + interface OfferedBankAccount { + + // Unique identifier for the offered account + offeredAccountId: string; + + // IBAN of the offered account iban: string; - // bic + // BIC of the account's financial institution bic: string; - // account holder - holder: string; + // Account owner name + ownerName: string; - // account label as given by the bank + // Account label as given by the bank account: string; + + // If the accoun thas been imported, + // this field contains the ID of the + // Nexus bank account associated with it. + nexusBankAccountId: string | null; } -.. http:post:: {nexusBase}/bank-connections/{connid}/accounts/import +.. http:post:: {nexusBase}/bank-connections/{connId}/import-account + + Import a bank account provided by the connection into the Nexus. + + If no Nexus bank account with the ID ``nexusBankAccountId`` exists, + a new one will be created, and it will have ``connId`` as the + default bank connection. - Import one bank account, allowing the user to name it. + If an existing Nexus bank account with the same ID already exists, + this connection will be added as an available connection for it. + This only succeeds if the bank account has the same IBAN. .. ts:def:: ImportBankAccount interface ImportBankAccount { - // alphanumeric identifier given by the bank to - // the bank account to import. - accountId: string; + // Identifier for the bank account, as returned by /accounts + // of the bank connection. + offeredAccountId: string; - // alphanumeric name chosen by the user to identify - // locally such imported bank account. - localName: string; + // Nexus-local identifier for the bank account. + nexusBankAccountId: string; } Facades -- cgit v1.2.3 From 73a91d2a6180ad39d03bfbf773c369a18295aaf1 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 24 Jun 2020 19:06:31 +0200 Subject: add man page for taler-merchant-setup-reserve --- conf.py | 3 ++ manpages/taler-merchant-setup-reserve.1.rst | 76 +++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 manpages/taler-merchant-setup-reserve.1.rst diff --git a/conf.py b/conf.py index 9fd6009b..c7c1666b 100644 --- a/conf.py +++ b/conf.py @@ -316,6 +316,9 @@ man_pages = [ ("manpages/taler-merchant-httpd.1", "taler-merchant-httpd", "run Taler merchant backend (with RESTful API)", "GNU Taler contributors", 1), + ("manpages/taler-merchant-setup-reserve.1", "taler-merchant-setup-reserve", + "setup reserve for tipping at a Taler merchant backend", "GNU Taler contributors", + 1), ("manpages/taler.conf.5", "taler.conf", "Taler configuration file", "GNU Taler contributors", 5), ] diff --git a/manpages/taler-merchant-setup-reserve.1.rst b/manpages/taler-merchant-setup-reserve.1.rst new file mode 100644 index 00000000..485f769b --- /dev/null +++ b/manpages/taler-merchant-setup-reserve.1.rst @@ -0,0 +1,76 @@ +taler-merchant-setup-reserve(1) +############################### + + +.. only:: html + + Name + ==== + + **taler-merchant-setup-reserve** - setup reserve for tipping + + +Synopsis +======== + +**taler-merchant-setup-reserve** [*options*] + + +Description +=========== + +**taler-merchant-setup-reserve** is a command line tool to setup a reserve +(creating the private reserve key) and obtaining the wire transfer information +from the exchange needed to fill the reserve. + + +Options +======= + +-a VALUE, --amount=VALUE + Amount to be transferred to the reserve. Mandatory. + +-e URL, --exchange-url=URL + Use URL for the exchange base URL. This is the exchange where + the reserve will be created. The currency used in the amount + specificiation must be offered by this exchange. Mandatory. + +-m URL, --merchant-url=URL + Use URL as the merchant base URL. Should include the path to + the instance if the reserve is to be created for a non-default instance. + Mandatory. + +-w METHOD, --wire-method=METHOD + Which wire method should be used. Needed to select the wire + transfer method of the exchange. The method must be supported + by the exchange. Typical values would be "iban" or "x-taler-bank". + Mandatory. + +-c FILENAME, --config=FILENAME + Use the configuration and other resources for the merchant to + operate from FILENAME. + +-h, --help + Print short help on options. + +-v, --version + Print version information. + +-l LF, --logfile=LF + Sends logs to file whose path is LF. + +-L LOGLEVEL, --log=LOGLEVEL + Use loglevel LOGLEVEL. + + +Bugs +==== + +Report bugs by using https://bugs.taler.net/ or by sending electronic +mail to . + + +See Also +======== + +taler-merchant-dbinit(1), taler.conf(5) -- cgit v1.2.3 From 4c8e4a88a75db50b58b4eaf20dee04e99c4bd86a Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 24 Jun 2020 19:41:54 +0200 Subject: remove outdated merchant documentation, remark where more is needed --- conf.py | 6 +- fdl-1.3.rst | 26 +-- taler-merchant-api-tutorial.rst | 5 +- taler-merchant-manual.rst | 439 ++++++++++++++-------------------------- 4 files changed, 173 insertions(+), 303 deletions(-) diff --git a/conf.py b/conf.py index c7c1666b..64ce8c47 100644 --- a/conf.py +++ b/conf.py @@ -77,16 +77,16 @@ master_doc = 'index' # General information about the project. project = u'GNU Taler' -copyright = u'2014, 2015, 2016 Florian Dold, Benedikt Muller, Sree Harsha Totakura, Christian Grothoff, Marcello Stanisci (GPLv3+ or GFDL 1.3+)' +copyright = u'2014-2020 Taler Systems SA (GPLv3+ or GFDL 1.3+)' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = '0.6pre1' +version = '0.8pre0' # The full version, including alpha/beta/rc tags. -release = '0.6.0pre1' +release = '0.8.0pre0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/fdl-1.3.rst b/fdl-1.3.rst index 6dec4945..49bf2d3e 100644 --- a/fdl-1.3.rst +++ b/fdl-1.3.rst @@ -12,7 +12,7 @@ Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. 0. PREAMBLE -^^^^^^^^^^^ +----------- The purpose of this License is to make a manual, textbook, or other functional and useful document “free” in the sense of freedom: to assure @@ -36,7 +36,7 @@ published as a printed book. We recommend this License principally for works whose purpose is instruction or reference. 1. APPLICABILITY AND DEFINITIONS -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +-------------------------------- This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be @@ -124,7 +124,7 @@ these Warranty Disclaimers may have is void and has no effect on the meaning of this License. 2. VERBATIM COPYING -^^^^^^^^^^^^^^^^^^^ +------------------- You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the @@ -140,7 +140,7 @@ You may also lend copies, under the same conditions stated above, and you may publicly display copies. 3. COPYING IN QUANTITY -^^^^^^^^^^^^^^^^^^^^^^ +---------------------- If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the @@ -178,7 +178,7 @@ Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document. 4. MODIFICATIONS -^^^^^^^^^^^^^^^^ +---------------- You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the @@ -264,7 +264,7 @@ give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version. 5. COMBINING DOCUMENTS -^^^^^^^^^^^^^^^^^^^^^^ +---------------------- You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified @@ -289,7 +289,7 @@ sections Entitled “Dedications”. You must delete all sections Entitled “Endorsements”. 6. COLLECTIONS OF DOCUMENTS -^^^^^^^^^^^^^^^^^^^^^^^^^^^ +--------------------------- You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this @@ -303,7 +303,7 @@ License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document. 7. AGGREGATION WITH INDEPENDENT WORKS -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +------------------------------------- A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or @@ -322,7 +322,7 @@ equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the whole aggregate. 8. TRANSLATION -^^^^^^^^^^^^^^ +-------------- Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing @@ -342,7 +342,7 @@ If a section in the Document is Entitled “Acknowledgements”, Title (section 1) will typically require changing the actual title. 9. TERMINATION -^^^^^^^^^^^^^^ +-------------- You may not copy, modify, sublicense, or distribute the Document except as expressly provided under this License. Any attempt otherwise to copy, @@ -370,7 +370,7 @@ reinstated, receipt of a copy of some or all of the same material does not give you any rights to use it. 10. FUTURE REVISIONS OF THIS LICENSE -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +------------------------------------ The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will @@ -390,7 +390,7 @@ used, that proxy’s public statement of acceptance of a version permanently authorizes you to choose that version for the Document. 11. RELICENSING -^^^^^^^^^^^^^^^ +--------------- “Massive Multiauthor Collaboration Site” (or “MMC Site”) means any World Wide Web server that publishes copyrightable works and also provides @@ -419,7 +419,7 @@ under CC-BY-SA on the same site at any time before August 1, 2009, provided the MMC is eligible for relicensing. ADDENDUM: How to use this License for your documents -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +---------------------------------------------------- To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license diff --git a/taler-merchant-api-tutorial.rst b/taler-merchant-api-tutorial.rst index f97f96c1..6442e7c2 100644 --- a/taler-merchant-api-tutorial.rst +++ b/taler-merchant-api-tutorial.rst @@ -66,7 +66,7 @@ components: The following image illustrates the various interactions of these key components: -|image0| +.. image:: arch-api.png The backend provides the cryptographic protocol support, stores Taler-specific financial information and communicates with the GNU Taler @@ -736,6 +736,3 @@ locations and they is also allowed to have additional fields. Contract renderers must render at least the fields listed above, and should render fields that they do not understand as a key-value list. - - -.. |image0| image:: arch-api.png diff --git a/taler-merchant-manual.rst b/taler-merchant-manual.rst index dfa6492e..8fcb487e 100644 --- a/taler-merchant-manual.rst +++ b/taler-merchant-manual.rst @@ -50,8 +50,8 @@ operating a basic backend. Architecture overview --------------------- -:keywords: crypto-currency -:keywords: KUDOS +.. index:: crypto-currency +.. index:: KUDOS Taler is a pure payment system, not a new crypto-currency. As such, it operates in a traditional banking context. In particular, this means @@ -60,33 +60,31 @@ regular bank account, and payments can be executed in ordinary currencies such as USD or EUR. For testing purposes, Taler uses a special currency “KUDOS” and includes its own special bank. +.. index:: frontend +.. index:: back office +.. index:: backend +.. index:: DBMS +.. index:: Postgres + The Taler software stack for a merchant consists of four main components: -- frontend - A frontend which interacts with the customer’s browser. The frontend +- A frontend which interacts with the customer’s browser. The frontend enables the customer to build a shopping cart and place an order. Upon payment, it triggers the respective business logic to satisfy the order. This component is not included with Taler, but rather assumed to exist at the merchant. This manual describes how to integrate Taler with Web shop frontends. - -- back office - A back office application that enables the shop operators to view +- A back office application that enables the shop operators to view customer orders, match them to financial transfers, and possibly approve refunds if an order cannot be satisfied. This component is again not included with Taler, but rather assumed to exist at the merchant. This manual will describe how to integrate such a component to handle payments managed by Taler. - -- backend - A Taler-specific payment backend which makes it easy for the frontend +- A Taler-specific payment backend which makes it easy for the frontend to process financial transactions with Taler. The next two chapters will describe how to install and configure this backend. - -- DBMS - Postgres - A DBMS which stores the transaction history for the Taler backend. +- A DBMS which stores the transaction history for the Taler backend. For now, the GNU Taler reference implemenation only supports Postgres, but the code could be easily extended to support another DBMS. @@ -94,11 +92,10 @@ components: The following image illustrates the various interactions of these key components: -:: +.. image:: arch-api.png - Missing diagram image +.. index:: RESTful -RESTful Basically, the backend provides the cryptographic protocol support, stores Taler-specific financial information in a DBMS and communicates with the GNU Taler exchange over the Internet. The frontend accesses the @@ -128,7 +125,7 @@ system. .. _Installation-of-dependencies: Installation of dependencies -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The following packages need to be installed before we can compile the backend: @@ -173,9 +170,9 @@ the libgnunetutil and GNU Taler exchange dependencies. .. _Installing-libgnunetutil: Installing libgnunetutil -~~~~~~~~~~~~~~~~~~~~~~~~ +^^^^^^^^^^^^^^^^^^^^^^^^ -:keywords: GNUnet +.. index:: GNUnet Before you install libgnunetutil, you must download and install the dependencies mentioned in the previous section, otherwise the build may @@ -200,9 +197,9 @@ which requires you to run the last step as ``root``. .. _Installing-the-GNU-Taler-exchange: Installing the GNU Taler exchange -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -:keywords: exchange +.. index:: exchange After installing GNUnet, you can download and install the exchange as follows: @@ -227,9 +224,9 @@ installed GNUnet to ``/usr/local`` in the previous step. .. _Installing-the-GNU-Taler-merchant-backend: Installing the GNU Taler merchant backend -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -:keywords: backend +.. index:: backend The following steps assume all dependencies are installed. @@ -257,8 +254,8 @@ GNUnet to ``/usr/local`` in the previous steps. Installing Taler on Debian GNU/Linux ------------------------------------ -:keywords: Wheezy -:keywords: Debian +.. index:: Wheezy +.. index:: Debian Debian wheezy is too old and lacks most of the packages required. @@ -318,8 +315,8 @@ if you used the Debian wheezy instructions above, you need to pass How to configure the merchant’s backend ======================================= -:keywords: taler-config -:keywords: taler.conf +.. index:: taler-config +.. index:: taler.conf The installation already provides reasonable defaults for most of the configuration options. However, some must be provided, in particular the @@ -336,22 +333,33 @@ see `Using taler-config <#Using-taler_002dconfig>`__. Backend options --------------- +.. index:: DBMS +.. index:: Postgres +.. index:: UNIX domain socket +.. index:: TCP +.. index:: port +.. index:: currency +.. index:: KUDOS +.. index:: exchange +.. index:: instance +.. index:: wire format + The following table describes the options that commonly need to be modified. Here, the notation ``[$section]/$option`` denotes the option ``$option`` under the section ``[$section]`` in the configuration file. + Service address - The following option sets the transport layer address used by the - merchant backend: +^^^^^^^^^^^^^^^ -:keywords: UNIX domain socket -:keywords: TCP +The following option sets the transport layer address used by the +merchant backend: :: [MERCHANT]/SERVE = TCP | UNIX - If given, +If given, - ``TCP``, then we need to set the TCP port in ``[MERCHANT]/PORT`` @@ -360,13 +368,12 @@ Service address latter takes the usual permission mask given as a number, e.g. 660 for user/group read-write access. - The frontend can then connect to the backend over HTTP using the - specified address. If frontend and backend run within the same - operating system, the use of a UNIX domain socket is recommended to - avoid accidentally exposing the backend to the network. +The frontend can then connect to the backend over HTTP using the specified +address. If frontend and backend run within the same operating system, the +use of a UNIX domain socket is recommended to avoid accidentally exposing +the backend to the network. -:keywords: port - To run the Taler backend on TCP port 8888, use: +To run the Taler backend on TCP port 8888, use: :: @@ -374,70 +381,68 @@ Service address $ taler-config -s MERCHANT -o PORT -V 8888 Currency - Which currency the Web shop deals in, i.e. “EUR” or “USD”, is - specified using the option +^^^^^^^^ + +Which currency the Web shop deals in, i.e. “EUR” or “USD”, is +specified using the option -:keywords: currency -:keywords: KUDOS :: [TALER]/CURRENCY - For testing purposes, the currency MUST match “KUDOS” so that tests - will work with the Taler demonstration exchange at - https://exchange.demo.taler.net/: +For testing purposes, the currency MUST match “KUDOS” so that tests +will work with the Taler demonstration exchange at +https://exchange.demo.taler.net/: :: $ taler-config -s TALER -o CURRENCY -V KUDOS Database -:keywords: DBMS +^^^^^^^^ - In principle is possible for the backend to support different DBMSs. - The option +In principle is possible for the backend to support different DBMSs. +The option :: [MERCHANT]/DB - specifies which DBMS is to be used. However, currently only the value - "postgres" is supported. This is also the default. +specifies which DBMS is to be used. However, currently only the value +"postgres" is supported. This is also the default. - In addition to selecting the DBMS software, the backend requires - DBMS-specific options to access the database. +In addition to selecting the DBMS software, the backend requires +DBMS-specific options to access the database. - For postgres, you need to provide: +For postgres, you need to provide: :: [merchantdb-postgres]/config -:keywords: Postgres - - This option specifies a postgres access path using the format - ``postgres:///$DBNAME``, where ``$DBNAME`` is the name of the - Postgres database you want to use. Suppose ``$USER`` is the name of - the user who will run the backend process. Then, you need to first - run +This option specifies a postgres access path using the format +``postgres:///$DBNAME``, where ``$DBNAME`` is the name of the +Postgres database you want to use. Suppose ``$USER`` is the name of +the user who will run the backend process. Then, you need to first +run :: $ sudu -u postgres createuser -d $USER - as the Postgres database administrator (usually ``postgres``) to - grant ``$USER`` the ability to create new databases. Next, you should - as ``$USER`` run: +as the Postgres database administrator (usually ``postgres``) to +grant ``$USER`` the ability to create new databases. Next, you should +as ``$USER`` run: :: $ createdb $DBNAME - to create the backend’s database. Here, ``$DBNAME`` must match the - database name given in the configuration file. +to create the backend’s database. Here, ``$DBNAME`` must match the +database name given in the configuration file. - To configure the Taler backend to use this database, run: +To configure the Taler backend to use this database, run: :: @@ -445,11 +450,11 @@ Database -V postgres:///$DBNAME Exchange -:keywords: exchange +^^^^^^^^ - To add an exchange to the list of trusted payment service providers, - you create a section with a name that starts with “exchange-”. In - that section, the following options need to be configured: +To add an exchange to the list of trusted payment service providers, +you create a section with a name that starts with “exchange-”. In +that section, the following options need to be configured: - The “url” option specifies the exchange’s base URL. For example, to use the Taler demonstrator use: @@ -468,92 +473,28 @@ Exchange $ taler-config -s EXCHANGE-demo -o master_key \ -V CQQZ9DY3MZ1ARMN5K1VKDETS04Y2QCKMMCFHZSWJWWVN82BTTH00 - Note that multiple exchanges can be added to the system by using - different tokens in place of ``demo`` in the example above. Note - that all of the exchanges must use the same currency. If you need - to support multiple currencies, you need to configure a backend - per currency. +Note that multiple exchanges can be added to the system by using +different tokens in place of ``demo`` in the example above. Note +that all of the exchanges must use the same currency. If you need +to support multiple currencies, you need to configure a backend +per currency. -Instances -:keywords: instance - The backend allows the user to run multiple instances of shops with - distinct business entities against a single backend. Each instance - uses its own bank accounts and key for signing contracts. It is - mandatory to configure a "default" instance. - - The “KEYFILE” option specifies the file containing the instance’s - private signing key. For example, use: +Auditor +^^^^^^^ - :: +FIXME: document here how to add an auditor to the list of +trusted auditors! - $ taler-config -s INSTANCE-default -o KEYFILE \ - -V '${TALER_CONFIG_HOME}/merchant/instace/default.key' - - The “NAME” option specifies a human-readable name for the - instance. For example, use: - - :: - - $ taler-config -s INSTANCE-default -o NAME \ - -V 'Kudos Inc.' - - - The optional “TIP_EXCHANGE” and “TIP_EXCHANGE_PRIV_FILENAME” - options are discussed in Tipping visitors - -Accounts -:keywords: wire format - - In order to receive payments, the merchant backend needs to - communicate bank account details to the exchange. For this, the - configuration must include one or more sections named “ACCOUNT-name” - where ``name`` can be replaced by some human-readable word - identifying the account. For each section, the following options - should be provided: - - - The “URL” option specifies a ``payto://``-URL for the account of - the merchant. For example, use: - - :: - - $ taler-config -s ACCOUNT-bank -o NAME \ - -V 'payto://x-taler-bank/bank.demo.taler.net/4' - - - The “WIRE_RESPONSE” option specifies where Taler should store the - (salted) JSON encoding of the wire account. The file given will be - created if it does not exist. For example, use: - - :: - - $ taler-config -s ACCOUNT-bank -o WIRE_RESPONSE \ - -V '{$TALER_CONFIG_HOME}/merchant/bank.json' - - - For each ``instance`` that should use this account, you should set - ``HONOR_instance`` and ``ACTIVE_instance`` to YES. The first - option will cause the instance to accept payments to the account - (for existing contracts), while the second will cause the backend - to include the account as a possible option for new contracts. - - For example, use: - - :: - - $ taler-config -s ACCOUNT-bank -o HONOR_default \ - -V YES - $ taler-config -s ACCOUNT-bank -o ACTIVE_default \ - -V YES - - to use “account-bank” for the “default” instance. - - Note that additional instances can be specified using different - tokens in the section name instead of ``default``. .. _Sample-backend-configuration: Sample backend configuration ---------------------------- -:keywords: configuration +.. index:: configuration The following is an example for a complete backend configuration: @@ -570,24 +511,14 @@ The following is an example for a complete backend configuration: [MERCHANTDB-postgres] CONFIG = postgres:///donations - [INSTANCE-default] - KEYFILE = $DATADIR/key.priv - NAME = "Kudos Inc." - - [ACCOUNT-bank] - URL = payto://x-taler-bank/bank.demo.taler.net/4 - WIRE_RESPONSE = $DATADIR/bank.json - HONOR_default = YES - ACTIVE_default = YES - TALER_BANK_AUTH_METHOD = basic - USERNAME = my_user - PASSWORD = 1234pass - [merchant-exchange-trusted] + # FIXME: check this is up-to-date! EXCHANGE_BASE_URL = https://exchange.demo.taler.net/ MASTER_KEY = CQQZ9DY3MZ1ARMN5K1VKDETS04Y2QCKMMCFHZSWJWWVN82BTTH00 CURRENCY = KUDOS + [FIXME: add example for AUDITOR!] + Given the above configuration, the backend will use a database named ``donations`` within Postgres. @@ -604,8 +535,8 @@ them. Launching the backend --------------------- -:keywords: backend -:keywords: taler-merchant-httpd +.. index:: backend +.. index:: taler-merchant-httpd Assuming you have configured everything correctly, you can launch the merchant backend using: @@ -632,6 +563,37 @@ Please note that your backend is right now likely globally reachable. Production systems should be configured to bind to a UNIX domain socket or properly restrict access to the port. +.. _Instances: + +Instances +========= + +The backend allows the user to run multiple instances of shops with +distinct business entities against a single backend. Each instance +uses its own bank accounts and key for signing contracts. It is +mandatory to configure at least the "default" instance. + +Instances can be configured by POSTing the necessary requests to the +backend (possibly via a Web interface -- once we implement that). + +FIXME: more details on how to setup instances here! + + +Accounts +-------- + +The main configuration data that must be provided for each instance +is the bank account information. + +In order to receive payments, the merchant backend needs to +communicate bank account details to the exchange. + +The bank account information is provided in the form of +a ``payto://``-URL. + +FIXME: more details on how to setup accounts here! + + .. _Testing: Testing @@ -683,7 +645,7 @@ Run the test in the following way: $ taler-merchant-generate-payments [-c config] [-e EURL] [-m MURL] The argument ``config`` given to ``-c`` points to the configuration file -and is optional – ``~/.config/taler.conf`` will be checked by default. +and is optional – ``^/.config/taler.conf`` will be checked by default. By default, the tool forks two processes: one for the merchant backend, and one for the exchange. The option ``-e`` (``-m``) avoids any exchange (merchant backend) fork, and just runs the generator against the @@ -745,7 +707,7 @@ Advanced topics Configuration format -------------------- -:keywords: configuration +.. index:: configuration In Taler realm, any component obeys to the same pattern to get configuration values. According to this pattern, once the component has @@ -819,7 +781,7 @@ configuration file used in our demos. See under ``deployment/config``. Using taler-config ------------------ -:keywords: taler-config +.. index:: taler-config The tool ``taler-config`` can be used to extract or manipulate configuration values; however, the configuration use the well-known INI @@ -859,42 +821,22 @@ compare: :: - $ taler-config -s ACCOUNT-bank \ - -o WIRE_RESPONSE - $ taler-config -f -s ACCOUNT-bank \ - -o WIRE_RESPONSE + $ taler-config -s PATHS \ + -o TALER_DATA_HOME + $ taler-config -f -s PATHS \ + -o TALER_DATA_HOME While the configuration file is typically located at ``$HOME/.config/taler.conf``, an alternative location can be specified to ``taler-merchant-httpd`` and ``taler-config`` using the ``-c`` option. -.. _Merchant-key-management: - -Merchant key management ------------------------ - -:keywords: merchant key -:keywords: KEYFILE - -The option “KEYFILE” in the section “INSTANCE-default” specifies the -path to the instance’s private key. You do not need to create a key -manually, the backend will generate it automatically if it is missing. -While generally unnecessary, it is possible to display the corresponding -public key using the ``gnunet-ecc`` command-line tool: - -:: - - $ gnunet-ecc -p \ - $(taler-config -f -s INSTANCE-default \ - -o KEYFILE) - .. _Tipping-visitors: Tipping visitors ---------------- -:keywords: tipping +.. index:: tipping Taler can also be used to tip Web site visitors. For example, you may be running an online survey, and you want to reward those people that have @@ -904,118 +846,48 @@ how to setup the Taler merchant backend for tipping. There are four basic steps that must happen to tip a visitor. -.. _Configure-a-reserve-and-exchange-for-tipping: - -Configure a reserve and exchange for tipping -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:keywords: gnunet-ecc -:keywords: reserve key - -To tip users, you first need to create a reserve. A reserve is a pool of -money held in escrow at the Taler exchange. This is the source of the -funds for the tips. Tipping will fail (resulting in disappointed -visitors) if you do not have enough funds in your reserve! - -First, we configure the backend. You need to enable tipping for each -instance separately, or you can use an instance only for tipping. To -configure the “default” instance for tipping, use the following -configuration: - -:: - - [INSTANCE-default] - # this is NOT the tip.priv - KEYFILE = signing_key.priv - # replace the URL with the URL of the exchange you will use - TIP_EXCHANGE = https://exchange:443/ - # here put the path to the file created with "gnunet-ecc -g1 tip.priv" - TIP_RESERVE_PRIV_FILENAME = tip.priv - -Note that the KEYFILE option should have already been present for the -instance. It has nothing to do with the “tip.priv” file we created -above, and you should probably use a different file here. - -Instead of manually editing the configuration, you could also run: - -:: - - $ taler-config -s INSTANCE-default \ - -o TIP_RESERVE_PRIV_FILENAME \ - -V tip.priv - $ taler-config -s INSTANCE-default \ - -o TIP_EXCHANGE \ - -V https://exchange:443/ - -Next, to create the ``TIP_RESERVE_PRIV_FILENAME`` file, use: - -:: - - $ gnunet-ecc -g 1 \ - $(taler-config -f -s INSTANCE-default \ - -o TIP-RESERVE_PRIV_FILENAME) - -This will create a file with the private key that will be used to -identify the reserve. You need to do this once for each instance that is -configured to tip. - -Now you can (re)start the backend with the new configuration. +FIXME: write current explanation! .. _Fund-the-reserve: Fund the reserve -~~~~~~~~~~~~~~~~ - -:keywords: reserve -:keywords: close +^^^^^^^^^^^^^^^^ -To fund the reserve, you must first extract the public key from -“tip.priv”: +.. index:: reserve +.. index:: close -:: - - $ gnunet-ecc --print-public-key \ - $(taler-config -f -s INSTANCE-default \ - -o TIP-RESERVE_PRIV_FILENAME) - -In our example, the output for the public key is: +In our example, the output for the wire transfer subject is: :: QPE24X8PBX3BZ6E7GQ5VAVHV32FWTTCADR0TRQ183MSSJD2CHNEG You now need to make a wire transfer to the exchange’s bank account -using the public key as the wire transfer subject. The exchange’s bank -account details can be found in JSON format at -“https://exchange:443//wire/METHOD” where METHOD is the respective wire -method (i.e. “sepa”). Depending on the exchange’s operator, you may also -be able to find the bank details in a human-readable format on the main -page of the exchange. +using the public key as the wire transfer subject. Make your wire transfer and (optionally) check at -“https://exchange:443/reserve/status/reserve_pub=QPE24X...” whether your -transfer has arrived at the exchange. +“https://exchange/reserves/QPE24X...” whether your transfer has arrived at the +exchange. Once the funds have arrived, you can start to use the reserve for tipping. -Note that an exchange will typically close a reserve after four weeks, -wiring all remaining funds back to the sender’s account. Thus, you -should plan to wire funds corresponding to a campaign of about two weeks -to the exchange initially. If your campaign runs longer, you should wire -further funds to the reserve every other week to prevent it from -expiring. +Note that an exchange will typically close a reserve after four weeks, wiring +all remaining funds back to the sender’s account. Thus, you should plan to +wire funds corresponding to a campaign of about two weeks to the exchange +initially. If your campaign runs longer, you should setup another reserve +every other week to ensure one is always ready. .. _Authorize-a-tip: Authorize a tip -~~~~~~~~~~~~~~~ +^^^^^^^^^^^^^^^ -When your frontend has reached the point where a client is supposed to -receive a tip, it needs to first authorize the tip. For this, the -frontend must use the “/tip-authorize” API of the backend. To authorize -a tip, the frontend has to provide the following information in the body -of the POST request: +When your frontend has reached the point where a client is supposed to receive +a tip, it needs to first authorize the tip. For this, the frontend must use +the “/private/reserves/$RID/tip-authorize” API of the backend. To authorize a +tip, the frontend has to provide the following information in the body of the +POST request: - The amount of the tip @@ -1040,18 +912,19 @@ missconfigured instances or a lack of remaining funds for tipping. .. _Picking-up-of-the-tip: Picking up of the tip -~~~~~~~~~~~~~~~~~~~~~ +^^^^^^^^^^^^^^^^^^^^^ -The wallet will POST a JSON object to the shop’s “/tip-pickup” handler. +The wallet will POST a JSON object to the shop’s “/tips/$TIP/pickup” handler. The frontend must then forward this request to the backend. The response generated by the backend can then be forwarded directly to the wallet. -.. _Generate-payments: +.. _Benchmarking: -Generate payments ------------------ +Benchmarking +------------ + +.. index:: testing database -testing database The merchant codebase offers the ``taler-merchant-benchmark`` tool to populate the database with fake payments. This tool is in charge of starting a merchant, exchange, and bank processes, and provide them all -- cgit v1.2.3 From cd10263cc144e7a3987f70b7b02d7c980a87b058 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 24 Jun 2020 20:46:02 +0200 Subject: specify current merchant configuration --- taler-merchant-manual.rst | 308 +++++++++++++++++++++++++++------------------- 1 file changed, 182 insertions(+), 126 deletions(-) diff --git a/taler-merchant-manual.rst b/taler-merchant-manual.rst index 8fcb487e..f8515c0a 100644 --- a/taler-merchant-manual.rst +++ b/taler-merchant-manual.rst @@ -312,6 +312,7 @@ instructions starting with the installation of libgnunetutil. Note that if you used the Debian wheezy instructions above, you need to pass ``--with-microhttpd=/usr/local/`` to all ``configure`` invocations. + How to configure the merchant’s backend ======================================= @@ -386,7 +387,6 @@ Currency Which currency the Web shop deals in, i.e. “EUR” or “USD”, is specified using the option - :: [TALER]/CURRENCY @@ -449,45 +449,92 @@ To configure the Taler backend to use this database, run: $ taler-config -s MERCHANTDB-postgres -o CONFIG \ -V postgres:///$DBNAME +.. index: MASTER_KEY + Exchange ^^^^^^^^ -To add an exchange to the list of trusted payment service providers, -you create a section with a name that starts with “exchange-”. In -that section, the following options need to be configured: +To add an exchange to the list of trusted payment service providers, you +create a section with a name that starts with “MERCHANT-EXCHANGE-”. In that +section, the following options need to be configured: - - The “url” option specifies the exchange’s base URL. For example, - to use the Taler demonstrator use: + - The “EXCHANGE_BASE_URL” option specifies the exchange’s base URL. For example, + to use the Taler demonstrator, specify: :: - $ taler-config -s EXCHANGE-demo -o URL \ + $ taler-config -s MERCHANT-EXCHANGE-demo \ + -o EXCHANGE_BASE_URL \ -V https://exchange.demo.taler.net/ - - master key - The “master_key” option specifies the exchange’s master public key + - The “MASTER_KEY” option specifies the exchange’s master public key in base32 encoding. For the Taler demonstrator, use: :: - $ taler-config -s EXCHANGE-demo -o master_key \ + $ taler-config -s MERCHANT-EXCHANGE-demo \ + -o MASTER_KEY \ -V CQQZ9DY3MZ1ARMN5K1VKDETS04Y2QCKMMCFHZSWJWWVN82BTTH00 -Note that multiple exchanges can be added to the system by using -different tokens in place of ``demo`` in the example above. Note -that all of the exchanges must use the same currency. If you need -to support multiple currencies, you need to configure a backend -per currency. + - The “CURRENCY” option specifies the exchange’s currency. + For the Taler demonstrator, use: + + :: + + $ taler-config -s MERCHANT-EXCHANGE-demo \ + -o CURRENCY \ + -V KUDOS + +Note that multiple exchanges can be added to the system by using different +tokens in place of ``demo`` in the example above. Note that all of the +exchanges must use the same currency: If the currency does not match the main +currency from the "TALER" section, the exchange is ignored. If you need to +support multiple currencies, you need to configure a backend per currency. Auditor ^^^^^^^ -FIXME: document here how to add an auditor to the list of -trusted auditors! +To add an auditor to the list of trusted auditors (which implies +that all exchanges audited by this auditor will be trusted!) +you create a section with a name that starts with “MERCHANT-AUDITOR-”. In +that section, the following options need to be configured: + + - The “AUDITOR_BASE_URL” option specifies the auditor’s base URL. For example, + to use the Taler demonstrator's auditor, specify: + + :: + + $ taler-config -s MERCHANT-AUDITOR-demo \ + -o AUDITOR_BASE_URL \ + -V https://exchange.demo.taler.net/ + + - The “AUDITOR_KEY” option specifies the auditor's public key + in base32 encoding. For the Taler demonstrator, use: + + :: + + $ taler-config -s MERCHANT-AUDITOR-demo \ + -o AUDITOR_KEY \ + -V FIXMEBADVALUENEEDTOGETTHERIGHTVALUEHEREEVENTUALLY000 + + - The “CURRENCY” option specifies the auditor’s currency. + For the Taler demonstrator, use: + + :: + + $ taler-config -s MERCHANT-AUDITOR-demo \ + -o CURRENCY \ + -V KUDOS +Note that multiple auditors can be added to the system by using different +tokens in place of ``demo`` in the example above. Note that all of the +auditors must use the same currency: If the currency does not match the main +currency from the "TALER" section, the auditor is ignored. If you need to +support multiple currencies, you need to configure a backend per currency. + .. _Sample-backend-configuration: @@ -511,13 +558,19 @@ The following is an example for a complete backend configuration: [MERCHANTDB-postgres] CONFIG = postgres:///donations - [merchant-exchange-trusted] - # FIXME: check this is up-to-date! + [merchant-exchange-NAME] EXCHANGE_BASE_URL = https://exchange.demo.taler.net/ MASTER_KEY = CQQZ9DY3MZ1ARMN5K1VKDETS04Y2QCKMMCFHZSWJWWVN82BTTH00 + # If currency does not match [TALER] section, the exchange + # will be ignored! CURRENCY = KUDOS - [FIXME: add example for AUDITOR!] + [merchant-auditor-NAME] + AUDITOR_BASE_URL = https://auditor.demo.taler.net/ + AUDITOR_KEY = DSDASDXAMDAARMNAD53ZA4AFAHA2QADAMAHHASWDAWXN84SDAA11 + # If currency does not match [TALER] section, the auditor + # will be ignored! + CURRENCY = KUDOS Given the above configuration, the backend will use a database named ``donations`` within Postgres. @@ -594,112 +647,6 @@ a ``payto://``-URL. FIXME: more details on how to setup accounts here! -.. _Testing: - -Testing -======= - -The tool ``taler-merchant-generate-payments`` can be used to test the -merchant backend installation. It implements all the payment’s steps in -a programmatically way, relying on the backend you give it as input. -Note that this tool gets installed along all the merchant backend’s -binaries. - -This tool gets configured by a config file, that must have the following -layout: - -:: - - [PAYMENTS-GENERATOR] - - # The exchange used during the test: make sure the merchant backend - # being tested accpets this exchange. - # If the sysadmin wants, she can also install a local exchange - # and test against it. - EXCHANGE = https://exchange.demo.taler.net/ - - # This value must indicate some URL where the backend - # to be tested is listening; it doesn't have to be the - # "official" one, though. - MERCHANT = http://localbackend/ - - # This value is used when the tool tries to withdraw coins, - # and must match the bank used by the exchange. If the test is - # done against the exchange at https://exchange.demo.taler.net/, - # then this value can be "https://bank.demo.taler.net/". - BANK = https://bank.demo.taler.net/ - - # The merchant instance in charge of serving the payment. - # Make sure this instance has a bank account at the same bank - # indicated by the 'bank' option above. - INSTANCE = default - - # The currency used during the test. Must match the one used - # by merchant backend and exchange. - CURRENCY = KUDOS - -Run the test in the following way: - -:: - - $ taler-merchant-generate-payments [-c config] [-e EURL] [-m MURL] - -The argument ``config`` given to ``-c`` points to the configuration file -and is optional – ``^/.config/taler.conf`` will be checked by default. -By default, the tool forks two processes: one for the merchant backend, -and one for the exchange. The option ``-e`` (``-m``) avoids any exchange -(merchant backend) fork, and just runs the generator against the -exchange (merchant backend) running at ``EURL`` (``MURL``). - -Please NOTE that the generator contains *hardcoded* values, as for -deposit fees of the coins it uses. In order to work against the used -exchange, those values MUST match the ones used by the exchange. - -The following example shows how the generator "sets" a deposit fee of -EUR:0.01 for the 5 EURO coin. - -:: - - // from /src/sample/generate_payments.c - { .oc = OC_PAY, - .label = "deposit-simple", - .expected_response_code = MHD_HTTP_OK, - .details.pay.contract_ref = "create-proposal-1", - .details.pay.coin_ref = "withdraw-coin-1", - .details.pay.amount_with_fee = concat_amount (currency, "5"), - .details.pay.amount_without_fee = concat_amount (currency, "4.99") }, - -The logic calculates the deposit fee according to the subtraction: -``amount_with_fee - amount_without_fee``. - -The following example shows a 5 EURO coin configuration - needed by the -used exchange - which is compatible with the hardcoded example above. - -:: - - [COIN_eur_5] - value = EUR:5 - duration_overlap = 5 minutes - duration_withdraw = 7 days - duration_spend = 2 years - duration_legal = 3 years - fee_withdraw = EUR:0.00 - fee_deposit = EUR:0.01 # important bit - fee_refresh = EUR:0.00 - fee_refund = EUR:0.00 - rsa_keysize = 1024 - -If the command terminates with no errors, then the merchant backend is -correctly installed. - -After this operation is done, the merchant database will have some dummy -data in it, so it may be convenient to clean all the tables; to this -purpose, issue the following command: - -:: - - $ taler-merchant-dbinit -r - Advanced topics =============== @@ -1026,6 +973,115 @@ Legacy This chapter contains some legacy documentation we need to update before it can be considered even reasonably accurate. + +Taler payments generator +------------------------ + +This tool does not exist anymore right now... + +The tool ``taler-merchant-generate-payments`` can be used to test the +merchant backend installation. It implements all the payment’s steps in +a programmatically way, relying on the backend you give it as input. +Note that this tool gets installed along all the merchant backend’s +binaries. + +This tool gets configured by a config file, that must have the following +layout: + +:: + + [PAYMENTS-GENERATOR] + + # The exchange used during the test: make sure the merchant backend + # being tested accpets this exchange. + # If the sysadmin wants, she can also install a local exchange + # and test against it. + EXCHANGE = https://exchange.demo.taler.net/ + + # This value must indicate some URL where the backend + # to be tested is listening; it doesn't have to be the + # "official" one, though. + MERCHANT = http://localbackend/ + + # This value is used when the tool tries to withdraw coins, + # and must match the bank used by the exchange. If the test is + # done against the exchange at https://exchange.demo.taler.net/, + # then this value can be "https://bank.demo.taler.net/". + BANK = https://bank.demo.taler.net/ + + # The merchant instance in charge of serving the payment. + # Make sure this instance has a bank account at the same bank + # indicated by the 'bank' option above. + INSTANCE = default + + # The currency used during the test. Must match the one used + # by merchant backend and exchange. + CURRENCY = KUDOS + +Run the test in the following way: + +:: + + $ taler-merchant-generate-payments [-c config] [-e EURL] [-m MURL] + +The argument ``config`` given to ``-c`` points to the configuration file +and is optional – ``^/.config/taler.conf`` will be checked by default. +By default, the tool forks two processes: one for the merchant backend, +and one for the exchange. The option ``-e`` (``-m``) avoids any exchange +(merchant backend) fork, and just runs the generator against the +exchange (merchant backend) running at ``EURL`` (``MURL``). + +Please NOTE that the generator contains *hardcoded* values, as for +deposit fees of the coins it uses. In order to work against the used +exchange, those values MUST match the ones used by the exchange. + +The following example shows how the generator "sets" a deposit fee of +EUR:0.01 for the 5 EURO coin. + +:: + + // from /src/sample/generate_payments.c + { .oc = OC_PAY, + .label = "deposit-simple", + .expected_response_code = MHD_HTTP_OK, + .details.pay.contract_ref = "create-proposal-1", + .details.pay.coin_ref = "withdraw-coin-1", + .details.pay.amount_with_fee = concat_amount (currency, "5"), + .details.pay.amount_without_fee = concat_amount (currency, "4.99") }, + +The logic calculates the deposit fee according to the subtraction: +``amount_with_fee - amount_without_fee``. + +The following example shows a 5 EURO coin configuration - needed by the +used exchange - which is compatible with the hardcoded example above. + +:: + + [COIN_eur_5] + value = EUR:5 + duration_overlap = 5 minutes + duration_withdraw = 7 days + duration_spend = 2 years + duration_legal = 3 years + fee_withdraw = EUR:0.00 + fee_deposit = EUR:0.01 # important bit + fee_refresh = EUR:0.00 + fee_refund = EUR:0.00 + rsa_keysize = 1024 + +If the command terminates with no errors, then the merchant backend is +correctly installed. + +After this operation is done, the merchant database will have some dummy +data in it, so it may be convenient to clean all the tables; to this +purpose, issue the following command: + +:: + + $ taler-merchant-dbinit -r + + + Installing Taler using Docker ----------------------------- -- cgit v1.2.3 From 37e0261169fb745d3fd56d68f2873db33f68a45e Mon Sep 17 00:00:00 2001 From: MS Date: Thu, 25 Jun 2020 05:07:45 +0200 Subject: remove old field --- libeufin/api-nexus.rst | 3 --- 1 file changed, 3 deletions(-) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index 6424e73f..20a586a1 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -359,9 +359,6 @@ to the real bank. // Account owner name ownerName: string; - // Account label as given by the bank - account: string; - // If the accoun thas been imported, // this field contains the ID of the // Nexus bank account associated with it. -- cgit v1.2.3 From 7bc827cff7ead90832169dd22faf3faf9fd83790 Mon Sep 17 00:00:00 2001 From: MS Date: Thu, 25 Jun 2020 13:11:31 +0200 Subject: typo --- libeufin/api-nexus.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index 20a586a1..61d55e25 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -359,7 +359,7 @@ to the real bank. // Account owner name ownerName: string; - // If the accoun thas been imported, + // If the account has been imported, // this field contains the ID of the // Nexus bank account associated with it. nexusBankAccountId: string | null; -- cgit v1.2.3 From b1d2864aa3c80a223a782352aa5fb64f4d613424 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 25 Jun 2020 22:54:04 +0200 Subject: improve merchant manual --- taler-merchant-manual.rst | 158 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 135 insertions(+), 23 deletions(-) diff --git a/taler-merchant-manual.rst b/taler-merchant-manual.rst index f8515c0a..d6f07efb 100644 --- a/taler-merchant-manual.rst +++ b/taler-merchant-manual.rst @@ -152,11 +152,13 @@ backend: - libargon2 >= 20171227 (GNUnet 0.13 needs it to build, not actively used by GNU Taler) +- libsqlite3 >= 3.0 (GNUnet 0.13 needs it to build, not actively used by GNU Taler) + - libjansson >= 2.7 - Postgres >= 9.6, including libpq -- libgnunetutil (from Git) +- GNUnet (from Git) - GNU Taler exchange (from Git) @@ -169,20 +171,20 @@ the libgnunetutil and GNU Taler exchange dependencies. .. _Installing-libgnunetutil: -Installing libgnunetutil -^^^^^^^^^^^^^^^^^^^^^^^^ +Installing GNUnet +^^^^^^^^^^^^^^^^^ .. index:: GNUnet -Before you install libgnunetutil, you must download and install the -dependencies mentioned in the previous section, otherwise the build may -succeed but fail to export some of the tooling required by Taler. +Before you install GNUnet, you must download and install the dependencies +mentioned in the previous section, otherwise the build may succeed, but could +fail to export some of the tooling required by GNU Taler. -To download and install libgnunetutil, proceed as follows: +To download and install GNUnet, proceed as follows: :: - $ git clone https://gnunet.org/git/gnunet/ + $ git clone https://git.gnunet.org/gnunet/ $ cd gnunet/ $ ./bootstrap $ ./configure [--prefix=GNUNETPFX] @@ -194,6 +196,11 @@ To download and install libgnunetutil, proceed as follows: If you did not specify a prefix, GNUnet will install to ``/usr/local``, which requires you to run the last step as ``root``. +There is no need to actually run a GNUnet peer to use the Taler merchant +backend -- all the merchant needs from GNUnet is a number of headers and +libraries! + + .. _Installing-the-GNU-Taler-exchange: Installing the GNU Taler exchange @@ -206,7 +213,7 @@ follows: :: - $ git clone git://taler.net/exchange + $ git clone https://git.taler.net/exchange/ $ cd exchange $ ./bootstrap $ ./configure [--prefix=EXCHANGEPFX] \ @@ -216,10 +223,15 @@ follows: $ make # make install -If you did not specify a prefix, the exchange will install to -``/usr/local``, which requires you to run the last step as ``root``. -Note that you have to specify ``--with-gnunet=/usr/local`` if you -installed GNUnet to ``/usr/local`` in the previous step. +If you did not specify a prefix, the exchange will install to ``/usr/local``, +which requires you to run the last step as ``root``. You have to specify +``--with-gnunet=/usr/local`` if you installed GNUnet to ``/usr/local`` in the +previous step. + +There is no need to actually run a Taler exchange to use the Taler merchant +backend -- all the merchant needs from the Taler exchange is a few headers and +libraries! + .. _Installing-the-GNU-Taler-merchant-backend: @@ -234,7 +246,7 @@ Use the following commands to download and install the merchant backend: :: - $ git clone git://taler.net/merchant + $ git clone https://git.taler.net/merchant/ $ cd merchant $ ./bootstrap $ ./configure [--prefix=PFX] \ @@ -243,12 +255,24 @@ Use the following commands to download and install the merchant backend: $ # Each dependency can be fetched from non standard locations via $ # the '--with-' option. See './configure --help'. $ make - $ make install + # make install + +If you did not specify a prefix, the exchange will install to +``/usr/local``, which requires you to run the last step as ``root``. -Note that you have to specify ``--with-exchange=/usr/local`` and/or +You have to specify ``--with-exchange=/usr/local`` and/or ``--with-exchange=/usr/local`` if you installed the exchange and/or GNUnet to ``/usr/local`` in the previous steps. +Depending on the prefixes you specified for the installation and the +distribution you are using, you may have to edit ``/etc/ld.so.conf``, adding +lines for ``GNUNETPFX/lib/`` and ``EXCHANGEPFX/lib/`` and ``PFX/lib/`` +(replace the prefixes with the actual paths you used). Afterwards, you should +run ``ldconfig``. Without this step, it is possible that the linker may not +find the installed libraries and launching the Taler merchant backend would +then fail. + + .. _Installing-Taler-on-Debian-GNU_002fLinux: Installing Taler on Debian GNU/Linux @@ -381,6 +405,8 @@ To run the Taler backend on TCP port 8888, use: $ taler-config -s MERCHANT -o SERVE -V TCP $ taler-config -s MERCHANT -o PORT -V 8888 + + Currency ^^^^^^^^ @@ -399,6 +425,7 @@ https://exchange.demo.taler.net/: $ taler-config -s TALER -o CURRENCY -V KUDOS + Database ^^^^^^^^ @@ -429,7 +456,7 @@ run :: - $ sudu -u postgres createuser -d $USER + $ sudo -u postgres createuser -d $USER as the Postgres database administrator (usually ``postgres``) to grant ``$USER`` the ability to create new databases. Next, you should @@ -449,6 +476,21 @@ To configure the Taler backend to use this database, run: $ taler-config -s MERCHANTDB-postgres -o CONFIG \ -V postgres:///$DBNAME +Now you should create the tables and indices. To do this, run as ``$USER``: + + :: + + $ taler-merchant-dbinit + + +You can improve your security posture if you now REVOKE the rights to CREATE, +DROP or ALTER tables from ``$USER``. However, if you do so, please be aware +that you may have to temporarily GRANT those rights again when you update the +merchant backend. For details on how to REVOKE or GRANT these rights, consult +the Postgres documentation. + + + .. index: MASTER_KEY Exchange @@ -592,15 +634,18 @@ Launching the backend .. index:: taler-merchant-httpd Assuming you have configured everything correctly, you can launch the -merchant backend using: +merchant backend as ``$USER`` using: :: $ taler-merchant-httpd -When launched for the first time, this command will print a message -about generating your private key. If everything worked as expected, the -command +To ensure the process runs always in the background and also after rebooting, +you should use systemd, cron or some other init system of your operating +system to launch the process. Consult the documentation of your operating +system for how to start and stop daemons. + +If everything worked as expected, the command :: @@ -614,7 +659,8 @@ should return the message Please note that your backend is right now likely globally reachable. Production systems should be configured to bind to a UNIX domain socket -or properly restrict access to the port. +and use TLS for improved network privacy, see `Secure setup <#Secure-setup>`__. + .. _Instances: @@ -632,6 +678,8 @@ backend (possibly via a Web interface -- once we implement that). FIXME: more details on how to setup instances here! + + Accounts -------- @@ -647,10 +695,74 @@ a ``payto://``-URL. FIXME: more details on how to setup accounts here! +Upgrade procedure +================= + +This is the general upgrade procedure. Please see the release notes +for your specific version to check if a particular release has special +upgrade requirements. + +Please note that upgrades are ONLY supported for released version of the +merchant. Attempting to upgrade from or to a version in Git is not supported +and may result in subtle data loss. + +To safely upgrade the merchant, you should first stop the existing +taler-merchant-httpd process, backup your merchant database (see Postgres +manual), and then install the latest version of the code. + +If you REVOKED database permissions, ensure that the rights to CREATE, +DROP, and ALTER tables are GRANTed to ``$USER`` again. Then, run: + + :: + + $ taler-merchant-dbinit + +to upgrade the database to the latest schema. After that, you may again +REVOKE the database permissions. Finally, restart the HTTP service, either via +your systemd or init system, or directly using: + + :: + + $ taler-merchant-httpd + + Advanced topics =============== +.. _Secure-setup: + +Secure setup +------------ + +.. index:: security +.. index:: TLS + +For additional security, you may want to have the backend bind to a UNIX +domain socket and use an HTTP reverse proxy for TLS termination: + + :: + + $ taler-config -s MERCHANT -o SERVE -V UNIX + $ taler-config -s MERCHANT -o UNIXPATH -V /some/path/here.sock + +Assuming your domain name is /example.com/ and you have TLS configured, +a possible reverse proxy directive for Nginx would be: + + :: + + proxy_pass http://unix:/some/path/here.sock; + proxy_redirect off; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Host "example.com"; + proxy_set_header X-Forwarded-Proto "https"; + +Leave out the last line if your Nginx reverse proxy does not have HTTPS +enabled. Make sure to restart the /taler-merchant-httpd/ process after +changing the configuration. + + + Configuration format -------------------- @@ -726,7 +838,7 @@ configuration file used in our demos. See under ``deployment/config``. .. _Using-taler_002dconfig: Using taler-config ------------------- +^^^^^^^^^^^^^^^^^^ .. index:: taler-config -- cgit v1.2.3 From e25c00421f555d8fe371b135451f06dedd0e11b5 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 25 Jun 2020 23:10:17 +0200 Subject: improving merchant backend documentation --- taler-merchant-manual.rst | 310 ++++++++++++++++++++++++++-------------------- 1 file changed, 176 insertions(+), 134 deletions(-) diff --git a/taler-merchant-manual.rst b/taler-merchant-manual.rst index d6f07efb..9f44960a 100644 --- a/taler-merchant-manual.rst +++ b/taler-merchant-manual.rst @@ -673,11 +673,36 @@ uses its own bank accounts and key for signing contracts. It is mandatory to configure at least the "default" instance. Instances can be configured by POSTing the necessary requests to the -backend (possibly via a Web interface -- once we implement that). +backend. To create a first instance, create a file ``instance.json`` +with an `InstanceConfigurationMessage`: -FIXME: more details on how to setup instances here! +:: + + { + payto_uris : [ "payto://iban/IBANNUMBERHERE" ], + id : "default", + name: "example.com", + address: { country : "zz" }, + jurisdiction: { country : "zz" }, + default_max_wire_fee: "KUDOS:1", + default_wire_fee_amortization: 100, + default_max_deposit_fee: "KUDOS:1", + default_wire_transfer_delay: { d_ms : 1209600000 }, + default_pay_delay: { d_ms : 1209600000 }, + } + +You can then create the instance using: +:: + $ wget --post-file=instance.json http://localhost:8888/private/instances +The base URL for the instance will then be +``http://localhost:8888/instances/default``. You can create additional +instances by changing the "id" value to identifies other than "default". + +Endpoints to modify (reconfigure), permanently disable (while keeping the data) +or purge (deleting all associated data) instances exist as well and are documented +in the `Merchant Backend API documentation <#merchant-api>`__. Accounts @@ -689,10 +714,50 @@ is the bank account information. In order to receive payments, the merchant backend needs to communicate bank account details to the exchange. -The bank account information is provided in the form of -a ``payto://``-URL. +The bank account information is provided in the form of a ``payto://``-URL. + +See RFC XXXX for the format of ``payto://``-URLs. + + +.. _Inventory: + +Inventory management +==================== + + + + + +.. _Secure-setup: + +Secure setup +============ + +.. index:: security +.. index:: TLS + +For additional security, you may want to have the backend bind to a UNIX +domain socket and use an HTTP reverse proxy for TLS termination: + + :: + + $ taler-config -s MERCHANT -o SERVE -V UNIX + $ taler-config -s MERCHANT -o UNIXPATH -V /some/path/here.sock + +Assuming your domain name is /example.com/ and you have TLS configured, +a possible reverse proxy directive for Nginx would be: + + :: + + proxy_pass http://unix:/some/path/here.sock; + proxy_redirect off; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Host "example.com"; + proxy_set_header X-Forwarded-Proto "https"; -FIXME: more details on how to setup accounts here! +Leave out the last line if your Nginx reverse proxy does not have HTTPS +enabled. Make sure to restart the /taler-merchant-httpd/ process after +changing the configuration. Upgrade procedure @@ -726,40 +791,116 @@ your systemd or init system, or directly using: $ taler-merchant-httpd +.. _Tipping-visitors: -Advanced topics -=============== +Tipping visitors +================ -.. _Secure-setup: +.. index:: tipping -Secure setup ------------- +NOTE: This section is dated and should be reviewed! -.. index:: security -.. index:: TLS +Taler can also be used to tip Web site visitors. For example, you may be +running an online survey, and you want to reward those people that have +dutifully completed the survey. If they have installed a Taler wallet, +you can provide them with a tip for their deeds. This section describes +how to setup the Taler merchant backend for tipping. -For additional security, you may want to have the backend bind to a UNIX -domain socket and use an HTTP reverse proxy for TLS termination: +There are four basic steps that must happen to tip a visitor. - :: +FIXME: write current explanation! - $ taler-config -s MERCHANT -o SERVE -V UNIX - $ taler-config -s MERCHANT -o UNIXPATH -V /some/path/here.sock +.. _Fund-the-reserve: -Assuming your domain name is /example.com/ and you have TLS configured, -a possible reverse proxy directive for Nginx would be: +Fund the reserve +---------------- - :: +.. index:: reserve +.. index:: close - proxy_pass http://unix:/some/path/here.sock; - proxy_redirect off; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-Host "example.com"; - proxy_set_header X-Forwarded-Proto "https"; +In our example, the output for the wire transfer subject is: -Leave out the last line if your Nginx reverse proxy does not have HTTPS -enabled. Make sure to restart the /taler-merchant-httpd/ process after -changing the configuration. +:: + + QPE24X8PBX3BZ6E7GQ5VAVHV32FWTTCADR0TRQ183MSSJD2CHNEG + +You now need to make a wire transfer to the exchange’s bank account +using the public key as the wire transfer subject. + +Make your wire transfer and (optionally) check at +“https://exchange/reserves/QPE24X...” whether your transfer has arrived at the +exchange. + +Once the funds have arrived, you can start to use the reserve for +tipping. + +Note that an exchange will typically close a reserve after four weeks, wiring +all remaining funds back to the sender’s account. Thus, you should plan to +wire funds corresponding to a campaign of about two weeks to the exchange +initially. If your campaign runs longer, you should setup another reserve +every other week to ensure one is always ready. + +.. _Authorize-a-tip: + +Authorize a tip +--------------- + +When your frontend has reached the point where a client is supposed to receive +a tip, it needs to first authorize the tip. For this, the frontend must use +the “/private/reserves/$RID/tip-authorize” API of the backend. To authorize a +tip, the frontend has to provide the following information in the body of the +POST request: + +- The amount of the tip + +- The justification (only used internally for the back-office) + +- The URL where the wallet should navigate next after the tip was + processed + +- The tip-pickup URL (see next section) + +In response to this request, the backend will return a tip token, an +expiration time and the exchange URL. The expiration time will indicate +how long the tip is valid (when the reserve expires). The tip token is +an opaque string that contains all the information needed by the wallet +to process the tip. The frontend must send this tip token to the browser +in a special “402 Payment Required” response inside the ``X-Taler-Tip`` +header. + +The frontend should handle errors returned by the backend, such as +missconfigured instances or a lack of remaining funds for tipping. + +.. _Picking-up-of-the-tip: + +Picking up of the tip +--------------------- + +The wallet will POST a JSON object to the shop’s “/tips/$TIP/pickup” handler. +The frontend must then forward this request to the backend. The response +generated by the backend can then be forwarded directly to the wallet. + + + + +Advanced topics +=============== + +.. _MerchantDatabaseScheme: + +Database Scheme +--------------- + +The merchant database must be initialized using taler-merchant-dbinit. +This tool creates the tables required by the Taler merchant to operate. +The tool also allows you to reset the Taler merchant database, which is +useful for test cases but should never be used in production. Finally, +taler-merchant-dbinit has a function to garbage collect a database, +allowing administrators to purge records that are no longer required. + +The database scheme used by the merchant looks as follows: + +.. image:: merchant-db.png @@ -890,92 +1031,7 @@ While the configuration file is typically located at to ``taler-merchant-httpd`` and ``taler-config`` using the ``-c`` option. -.. _Tipping-visitors: - -Tipping visitors ----------------- - -.. index:: tipping - -Taler can also be used to tip Web site visitors. For example, you may be -running an online survey, and you want to reward those people that have -dutifully completed the survey. If they have installed a Taler wallet, -you can provide them with a tip for their deeds. This section describes -how to setup the Taler merchant backend for tipping. - -There are four basic steps that must happen to tip a visitor. - -FIXME: write current explanation! - -.. _Fund-the-reserve: - -Fund the reserve -^^^^^^^^^^^^^^^^ - -.. index:: reserve -.. index:: close - -In our example, the output for the wire transfer subject is: - -:: - - QPE24X8PBX3BZ6E7GQ5VAVHV32FWTTCADR0TRQ183MSSJD2CHNEG - -You now need to make a wire transfer to the exchange’s bank account -using the public key as the wire transfer subject. - -Make your wire transfer and (optionally) check at -“https://exchange/reserves/QPE24X...” whether your transfer has arrived at the -exchange. - -Once the funds have arrived, you can start to use the reserve for -tipping. - -Note that an exchange will typically close a reserve after four weeks, wiring -all remaining funds back to the sender’s account. Thus, you should plan to -wire funds corresponding to a campaign of about two weeks to the exchange -initially. If your campaign runs longer, you should setup another reserve -every other week to ensure one is always ready. - -.. _Authorize-a-tip: - -Authorize a tip -^^^^^^^^^^^^^^^ - -When your frontend has reached the point where a client is supposed to receive -a tip, it needs to first authorize the tip. For this, the frontend must use -the “/private/reserves/$RID/tip-authorize” API of the backend. To authorize a -tip, the frontend has to provide the following information in the body of the -POST request: - -- The amount of the tip - -- The justification (only used internally for the back-office) - -- The URL where the wallet should navigate next after the tip was - processed - -- The tip-pickup URL (see next section) - -In response to this request, the backend will return a tip token, an -expiration time and the exchange URL. The expiration time will indicate -how long the tip is valid (when the reserve expires). The tip token is -an opaque string that contains all the information needed by the wallet -to process the tip. The frontend must send this tip token to the browser -in a special “402 Payment Required” response inside the ``X-Taler-Tip`` -header. - -The frontend should handle errors returned by the backend, such as -missconfigured instances or a lack of remaining funds for tipping. - -.. _Picking-up-of-the-tip: -Picking up of the tip -^^^^^^^^^^^^^^^^^^^^^ - -The wallet will POST a JSON object to the shop’s “/tips/$TIP/pickup” handler. -The frontend must then forward this request to the backend. The response -generated by the backend can then be forwarded directly to the wallet. .. _Benchmarking: @@ -984,6 +1040,8 @@ Benchmarking .. index:: testing database +NOTE: This section is dated and should be reviewed! + The merchant codebase offers the ``taler-merchant-benchmark`` tool to populate the database with fake payments. This tool is in charge of starting a merchant, exchange, and bank processes, and provide them all @@ -1061,27 +1119,6 @@ topics that might be helpful to understand how the exchange operates, which files should be backed up. The information may also be helpful for diagnostics. -.. _MerchantDatabaseScheme: - -Database Scheme ---------------- - -The merchant database must be initialized using taler-merchant-dbinit. -This tool creates the tables required by the Taler merchant to operate. -The tool also allows you to reset the Taler merchant database, which is -useful for test cases but should never be used in production. Finally, -taler-merchant-dbinit has a function to garbage collect a database, -allowing administrators to purge records that are no longer required. - -The database scheme used by the merchant looks as follows: - -.. image:: merchant-db.png - - - -Legacy -====== - This chapter contains some legacy documentation we need to update before it can be considered even reasonably accurate. @@ -1194,6 +1231,11 @@ purpose, issue the following command: + + +Legacy +====== + Installing Taler using Docker ----------------------------- -- cgit v1.2.3 From 7f6d92f19506e45e4e526d34af5210214e063311 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 25 Jun 2020 23:37:08 +0200 Subject: cleanup --- taler-exchange-manual.rst | 7 +++---- taler-merchant-manual.rst | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/taler-exchange-manual.rst b/taler-exchange-manual.rst index 2e84ab54..86abce8d 100644 --- a/taler-exchange-manual.rst +++ b/taler-exchange-manual.rst @@ -483,9 +483,8 @@ The generated file will be echoed by the exchange when serving Wire fee structure ~~~~~~~~~~~~~~~~~~ -.. meta:: - :keywords: wire fee - :keywords: fee +.. index:: wire fee +.. index:: fee For each wire method (“sepa” or “x-taler-wire”) the exchange configuration must specify applicable wire fees. This is done @@ -916,7 +915,7 @@ TALER_SIGNATURE_AUDITOR_EXCHANGE_KEYS purpose. -.. _Benchmarking: +.. _ExchangeBenchmarking: Benchmarking ============ diff --git a/taler-merchant-manual.rst b/taler-merchant-manual.rst index 9f44960a..7e3eac6d 100644 --- a/taler-merchant-manual.rst +++ b/taler-merchant-manual.rst @@ -1033,7 +1033,7 @@ option. -.. _Benchmarking: +.. _MerchantBenchmarking: Benchmarking ------------ -- cgit v1.2.3 From ac542c2f0bf79cfc302b0fb7059adbbc6bdf60f0 Mon Sep 17 00:00:00 2001 From: buckE Date: Fri, 26 Jun 2020 04:13:40 +0000 Subject: removed exit 1 on sphinx warnings --- Makefile | 7 +++---- README | 4 ++++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index da61fa46..358aef58 100644 --- a/Makefile +++ b/Makefile @@ -60,8 +60,8 @@ diagrams: arch-api.png # The html-linked builder does not support caching, so we # remove all cached state first. html: diagrams -# -W = exit 1 on warning; --keep-going = complete build anyway; write log to ~/warnings.log - $(SPHINXBUILD) -W --keep-going -b html-linked $(ALLSPHINXOPTS) $(BUILDDIR)/html +# -W = exit 1 on warning; --keep-going = complete build anyway; -w /tmp/sphinx-warnings.log = write log to ~/warnings.log + $(SPHINXBUILD) -b html-linked $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." @@ -122,8 +122,7 @@ latex: "(use \`make latexpdf' here to do that automatically)." latexpdf: - # -W = exit 1 on warning; --keep-going = complete build anyway - $(SPHINXBUILD) -W --keep-going -w $(shell echo $HOME)/logs/sphinx-warnings.log -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." diff --git a/README b/README index 55a9c430..b7f64144 100644 --- a/README +++ b/README @@ -4,3 +4,7 @@ Before building the documentation, make sure that you have the required dependencies installed using pip3: $ pip3 install --user --upgrade recommonmark sphinx + +Note by Buck: when setting up on VM, I also needed: + +# apt install texlive-latex-extra graphviz -- cgit v1.2.3 From 0406210f38cebe8a46af29a64b81a083c9f8a762 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 26 Jun 2020 09:31:27 +0200 Subject: update man pages --- manpages/taler-auditor-dbinit.1.rst | 2 +- manpages/taler-auditor-exchange.1.rst | 2 +- manpages/taler-auditor-sign.1.rst | 2 +- manpages/taler-auditor.1.rst | 2 +- manpages/taler-bank-transfer.1.rst | 2 +- manpages/taler-config-generate.1.rst | 2 +- manpages/taler-exchange-aggregator.1.rst | 2 +- manpages/taler-exchange-benchmark.1.rst | 2 +- manpages/taler-exchange-closer.1.rst | 2 +- manpages/taler-exchange-dbinit.1.rst | 2 +- manpages/taler-exchange-httpd.1.rst | 2 +- manpages/taler-exchange-keycheck.1.rst | 2 +- manpages/taler-exchange-keyup.1.rst | 2 +- manpages/taler-exchange-transfer.1.rst | 2 +- manpages/taler-exchange-wire.1.rst | 2 +- manpages/taler-exchange-wirewatch.1.rst | 2 +- manpages/taler-merchant-benchmark.1.rst | 2 +- manpages/taler-merchant-httpd.1.rst | 2 +- manpages/taler-wallet-cli.1.rst | 2 +- manpages/taler.conf.5.rst | 217 ++++++++++++------------------- 20 files changed, 104 insertions(+), 151 deletions(-) diff --git a/manpages/taler-auditor-dbinit.1.rst b/manpages/taler-auditor-dbinit.1.rst index 463814ac..48509012 100644 --- a/manpages/taler-auditor-dbinit.1.rst +++ b/manpages/taler-auditor-dbinit.1.rst @@ -54,5 +54,5 @@ taler-auditor-httpd(1), taler-auditor(1), taler.conf(5). Bugs ==== -Report bugs by using https://bugs.gnunet.org or by sending electronic +Report bugs by using https://bugs.taler.net/ or by sending electronic mail to . diff --git a/manpages/taler-auditor-exchange.1.rst b/manpages/taler-auditor-exchange.1.rst index 422d8b06..3471cf1a 100644 --- a/manpages/taler-auditor-exchange.1.rst +++ b/manpages/taler-auditor-exchange.1.rst @@ -63,5 +63,5 @@ step). Furthermore, if we do verification, as a (less secure) convenience option, we should make **-** m optional and obtain it from the base URL. -Report bugs by using https://gnunet.org/bugs/ or by sending electronic +Report bugs by using https://bugs.taler.net/ or by sending electronic mail to . diff --git a/manpages/taler-auditor-sign.1.rst b/manpages/taler-auditor-sign.1.rst index b9c34fb8..86dfba39 100644 --- a/manpages/taler-auditor-sign.1.rst +++ b/manpages/taler-auditor-sign.1.rst @@ -59,5 +59,5 @@ taler.conf(5) Bugs ==== -Report bugs by using https://gnunet.org/bugs/ or by sending electronic +Report bugs by using https://bugs.taler.net/ or by sending electronic mail to . diff --git a/manpages/taler-auditor.1.rst b/manpages/taler-auditor.1.rst index d8ee1a96..1d04c487 100644 --- a/manpages/taler-auditor.1.rst +++ b/manpages/taler-auditor.1.rst @@ -47,5 +47,5 @@ gnunet-ecc(1), taler-auditor-sign(1), taler.conf(5), taler-auditor-dbinit(1) Bugs ==== -Report bugs by using https://bugs.gnunet.org or by sending electronic +Report bugs by using https://bugs.taler.net or by sending electronic mail to . diff --git a/manpages/taler-bank-transfer.1.rst b/manpages/taler-bank-transfer.1.rst index 9e466def..56fe0186 100644 --- a/manpages/taler-bank-transfer.1.rst +++ b/manpages/taler-bank-transfer.1.rst @@ -105,5 +105,5 @@ taler-bank-manage(1), taler.conf(5), https://docs.taler.net/core/api-wire.html#w Bugs ==== -Report bugs by using https://gnunet.org/bugs/ or by sending electronic +Report bugs by using https://bugs.taler.net/ or by sending electronic mail to diff --git a/manpages/taler-config-generate.1.rst b/manpages/taler-config-generate.1.rst index f7fd1cc5..3cd36d10 100644 --- a/manpages/taler-config-generate.1.rst +++ b/manpages/taler-config-generate.1.rst @@ -89,5 +89,5 @@ for the Taler exchange or Taler merchants. Bugs ==== -Report bugs by using https://gnunet.org/bugs/ or by sending electronic +Report bugs by using https://bugs.taler.net/ or by sending electronic mail to . diff --git a/manpages/taler-exchange-aggregator.1.rst b/manpages/taler-exchange-aggregator.1.rst index 255e1e14..1e010fad 100644 --- a/manpages/taler-exchange-aggregator.1.rst +++ b/manpages/taler-exchange-aggregator.1.rst @@ -43,5 +43,5 @@ taler-exchange-httpd(1), taler.conf(5). Bugs ==== -Report bugs by using https://gnunet.org/bugs/ or by sending electronic +Report bugs by using https://bugs.taler.net/ or by sending electronic mail to . diff --git a/manpages/taler-exchange-benchmark.1.rst b/manpages/taler-exchange-benchmark.1.rst index 9bc0c8d0..98bae49e 100644 --- a/manpages/taler-exchange-benchmark.1.rst +++ b/manpages/taler-exchange-benchmark.1.rst @@ -69,5 +69,5 @@ taler-exchange-httpd(1), taler.conf(5) Bugs ==== -Report bugs by using https://gnunet.org/bugs/ or by sending electronic +Report bugs by using https://bugs.taler.net/ or by sending electronic mail to . diff --git a/manpages/taler-exchange-closer.1.rst b/manpages/taler-exchange-closer.1.rst index 8783cd61..7cc9e34c 100644 --- a/manpages/taler-exchange-closer.1.rst +++ b/manpages/taler-exchange-closer.1.rst @@ -43,5 +43,5 @@ taler-exchange-transfer(1), taler-exchange-httpd(1), taler.conf(5). Bugs ==== -Report bugs by using https://gnunet.org/bugs/ or by sending electronic +Report bugs by using https://bugs.taler.net/ or by sending electronic mail to . diff --git a/manpages/taler-exchange-dbinit.1.rst b/manpages/taler-exchange-dbinit.1.rst index 6d9b787b..5a1616d5 100644 --- a/manpages/taler-exchange-dbinit.1.rst +++ b/manpages/taler-exchange-dbinit.1.rst @@ -52,5 +52,5 @@ taler-exchange-reservemod(1), taler.conf(5). Bugs ==== -Report bugs by using https://bugs.gnunet.org or by sending electronic +Report bugs by using https://bugs.taler.net or by sending electronic mail to . diff --git a/manpages/taler-exchange-httpd.1.rst b/manpages/taler-exchange-httpd.1.rst index 11027684..88a47435 100644 --- a/manpages/taler-exchange-httpd.1.rst +++ b/manpages/taler-exchange-httpd.1.rst @@ -100,5 +100,5 @@ taler-exchange-reservemod(1), taler.conf(5). Bugs ==== -Report bugs by using https://gnunet.org/bugs or by sending electronic +Report bugs by using https://bugs.taler.net or by sending electronic mail to . diff --git a/manpages/taler-exchange-keycheck.1.rst b/manpages/taler-exchange-keycheck.1.rst index 3f7b0352..d79bbddb 100644 --- a/manpages/taler-exchange-keycheck.1.rst +++ b/manpages/taler-exchange-keycheck.1.rst @@ -51,5 +51,5 @@ taler-exchange-dbinit(1), taler.conf(5). Bugs ==== -Report bugs by using https://gnunet.org/bugs/ or by sending electronic +Report bugs by using https://bugs.taler.net/ or by sending electronic mail to . diff --git a/manpages/taler-exchange-keyup.1.rst b/manpages/taler-exchange-keyup.1.rst index cab075a7..d21cbebe 100644 --- a/manpages/taler-exchange-keyup.1.rst +++ b/manpages/taler-exchange-keyup.1.rst @@ -80,5 +80,5 @@ taler-exchange-keycheck(1), taler.conf(5). Bugs ==== -Report bugs by using https://gnunet.org/bugs/ or by sending electronic +Report bugs by using https://bugs.taler.net/ or by sending electronic mail to . diff --git a/manpages/taler-exchange-transfer.1.rst b/manpages/taler-exchange-transfer.1.rst index 4dac3625..c579e655 100644 --- a/manpages/taler-exchange-transfer.1.rst +++ b/manpages/taler-exchange-transfer.1.rst @@ -42,5 +42,5 @@ taler-exchange-httpd(1), taler.conf(5). Bugs ==== -Report bugs by using https://gnunet.org/bugs/ or by sending electronic +Report bugs by using https://bugs.taler.net/ or by sending electronic mail to . diff --git a/manpages/taler-exchange-wire.1.rst b/manpages/taler-exchange-wire.1.rst index 22ab8572..23242d1c 100644 --- a/manpages/taler-exchange-wire.1.rst +++ b/manpages/taler-exchange-wire.1.rst @@ -42,5 +42,5 @@ taler-exchange-httpd(1), taler.conf(5). Bugs ==== -Report bugs by using https://gnunet.org/bugs/ or by sending electronic +Report bugs by using https://bugs.taler.net/ or by sending electronic mail to . diff --git a/manpages/taler-exchange-wirewatch.1.rst b/manpages/taler-exchange-wirewatch.1.rst index 8aaa50fb..9c00fd66 100644 --- a/manpages/taler-exchange-wirewatch.1.rst +++ b/manpages/taler-exchange-wirewatch.1.rst @@ -53,5 +53,5 @@ taler-exchange-aggregator(1), taler-exchange-httpd(1), taler.conf(5). Bugs ==== -Report bugs by using https://gnunet.org/bugs/ or by sending electronic +Report bugs by using https://bugs.taler.net/ or by sending electronic mail to . diff --git a/manpages/taler-merchant-benchmark.1.rst b/manpages/taler-merchant-benchmark.1.rst index b4a1af36..3d688e07 100644 --- a/manpages/taler-merchant-benchmark.1.rst +++ b/manpages/taler-merchant-benchmark.1.rst @@ -99,7 +99,7 @@ Common Options Bugs ==== -Report bugs by using https://gnunet.org/bugs/ or by sending electronic +Report bugs by using https://bugs.taler.net/ or by sending electronic mail to . diff --git a/manpages/taler-merchant-httpd.1.rst b/manpages/taler-merchant-httpd.1.rst index 0d12030f..68cd2fbe 100644 --- a/manpages/taler-merchant-httpd.1.rst +++ b/manpages/taler-merchant-httpd.1.rst @@ -53,7 +53,7 @@ SIGTERM Bugs ==== -Report bugs by using Mantis or by sending +Report bugs by using Mantis or by sending electronic mail to diff --git a/manpages/taler-wallet-cli.1.rst b/manpages/taler-wallet-cli.1.rst index 83fe591c..15864478 100644 --- a/manpages/taler-wallet-cli.1.rst +++ b/manpages/taler-wallet-cli.1.rst @@ -57,5 +57,5 @@ for testing. Bugs ==== -Report bugs by using https://bugs.gnunet.org or by sending electronic +Report bugs by using https://bugs.taler.net or by sending electronic mail to . diff --git a/manpages/taler.conf.5.rst b/manpages/taler.conf.5.rst index d7ca470c..d880bc17 100644 --- a/manpages/taler.conf.5.rst +++ b/manpages/taler.conf.5.rst @@ -141,137 +141,6 @@ CONFIG How to access the database, i.e. “postgres:///taler” to use the “taler” database. Testcases use “talercheck”. -MERCHANT OPTIONS ----------------- - -The following options are from the “[merchant]” section and used by the -merchant backend. - -DB - Plugin to use for the database, i.e. “postgres” - -PORT - Port on which the HTTP server listens, i.e. 8080. - -WIRE_TRANSFER_DELAY - How quickly do we want the exchange to send us money? Note that wire - transfer fees will be higher if we ask for money to be wired often. - Given as a relative time, i.e. “5 s” - -DEFAULT_MAX_WIRE_FEE - Maximum wire fee we are willing to accept from exchanges. Given as a - Taler amount, i.e. “EUR:0.1” - -DEFAULT_MAX_DEPOSIT_FEE - Maximum deposit fee we are willing to cover. Given as a Taler amount, - i.e. “EUR:0.1” - -MERCHANT POSTGRES BACKEND DATABASE OPTIONS ------------------------------------------- - -The following options must be in section “[merchantdb-postgres]” if the -“postgres” plugin was selected for the database. - -CONFIG - How to access the database, i.e. “postgres:///taler” to use the - “taler” database. Testcases use “talercheck”. - -MERCHANT INSTANCES ------------------- - -The merchant configuration must specify a set of instances, containing -at least the “default” instance. The following options must be given in -each “[instance-NAME]” section. - -KEYFILE - Name of the file where the instance´s private key is to be stored, - i.e. “${TALER_CONFIG_HOME}/merchant/instance/name.priv” - -NAME - Human-readable name of the instance, i.e. “Kudos Inc.” - -Additionally, for instances that support tipping, the following options -are required. - -TIP_EXCHANGE - Base-URL of the exchange that holds the reserve for tipping, - i.e. “https://exchange.demo.taler.net/” - -TIP_EXCHANGE_PRIV_FILENAME - Filename with the private key granting access to the reserve, - i.e. “${TALER_CONFIG_HOME}/merchant/reserve/tip.priv” - -KNOWN EXCHANGES (for merchants) -------------------------------- - -The merchant configuration can include a list of known exchanges if the -merchant wants to specify that certain exchanges are explicitly trusted. -For each trusted exchange, a section [merchant-exchange-$NAME] must exist, where -$NAME is a merchant-given name for the exchange. The following options -must be given in each “[exchange-$NAME]” section. - -EXCHANGE_BASE_URL - Base URL of the exchange, i.e. “https://exchange.demo.taler.net/” - -MASTER_KEY - Crockford Base32 encoded master public key, public version of the - exchange´s long-time offline signing key. Can be omitted, in that - case the exchange will NOT be trusted unless it is audited by - a known auditor. - Omitting the MASTER_KEY can be useful if we do not trust the exchange - without an auditor, but should pre-load the keys of this - particular exchange on startup instead of waiting for it to be - required by a client. - -CURRENCY - Name of the currency for which this exchange is used, i.e. “KUDOS”. - The entire section is ignored if the currency does not match the currency - we use, which must be given in the [taler] section. - -KNOWN AUDITORS (for merchants) ------------------------------- - -The merchant configuration can include a list of known exchanges if the -merchant wants to specify that certain auditors are explicitly trusted. -For each trusted exchange, a section [merchant-auditor-$NAME] must exist, where -$NAME is a merchant-given name for the auditor. The following options -must be given in each “[merchant-auditor-$NAME]” section. - -AUDITOR_BASE_URL - Base URL of the auditor, i.e. “https://auditor.demo.taler.net/” - -AUDITOR_KEY - Crockford Base32 encoded auditor public key. - -CURRENCY - Name of the currency for which this auditor is trusted, i.e. “KUDOS” - The entire section is ignored if the currency does not match the currency - we use, which must be given in the [taler] section. - - -MERCHANT ACCOUNT OPTIONS ------------------------- - -PAYTO_URI - Specifies the payto://-URL of the account. The general format is - payto://$METHOD/$DETAILS. - -WIRE_RESPONSE (exchange and merchant) - Specifies the name of the file in which the wire details for this merchant - account should be located. Used by the Taler exchange service and the - taler-merchant-httpd (to generate and then use the file). - -HONOR_instance - Must be set to YES for the instances (where "instance" is the section name - of the instance) of the merchant backend that should accept payments (i.e. - Taler deposit operations) with the corresponding payto URI. - -ACTIVE_instance - Must be set to YES for the instances (where “instance” is the section - name of the instance) of the merchant backend that should use this - bank account in new offers/contracts. Setting ACTIVE_instance to YES - requires also setting HONOR_instance to YES. - EXCHANGE ACCOUNT OPTIONS ------------------------ @@ -386,6 +255,88 @@ FEE_REFUND RSA_KEYSIZE What is the RSA keysize modulos (in bits)? + +MERCHANT OPTIONS +---------------- + +The following options are from the “[merchant]” section and used by the +merchant backend. + +DB + Plugin to use for the database, i.e._“postgres” + +PORT + Port on which the HTTP server listens, i.e. 8080. + +LEGAL_PRESERVATION + How long do we keep data in the database for tax audits after the + transaction has completed? Default is 10 years. + +FORCE_AUDIT + Force the merchant to report every transaction to the auditor + (if the exchange has an auditor). Default is NO. Do not change + except for testing. + + +MERCHANT POSTGRES BACKEND DATABASE OPTIONS +------------------------------------------ + +The following options must be in section “[merchantdb-postgres]” if the +“postgres” plugin was selected for the database. + +CONFIG + How to access the database, i.e. “postgres:///taler” to use the + “taler” database. Testcases use “talercheck”. + + +KNOWN EXCHANGES (for merchants) +------------------------------- + +The merchant configuration can include a list of known exchanges if the +merchant wants to specify that certain exchanges are explicitly trusted. +For each trusted exchange, a section [merchant-exchange-$NAME] must exist, where +$NAME is a merchant-given name for the exchange. The following options +must be given in each “[exchange-$NAME]” section. + +EXCHANGE_BASE_URL + Base URL of the exchange, i.e. “https://exchange.demo.taler.net/” + +MASTER_KEY + Crockford Base32 encoded master public key, public version of the + exchange´s long-time offline signing key. Can be omitted, in that + case the exchange will NOT be trusted unless it is audited by + a known auditor. + Omitting the MASTER_KEY can be useful if we do not trust the exchange + without an auditor, but should pre-load the keys of this + particular exchange on startup instead of waiting for it to be + required by a client. + +CURRENCY + Name of the currency for which this exchange is used, i.e. “KUDOS”. + The entire section is ignored if the currency does not match the currency + we use, which must be given in the [taler] section. + +KNOWN AUDITORS (for merchants) +------------------------------ + +The merchant configuration can include a list of known exchanges if the +merchant wants to specify that certain auditors are explicitly trusted. +For each trusted exchange, a section [merchant-auditor-$NAME] must exist, where +$NAME is a merchant-given name for the auditor. The following options +must be given in each “[merchant-auditor-$NAME]” section. + +AUDITOR_BASE_URL + Base URL of the auditor, i.e. “https://auditor.demo.taler.net/” + +AUDITOR_KEY + Crockford Base32 encoded auditor public key. + +CURRENCY + Name of the currency for which this auditor is trusted, i.e. “KUDOS” + The entire section is ignored if the currency does not match the currency + we use, which must be given in the [taler] section. + + AUDITOR OPTIONS --------------- @@ -398,6 +349,7 @@ DB AUDITOR_PRIV_FILE Name of the file containing the auditor’s private key + AUDITOR POSTGRES BACKEND DATABASE OPTIONS ----------------------------------------- @@ -408,6 +360,7 @@ CONFIG How to access the database, i.e. "postgres:///taler" to use the "taler" database. Testcases use “talercheck”. + SEE ALSO ======== @@ -417,5 +370,5 @@ taler-exchange-keyup(1), taler-exchange-wire(1). BUGS ==== -Report bugs by using https://gnunet.org/bugs/ or by sending electronic +Report bugs by using https://bugs.taler.net/ or by sending electronic mail to . -- cgit v1.2.3 From a846d00e60789fe2ba1a64c86df69da9a494280a Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Fri, 26 Jun 2020 18:59:18 +0530 Subject: transaction --- libeufin/iso20022.rst | 94 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 64 insertions(+), 30 deletions(-) diff --git a/libeufin/iso20022.rst b/libeufin/iso20022.rst index 304bd0d8..aa6df201 100644 --- a/libeufin/iso20022.rst +++ b/libeufin/iso20022.rst @@ -29,52 +29,86 @@ LibEuFin combines camt.052, camt.053 and camt.054, as they essentially have the same structure and serve the same purpose: Reporting transactions on a customer's bank account. -.. code-block:: typescript - - interface CashManagementResponseMessage { - // ISO: MessageIdentification - messageId: string; - - messageType: "report" | "statement" | "notification"; +We also flatten the hierarchy a bit and only have entries ("money movement in one go") +and transactions. - // ISO: CreationDateTime - creationDateTime: string; +.. code-block:: typescript - entries: Entry[]; + interface AccountTransactionItem { + // LibEuFin-internal identifier for the transaction + nexusTransactionId: string; - } + // Link to the entry that contains the transaction + nexusEntryId: string; - interface Entry { - transactions: Transaction[]; - } + // At least one of entryId or accountServicerRef + // must be non-null + entryId?: string; + accountServicerRef?: string; - interface Transaction { creditDebitIndicator: "credit" | "debit"; amount: string; currency: string; - - bookingDate?: string; + instructedAmountDetails?: { + amount: string; + currency: string; + currencyExchange?: { + sourceCurrency: string; + targetCurrency: string; + unitCurrency: string; + exchangeRate: string; + contractId: string; + quotationDate: string; + }; + }; + status: "booked" | "pending" | "info"; valueDate?: string; + bookingDate?: string; + mandateId?: string; + endToEndId?: string; + messageId?: string; - accountServicerRef?: string; + creditor?: Party + creditorAgent?: FinancialInstitution; + creditorAccount?: FinancialInstitution; - bankTransactionCode: BankTransactionCode; + debtor?: Party + debtorAgent?: FinancialInstitution; + debtorAccount?: FinancialInstitution; - details: TransactionDetails[]; + unstructuredRemittanceInformation?: string; + bankTransactionCode: BankTransactionCode; } - interface TransactionDetails { - creditDebitIndicator: "credit" | "debit"; - amount: string; - currency: string; - - // Referenced message ID - messageId: string; + interface Party { + name?: string; + partyType: "private" | "organization"; + otherId?: { + id: string; + schemeName?: string; + issuer?: string; + }; + } - endToEndId: string; - paymentIdentificationId?: string; + interface Account { + name?: string; + currency?: string; + otherId?: { + id: string; + schemeName?: string; + issuer?: string; + }; + } - bankTransactionCode: BankTransactionCode; + interface FinancialInstitution { + type: "financial-institution"; + name?: string; + bic?: string; + otherId?: { + id: string; + schemeName?: string; + issuer?: string; + }; } interface BankTransactionCode { -- cgit v1.2.3 From f5663ec399529456a23819a795baf47d81631b66 Mon Sep 17 00:00:00 2001 From: MS Date: Fri, 26 Jun 2020 15:42:03 +0200 Subject: consistent renaming --- libeufin/api-nexus.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index 61d55e25..313b3898 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -83,13 +83,13 @@ manages payment initiations of the account and tracks the of payment initiations interface BankAccount { // mnemonic name identifying this bank account. - account: string; + nexusBankAccountId: string; // IBAN iban: string; // BIC bic: string; // Legal subject owning the account. - holder: string; + ownerName: string; } .. http:post:: {nexusBase}/bank-accounts/{acctid}/payment-initiations/{pmtid}/submit -- cgit v1.2.3 From 704a5e1eceed1a6f73d7998ce3068e848ac03e87 Mon Sep 17 00:00:00 2001 From: Dennis Neufeld Date: Fri, 26 Jun 2020 14:51:17 +0000 Subject: modified anastasis spec - authentication methods --- anastasis-db.png | Bin 52516 -> 58761 bytes anastasis.rst | 15 ++++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/anastasis-db.png b/anastasis-db.png index 4a2fc5c1..a3ab262c 100644 Binary files a/anastasis-db.png and b/anastasis-db.png differ diff --git a/anastasis.rst b/anastasis.rst index d0012c7a..bb206db3 100644 --- a/anastasis.rst +++ b/anastasis.rst @@ -803,10 +803,19 @@ SMS (sms) ^^^^^^^^^ Sends an SMS with a code to the users phone. -The must send this code back with his request (see $RESPONSE under 'Managing truth'). +The user must send this code back with his request (see $RESPONSE under 'Managing truth'). If the transmitted code is correct, the server responses with the requested encrypted key share. FIXME: details! + +Email verification (email) +^^^^^^^^^^^^^^^^^^^^^^^^^^ +Sends an email with a code to the users mail address. +The user must send this code back with his request (see $RESPONSE under 'Managing truth'). +If the transmitted code is correct, the server responses with the requested encrypted key share. +FIXME: details! + + Video identification (vid) ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -827,8 +836,8 @@ function over the same security answer is used to provide **optional data** for the decryption of the (encrypted) **key share**. -Post-Indent (post) -^^^^^^^^^^^^^^^^^^ +Snail mail verification (post) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Physical address verification via snail mail. FIXME: details! -- cgit v1.2.3 From 18012a7d0568cda761b6f7886fa445e4e8f8ff65 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 26 Jun 2020 17:42:30 +0200 Subject: terminology for merchant backend --- taler-merchant-api-tutorial.rst | 23 +++- taler-merchant-manual.rst | 289 +++++++++++++++++++++++++++++++--------- 2 files changed, 247 insertions(+), 65 deletions(-) diff --git a/taler-merchant-api-tutorial.rst b/taler-merchant-api-tutorial.rst index 6442e7c2..eb9505ce 100644 --- a/taler-merchant-api-tutorial.rst +++ b/taler-merchant-api-tutorial.rst @@ -1,5 +1,26 @@ +.. + This file is part of GNU TALER. + Copyright (C) 2014-2020 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 + + @author Marcello Stanisci + @author Florian Dold + @author Christian Grothoff + +.. _merchant-api-tutorial: + GNU Taler Merchant API Tutorial -################################### +############################### Introduction ============ diff --git a/taler-merchant-manual.rst b/taler-merchant-manual.rst index 7e3eac6d..6ffd193d 100644 --- a/taler-merchant-manual.rst +++ b/taler-merchant-manual.rst @@ -73,21 +73,24 @@ components: enables the customer to build a shopping cart and place an order. Upon payment, it triggers the respective business logic to satisfy the order. This component is not included with Taler, but rather - assumed to exist at the merchant. This manual describes how to - integrate Taler with Web shop frontends. + assumed to exist at the merchant. + The `Merchant API Tutorial <#merchant-api-tutorial>`__ gives an + introduction for how to integrate Taler with Web shop frontends. - A back office application that enables the shop operators to view customer orders, match them to financial transfers, and possibly approve refunds if an order cannot be satisfied. This component is - again not included with Taler, but rather assumed to exist at the - merchant. This manual will describe how to integrate such a component - to handle payments managed by Taler. + not included with Taler, but rather assumed to exist at the + merchant. The `Merchant Backend API <#merchant-api>`__ provides + the API specification that should be reviewed to integrate such a + back office with the Taler backend. - A Taler-specific payment backend which makes it easy for the frontend - to process financial transactions with Taler. The next two chapters - will describe how to install and configure this backend. + to process financial transactions with Taler. This manual primarily + describes how to install and configure this backend. - A DBMS which stores the transaction history for the Taler backend. For now, the GNU Taler reference implemenation only supports Postgres, but the code could be easily extended to support another - DBMS. + DBMS. Please review the Postgres documentation for details on + how to configure the database. The following image illustrates the various interactions of these key components: @@ -96,13 +99,150 @@ components: .. index:: RESTful -Basically, the backend provides the cryptographic protocol support, -stores Taler-specific financial information in a DBMS and communicates -with the GNU Taler exchange over the Internet. The frontend accesses the -backend via a RESTful API. As a result, the frontend never has to -directly communicate with the exchange, and also does not deal with -sensitive data. In particular, the merchant’s signing keys and bank -account information is encapsulated within the Taler backend. +Basically, the backend provides the cryptographic protocol support, stores +Taler-specific financial information in a DBMS and communicates with the GNU +Taler exchange over the Internet. The frontend accesses the backend via a +RESTful API. As a result, the frontend never has to directly communicate with +the exchange, and also does not deal with sensitive data. In particular, the +merchant’s signing keys and bank account information is encapsulated within +the Taler backend. + +A typical deployment will additionally include a full-blown Web server (like +Apache or Nginx). Such a Web server would be responsible for TLS termination +and access control to the /private/ API endpoints of the merchant backend. +Please carefully review the section on `Secure setup <#Secure-setup>`__ before +deploying a Taler merchant backend to production. + + +Terminology +=========== + +This chapter describes some of the key concepts used throughout the manual. + +Instances +--------- + +.. index:: instance + +The backend allows the user to run multiple *instances* of shops with distinct +business entities sharing a single backend. Each instance uses its own bank +accounts and key for signing contracts. All major accounting functionality is +separate per instance. What is shared is the database, HTTP(S) address and +the main Taler configuration (accepted currency, exchanges and auditors). + +Accounts +-------- + +.. index:: account + +To receive payments, an instance must have configured one or more bank +*accounts*. The backend does not have accounts for users, and instances are +also not really 'accounts'. So whenever we use the term *account*, it is about +a bank account of a merchant. + +Inventory +--------- + +.. index:: inventory +.. index:: product +.. index:: lock +.. index:: unit +.. index:: order + +The Taler backend offers inventory management as an optional function. +Inventory is tracked per instance and consists of *products* sold in +*units*. Inventory can be finite or infinite (for digital products). +Products may include previews (images) to be shown to the user and other +meta-data. Inventory management allows the frontend to *lock* products, +reserving them for a particular (unpaid) *order*. The backend can keep +track of how many units of a product remain in stock and ensure that +the number of units sold does not exceed the number of units in stock. + +Inventory management is optional, and it is possible for the frontend to +include products in orders that are not in the inventory, or to override +prices of products in the inventory. + +Orders and Contracts +-------------------- + +.. index:: order +.. index:: contract +.. index:: claim +.. index:: pay +.. index:: refund +.. index:: wire deadline +.. index:: lock +.. index:: legal expiration + +In Taler, users pay merchants for orders. An order is first created by the +merchant, where the merchant specifies the specific terms of the order. + +After an order is created, it is *claimed* by a wallet. Once an order is +claimed by a specific wallet, only that wallet will be able to pay for this +order, to the exclusion of other wallets even if they see the same order URL. + +A wallet may *pay* for a claimed order, at which point the order turns into +a (paid) contract. Orders have an expiration date after which the commercial +offer expires and any stock of products *locked* by the order is released, +allowing the stock to be sold in other orders. + +Once a contract has been paid, the merchant should fulfill the contract. It +is possible for the merchant to *refund* a contract order, for example if the +contract cannot be fulfilled after all. Refunds are only possible until the +exchange has *wired* the payment to the merchant. Once the funds have been +wired, refunds are no longer allowed by the Taler exchange. The *wire +deadline* specifies the latest time by which an exchange must wire the funds, +while the (earlier) *refund deadline* specifies the earliest time when an +exchange may wire the funds. + +Contract information is kept for legal reasons, typically to provide tax +records in case of a tax audit. After the *legal expiration* (by default a +decade), contract information is deleted. + +Transfers +--------- + +.. index:: transfer +.. index:: wire transfer + +The Taler backend can be used to verify that the exchange correctly wired all +of the funds to the merchant. However, the backend does not have access to the +incoming wire transfers of the merchant's bank account. Thus, merchants must +manually provide the backend with wire *transfer* data that specifies the wire +transfer subject and the amount that was received. Given this information, the +backend can detect and report any irregularities that might arise. + +Tipping +------- + +.. index:: tip +.. index:: grant +.. index:: pick up + +Taler does not only allow a Website to be paid, but also to make voluntary, +non-contractual payments to visitors, called *tips*. Such tips could be +granted as a reward for filling in surveys or watching advertisements. For +tips, there is no contract, tips are always voluntary actions by the Web +site that do not arise from a contractual obligation. Before a Web site +can create tips, it must establish a reserve. Once a reserve has been +established, the merchant can *grant* tips, allowing wallets to *pick up* +the tip. + +Reserves +-------- + +.. index:: reserve +.. index:: close + +A *reserve* is a pool of electronic cash at an exchange under the control of +a private key. Merchants withdraw coins from a reserve when granting +tips. A reserve is established by first generating the required key material +in the merchant backend, and then wiring the desired amount of funds to the +exchange. + +An exchange will automatically *close* a reserve after a fixed period of time +(typically about a month), wiring any remaining funds back to the merchant. + Installation ============ @@ -211,17 +351,17 @@ Installing the GNU Taler exchange After installing GNUnet, you can download and install the exchange as follows: -:: + :: - $ git clone https://git.taler.net/exchange/ - $ cd exchange - $ ./bootstrap - $ ./configure [--prefix=EXCHANGEPFX] \ - [--with-gnunet=GNUNETPFX] - $ # Each dependency can be fetched from non standard locations via - $ # the '--with-' option. See './configure --help'. - $ make - # make install + $ git clone https://git.taler.net/exchange/ + $ cd exchange + $ ./bootstrap + $ ./configure [--prefix=EXCHANGEPFX] \ + [--with-gnunet=GNUNETPFX] + $ # Each dependency can be fetched from non standard locations via + $ # the '--with-' option. See './configure --help'. + $ make + # make install If you did not specify a prefix, the exchange will install to ``/usr/local``, which requires you to run the last step as ``root``. You have to specify @@ -244,18 +384,18 @@ The following steps assume all dependencies are installed. Use the following commands to download and install the merchant backend: -:: + :: - $ git clone https://git.taler.net/merchant/ - $ cd merchant - $ ./bootstrap - $ ./configure [--prefix=PFX] \ - [--with-gnunet=GNUNETPFX] \ - [--with-exchange=EXCHANGEPFX] - $ # Each dependency can be fetched from non standard locations via - $ # the '--with-' option. See './configure --help'. - $ make - # make install + $ git clone https://git.taler.net/merchant/ + $ cd merchant + $ ./bootstrap + $ ./configure [--prefix=PFX] \ + [--with-gnunet=GNUNETPFX] \ + [--with-exchange=EXCHANGEPFX] + $ # Each dependency can be fetched from non standard locations via + $ # the '--with-' option. See './configure --help'. + $ make + # make install If you did not specify a prefix, the exchange will install to ``/usr/local``, which requires you to run the last step as ``root``. @@ -287,7 +427,7 @@ On Debian jessie, only GNU libmicrohttpd needs to be compiled from source. To install dependencies on Debian jesse, run the following commands: -:: + :: # apt-get install \ autoconf \ @@ -313,7 +453,7 @@ commands: For more recent versions of Debian, you should instead run: -:: + :: # apt-get install \ autoconf \ @@ -587,7 +727,7 @@ Sample backend configuration The following is an example for a complete backend configuration: -:: + :: [TALER] CURRENCY = KUDOS @@ -634,9 +774,9 @@ Launching the backend .. index:: taler-merchant-httpd Assuming you have configured everything correctly, you can launch the -merchant backend as ``$USER`` using: +merchant backend as ``$USER`` using -:: + :: $ taler-merchant-httpd @@ -647,13 +787,13 @@ system for how to start and stop daemons. If everything worked as expected, the command -:: + :: $ curl http://localhost:8888/ should return the message -:: + :: Hello, I'm a merchant's Taler backend. This HTTP server is not for humans. @@ -662,21 +802,19 @@ Production systems should be configured to bind to a UNIX domain socket and use TLS for improved network privacy, see `Secure setup <#Secure-setup>`__. -.. _Instances: +.. index:: instance +.. _Instance-setup: -Instances -========= +Instance setup +============== -The backend allows the user to run multiple instances of shops with -distinct business entities against a single backend. Each instance -uses its own bank accounts and key for signing contracts. It is -mandatory to configure at least the "default" instance. +Before using the backend, you must at least configure the "default" instance. Instances can be configured by POSTing the necessary requests to the backend. To create a first instance, create a file ``instance.json`` -with an `InstanceConfigurationMessage`: +with an `InstanceConfigurationMessage` -:: + :: { payto_uris : [ "payto://iban/IBANNUMBERHERE" ], @@ -693,7 +831,8 @@ with an `InstanceConfigurationMessage`: You can then create the instance using: -:: + :: + $ wget --post-file=instance.json http://localhost:8888/private/instances The base URL for the instance will then be @@ -719,14 +858,6 @@ The bank account information is provided in the form of a ``payto://``-URL. See RFC XXXX for the format of ``payto://``-URLs. -.. _Inventory: - -Inventory management -==================== - - - - .. _Secure-setup: @@ -736,14 +867,26 @@ Secure setup .. index:: security .. index:: TLS -For additional security, you may want to have the backend bind to a UNIX -domain socket and use an HTTP reverse proxy for TLS termination: +The Taler backend does not include even the most basic forms of +access control or transport layer security. Thus, production +setups **must** deploy the Taler backend behind an HTTP(S) server +that acts as a *reverse proxy*, performs TLS termination and +authentication and then forwards requests to the backend. + +Using UNIX domain sockets +------------------------- + +To ensure that the merchant backend is not exposed directly to the network, +you should bind the backend to a UNIX domain socket: :: $ taler-config -s MERCHANT -o SERVE -V UNIX $ taler-config -s MERCHANT -o UNIXPATH -V /some/path/here.sock +Reverse proxy configuration +--------------------------- + Assuming your domain name is /example.com/ and you have TLS configured, a possible reverse proxy directive for Nginx would be: @@ -757,7 +900,25 @@ a possible reverse proxy directive for Nginx would be: Leave out the last line if your Nginx reverse proxy does not have HTTPS enabled. Make sure to restart the /taler-merchant-httpd/ process after -changing the configuration. +changing the ``SERVE`` configuration. + +Access control +-------------- + +All endpoints with /private/ in the URL must be restricted to authorized users +of the respective instance. Specifically, the HTTP server must be configured +to only allow access to ``$BASE_URL/private/`` to the authorized users of the +default instance, and to ``$BASE_URL/instances/$ID/private/`` to the +authorized users of the instance ``$ID``. + +How access control is done (TLS client authentication, HTTP basic or digest +authentication, etc.) is completely up to the merchant and does not matter to +the Taler merchant backend. + +Note that all of the other endpoints (without /private/) are expected to be +fully exposed to the Internet, and wallets may have to interact with those +endpoints directly without client authentication. + Upgrade procedure -- cgit v1.2.3 From 0c7af9e8bba6007afd2820dd189d93614a3017ee Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 26 Jun 2020 20:28:11 +0200 Subject: update merchant documentation --- core/api-merchant.rst | 8 +++---- taler-merchant-manual.rst | 58 +++++++++++++++++++++++++++++++---------------- 2 files changed, 41 insertions(+), 25 deletions(-) diff --git a/core/api-merchant.rst b/core/api-merchant.rst index 5c50709a..c56cff0c 100644 --- a/core/api-merchant.rst +++ b/core/api-merchant.rst @@ -24,10 +24,7 @@ Merchant Backend API ==================== WARNING: This document describes the version 1 of the merchant backend -API, which is NOT yet implemented at all! - -TODO: https://bugs.gnunet.org/view.php?id=5987#c15127 - is not yet addressed by this specification! +API, which is NOT yet implemented in Git master! The ``*/private/*`` endpoints are only supposed to be exposed to the merchant internally, and must not be exposed on the @@ -35,7 +32,8 @@ Internet. Most endpoints given here can be prefixed by a base URL that includes the specific instance selected (BASE_URL/instances/$INSTANCE/). If -``/instances/`` is missing, the default instance is to be used. +``/instances/`` is missing from the request path, the ``default`` instance is +used. .. contents:: Table of Contents diff --git a/taler-merchant-manual.rst b/taler-merchant-manual.rst index 6ffd193d..8652e13d 100644 --- a/taler-merchant-manual.rst +++ b/taler-merchant-manual.rst @@ -74,13 +74,13 @@ components: Upon payment, it triggers the respective business logic to satisfy the order. This component is not included with Taler, but rather assumed to exist at the merchant. - The `Merchant API Tutorial <#merchant-api-tutorial>`__ gives an + The :ref:`Merchant API Tutorial ` gives an introduction for how to integrate Taler with Web shop frontends. - A back office application that enables the shop operators to view customer orders, match them to financial transfers, and possibly approve refunds if an order cannot be satisfied. This component is not included with Taler, but rather assumed to exist at the - merchant. The `Merchant Backend API <#merchant-api>`__ provides + merchant. The :ref:`Merchant Backend API ` provides the API specification that should be reviewed to integrate such a back office with the Taler backend. - A Taler-specific payment backend which makes it easy for the frontend @@ -110,7 +110,7 @@ the Taler backend. A typical deployment will additionally include a full-blown Web server (like Apache or Nginx). Such a Web server would be responsible for TLS termination and access control to the /private/ API endpoints of the merchant backend. -Please carefully review the section on `Secure setup <#Secure-setup>`__ before +Please carefully review the section on :ref:`Secure setup ` before deploying a Taler merchant backend to production. @@ -799,7 +799,7 @@ should return the message Please note that your backend is right now likely globally reachable. Production systems should be configured to bind to a UNIX domain socket -and use TLS for improved network privacy, see `Secure setup <#Secure-setup>`__. +and use TLS for improved network privacy, see :ref:`Secure setup `. .. index:: instance @@ -810,9 +810,9 @@ Instance setup Before using the backend, you must at least configure the "default" instance. -Instances can be configured by POSTing the necessary requests to the -backend. To create a first instance, create a file ``instance.json`` -with an `InstanceConfigurationMessage` +Instances can be configured by POSTing a request to +:http:post:`/private/instances`. To create a first instance, create a file +``instance.json`` with an `InstanceConfigurationMessage` :: @@ -841,7 +841,7 @@ instances by changing the "id" value to identifies other than "default". Endpoints to modify (reconfigure), permanently disable (while keeping the data) or purge (deleting all associated data) instances exist as well and are documented -in the `Merchant Backend API documentation <#merchant-api>`__. +in the :ref:`Merchant Backend API documentation `. Accounts @@ -959,17 +959,13 @@ Tipping visitors .. index:: tipping -NOTE: This section is dated and should be reviewed! - Taler can also be used to tip Web site visitors. For example, you may be running an online survey, and you want to reward those people that have dutifully completed the survey. If they have installed a Taler wallet, you can provide them with a tip for their deeds. This section describes how to setup the Taler merchant backend for tipping. -There are four basic steps that must happen to tip a visitor. - -FIXME: write current explanation! +There are three basic steps that must happen to tip a visitor. .. _Fund-the-reserve: @@ -977,7 +973,27 @@ Fund the reserve ---------------- .. index:: reserve -.. index:: close + +First, the reserve must be setup in the merchant backend. A reserve +is always tied to a particular instance. To create a reserve with +10 KUDOS at instance "default" using the demo exchange, use: + + :: + + $ taler-merchant-setup-reserve \ + -a KUDOS:10 \ + -e https://exchange.demo.taler.net/ \ + -m http://localhost:8888/instances/default + +The above command assumes that the merchant runs on localhost on +port 8888. The current implementation of the tool does not yet support +transmission of authentication information to the backend +(`see bug 6418 `_). + +The command will output a payto:// URI which specifies where to +wire the funds and which wire transfer subject to use. + +FIXME: add full example output. In our example, the output for the wire transfer subject is: @@ -986,7 +1002,7 @@ In our example, the output for the wire transfer subject is: QPE24X8PBX3BZ6E7GQ5VAVHV32FWTTCADR0TRQ183MSSJD2CHNEG You now need to make a wire transfer to the exchange’s bank account -using the public key as the wire transfer subject. +using the given wire transfer subject. Make your wire transfer and (optionally) check at “https://exchange/reserves/QPE24X...” whether your transfer has arrived at the @@ -1008,7 +1024,8 @@ Authorize a tip When your frontend has reached the point where a client is supposed to receive a tip, it needs to first authorize the tip. For this, the frontend must use -the “/private/reserves/$RID/tip-authorize” API of the backend. To authorize a +the :http:post:`/private/reserves/$RESERVE_PUB/authorize-tip` +API of the backend. To authorize a tip, the frontend has to provide the following information in the body of the POST request: @@ -1037,7 +1054,8 @@ missconfigured instances or a lack of remaining funds for tipping. Picking up of the tip --------------------- -The wallet will POST a JSON object to the shop’s “/tips/$TIP/pickup” handler. +The wallet will POST a JSON object to the shop’s +:http:post:`/tips/$TIP_ID/pickup` handler. The frontend must then forward this request to the backend. The response generated by the backend can then be forwarded directly to the wallet. @@ -1128,7 +1146,7 @@ Note that, in this stage of development, the file component. For example, both an exchange and a bank can read values from it. -The repository ``git://taler.net/deployment`` contains examples of +The `deployment repository `_ contains examples of configuration file used in our demos. See under ``deployment/config``. **Note** @@ -1416,12 +1434,12 @@ Before starting to build the merchant’s image, make sure a “docker-machine“ instance is up and running. Because all of the Docker source file are kept in our “deployment“ -repository, we start by checking out the ``git://taler.net/deployment`` +repository, we start by checking out the ``git://git.taler.net/deployment`` codebase: :: - $ git clone git://taler.net/deployment + $ git clone git://git.taler.net/deployment Now we actually build the merchant’s image. From the same directory as above: -- cgit v1.2.3 From 3f1f866aa002236da754b26284823b83c6010a2b Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 28 Jun 2020 22:06:31 +0200 Subject: bump required version --- taler-exchange-manual.rst | 2 +- taler-merchant-manual.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/taler-exchange-manual.rst b/taler-exchange-manual.rst index 86abce8d..703b3267 100644 --- a/taler-exchange-manual.rst +++ b/taler-exchange-manual.rst @@ -176,7 +176,7 @@ exchange compilation. - libcurl >= 7.26 (or libgnurl >= 7.26) -- GNU libmicrohttpd >= 0.9.59 +- GNU libmicrohttpd >= 0.9.71 - GNU libgcrypt >= 1.6 diff --git a/taler-merchant-manual.rst b/taler-merchant-manual.rst index 8652e13d..a064efce 100644 --- a/taler-merchant-manual.rst +++ b/taler-merchant-manual.rst @@ -284,7 +284,7 @@ backend: - libcurl >= 7.26 (or libgnurl >= 7.26) -- GNU libmicrohttpd >= 0.9.59 +- GNU libmicrohttpd >= 0.9.71 - GNU libgcrypt >= 1.6 -- cgit v1.2.3 From d5f27446c11bdcaacee3ce97bce1d2f94a3f87ef Mon Sep 17 00:00:00 2001 From: MS Date: Tue, 30 Jun 2020 16:37:25 +0200 Subject: bank connection delete API --- libeufin/api-nexus.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index 313b3898..44f5f474 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -300,6 +300,16 @@ to the real bank. :status 409 Conflict: The ``name`` field exists already for the requesting user. +.. http:post:: {nexusBase}/bank-connections/delete + + **Request:** + + .. ts:def:: BankConnectionDeletion + + interface BankConnectionDeletion { + // label of the bank connection to delete + bankConnectionId: string; + } .. http:get:: {nexusBase}/bank-connections -- cgit v1.2.3 From 03df919cc969a43b3e40322c5be0b62ad0e03c9a Mon Sep 17 00:00:00 2001 From: MS Date: Tue, 30 Jun 2020 17:22:58 +0200 Subject: align to $verb-$object uri style --- libeufin/api-nexus.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index 44f5f474..666fe1f3 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -300,7 +300,7 @@ to the real bank. :status 409 Conflict: The ``name`` field exists already for the requesting user. -.. http:post:: {nexusBase}/bank-connections/delete +.. http:post:: {nexusBase}/bank-connections/delete-connection **Request:** -- cgit v1.2.3 From 823f1a1b17212b26c9062d185b8516fe906aeaae Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Fri, 3 Jul 2020 00:21:18 +0530 Subject: notes on amount handling --- libeufin/iso20022.rst | 77 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 73 insertions(+), 4 deletions(-) diff --git a/libeufin/iso20022.rst b/libeufin/iso20022.rst index aa6df201..d87098a3 100644 --- a/libeufin/iso20022.rst +++ b/libeufin/iso20022.rst @@ -32,15 +32,84 @@ on a customer's bank account. We also flatten the hierarchy a bit and only have entries ("money movement in one go") and transactions. +Types of amounts in camt messages +--------------------------------- + +* Entry amount + + * ISO 20022: Mandatory, with debit/credit indicator. Indicates money + moving in/out of the account in the account's currency. + * LibEuFin: Same. + +* Entry transaction amount + + * ISO 20022: Optional, direction-less. Amount of money + moving between the debtor and creditor bank, may not be + in the account's currency (but the "native" currency between + the two banks). + * LibEuFin: Same. + +* Entry instructed amount + + * ISO 20022: Optional, direction-less. Amount of money specified in the + payment initiation message. Usually only specified when the amount is in a + different currency than the account currency. + * LibEuFin: Same. + +* Entry counter value amount + + * ISO 20022: Optional, direction-less. Amount in the account's + currency before charges. + * LibEuFin: Same. + +* Entry announced posting amount + + * (not used by LibEuFin) + +* EntryDetails amount + + * ISO 20022: Optional, with debit-credit indicator. Same as "Entry amount" + but for EntryDetails (= logical transactions). + * LibEuFin: Always present. In Swiss camt messages, the element is always + present. In German/Swedish/... camt, we take the "Entry amount" for + non-batch entries, whereas in batch entries we use the "EntryDetails + transaction amount" with the same debit credit indicator as the whole + entry, which by local rules is always in the bank account currency. + +* EntryDetails (transaction / instructed / counter value) amount + + * ISO 20022: Optional, direction-less. Same as "Entry ... amount" + but for EntryDetails (= logical transactions). + * Same. + +* EntryDetails announced posting amount + + * (not used by LibEuFin) + + +LibEuFin schema for account history +----------------------------------- + +FIXME: This is not complete yet. + .. code-block:: typescript - interface AccountTransactionItem { - // LibEuFin-internal identifier for the transaction - nexusTransactionId: string; + interface NexusTransactionsReponse { + entries: NexusAccountEntryItem[]; + } - // Link to the entry that contains the transaction + interface NexusAccountEntryItem { nexusEntryId: string; + // Serial number that will increase with each update + // to the entry. + nexusStatusSequenceId: number; + + entry: AccountEntryItem; + } + + interface AccountEntryItem { + // At least one of entryId or accountServicerRef // must be non-null entryId?: string; -- cgit v1.2.3 From a1c6d92237982d46ed36565d5c8e693b7267d4ee Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 4 Jul 2020 23:36:43 +0200 Subject: fix section name --- manpages/taler.conf.5.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manpages/taler.conf.5.rst b/manpages/taler.conf.5.rst index d880bc17..bfdece3c 100644 --- a/manpages/taler.conf.5.rst +++ b/manpages/taler.conf.5.rst @@ -146,7 +146,7 @@ EXCHANGE ACCOUNT OPTIONS ------------------------ An exchange (or merchant) can have multiple bank accounts. The following -options are for sections named “[account-SOMETHING]”. The SOMETHING is +options are for sections named “[exchange-account-SOMETHING]”. The SOMETHING is arbitrary and should be chosen to uniquely identify the bank account for the operator. -- cgit v1.2.3 From a951ebe385efd96dbe84ed9798efe0949feae824 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 4 Jul 2020 23:55:17 +0200 Subject: begin to document benchmark setup --- manpages/taler.conf.5.rst | 3 +++ taler-merchant-manual.rst | 37 ++++++++++++++++++++++++++++++++++--- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/manpages/taler.conf.5.rst b/manpages/taler.conf.5.rst index bfdece3c..82bff393 100644 --- a/manpages/taler.conf.5.rst +++ b/manpages/taler.conf.5.rst @@ -239,6 +239,9 @@ DURATION_WITHDRAW DURATION_SPEND How long do clients have to spend these coins? +DURATION_LEGAL + How long does the exchange have to keep records for this denomination? + FEE_WITHDRAW What fee is charged for withdrawal? diff --git a/taler-merchant-manual.rst b/taler-merchant-manual.rst index a064efce..d6ea1bf7 100644 --- a/taler-merchant-manual.rst +++ b/taler-merchant-manual.rst @@ -1221,6 +1221,40 @@ Benchmarking NOTE: This section is dated and should be reviewed! +Setup: create Exchange account and two user accounts ``42`` and ``43`` at +the bank: + +:: + + $ taler-bank-manage django add_bank_account Exchange + $ taler-bank-manage django add_bank_account 42 + $ taler-bank-manage django add_bank_account 43 + +Setup exchange password using: + +:: + + $ taler-bank-manage django changepassword_unsafe Exchange PASSWORD + +Configure merchant and exchange, then run: + +:: + + $ taler-exchange-dbinit + $ taler-exchange-keyup + $ taler-merchant-dbinit + +Launch bank, exchange and merchant backends: + +:: + + $ taler-bank-manage serve-http + $ taler-exchange-httpd + $ taler-merchant-httpd + + + + The merchant codebase offers the ``taler-merchant-benchmark`` tool to populate the database with fake payments. This tool is in charge of starting a merchant, exchange, and bank processes, and provide them all @@ -1230,9 +1264,6 @@ own configuration (as they would do in production). The tool takes all of the values it needs from the command line, with some of them being mandatory. Among those, we have: -- ``--currency=K`` Use currency *K*, for example to craft coins to - withdraw. - - ``--bank-url=URL`` Assume that the bank is serving under the base URL *URL*. This option is only actually used by the tool to check if the bank was well launched. -- cgit v1.2.3 From ec491ae8d7fe7444db68a8a4683c3dcafb994b3c Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 4 Jul 2020 23:59:23 +0200 Subject: wip --- taler-merchant-manual.rst | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/taler-merchant-manual.rst b/taler-merchant-manual.rst index d6ea1bf7..f48fb07a 100644 --- a/taler-merchant-manual.rst +++ b/taler-merchant-manual.rst @@ -1221,6 +1221,13 @@ Benchmarking NOTE: This section is dated and should be reviewed! +FIXME: which coin denominations are needed for the benchmark? + +FIXME: provide "minimum" configuration file! + +FIXME: explain Postgres setup! + + Setup: create Exchange account and two user accounts ``42`` and ``43`` at the bank: @@ -1248,11 +1255,9 @@ Launch bank, exchange and merchant backends: :: - $ taler-bank-manage serve-http - $ taler-exchange-httpd - $ taler-merchant-httpd - - + $ taler-bank-manage serve-http & + $ taler-exchange-httpd & + $ taler-merchant-httpd & The merchant codebase offers the ``taler-merchant-benchmark`` tool to -- cgit v1.2.3 From ce15fc3472f93b3d213d220f6a144cf58a0b5706 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 5 Jul 2020 12:19:55 +0200 Subject: improve documentation of taler.conf --- manpages/taler.conf.5.rst | 161 ++++++++++++++++++++++------------------------ 1 file changed, 77 insertions(+), 84 deletions(-) diff --git a/manpages/taler.conf.5.rst b/manpages/taler.conf.5.rst index 82bff393..174587ed 100644 --- a/manpages/taler.conf.5.rst +++ b/manpages/taler.conf.5.rst @@ -27,31 +27,31 @@ The following options are from the “[taler]” section and used by virtually all Taler components. CURRENCY - Name of the currency, i.e. “EUR” for Euro. + Name of the currency, i.e. “EUR” for Euro. The “[PATHS]” section is special in that it contains paths that can be referenced using “$” in other configuration values that specify filenames. For Taler, it commonly contains the following paths: TALER_HOME - Home directory of the user, usually “${HOME}”. Can be overwritten by - testcases by setting ${TALER_TEST_HOME}. + Home directory of the user, usually “${HOME}”. Can be overwritten by + testcases by setting ${TALER_TEST_HOME}. TALER_DATA_HOME - Where should Taler store its long-term data. Usually - “${TALER_HOME}/.local/share/taler/” + Where should Taler store its long-term data. Usually + “${TALER_HOME}/.local/share/taler/” TALER_CONFIG_HOME - Where is the Taler configuration kept. Usually - “${TALER_HOME}/.config/taler/” + Where is the Taler configuration kept. Usually + “${TALER_HOME}/.config/taler/” TALER_CACHE_HOME - Where should Taler store cached data. Usually - “${TALER_HOME}/.cache/taler/” + Where should Taler store cached data. Usually + “${TALER_HOME}/.cache/taler/” TALER_RUNTIME_DIR - Where should Taler store system runtime data (like UNIX domain - sockets). Usually “${TMP}/taler-system-runtime”. + Where should Taler store system runtime data (like UNIX domain + sockets). Usually “${TMP}/taler-system-runtime”. EXCHANGE OPTIONS ---------------- @@ -60,42 +60,42 @@ The following options are from the “[exchange]” section and used by most exchange tools. DB - Plugin to use for the database, i.e. “postgres” + Plugin to use for the database, i.e. “postgres” PORT - Port on which the HTTP server listens, i.e. 8080. + Port on which the HTTP server listens, i.e. 8080. MASTER_PUBLIC_KEY - Crockford Base32-encoded master public key, public version of the - exchange´s long-time offline signing key. + Crockford Base32-encoded master public key, public version of the + exchange´s long-time offline signing key. MASTER_PRIV_FILE - Location of the master private key on disk. Only used by tools that - can be run offline (as the master key is for offline signing). + Location of the master private key on disk. Only used by tools that + can be run offline (as the master key is for offline signing). BASE_URL - Specifies the base URL under which the exchange can be reached. Added - to wire transfers to enable tracking by merchants. + Specifies the base URL under which the exchange can be reached. Added + to wire transfers to enable tracking by merchants. AGGREGATOR_IDLE_SLEEP_INTERVAL - For how long should the aggregator sleep when it is idle before trying - to look for more work? Default is 60 seconds. + For how long should the aggregator sleep when it is idle before trying + to look for more work? Default is 60 seconds. SIGNKEY_DURATION - For how long is a signing key valid? + For how long is a signing key valid? LEGAL_DURATION - For how long are signatures with signing keys legally valid? + For how long are signatures with signing keys legally valid? LOOKAHEAD_SIGN - How long do we generate denomination and signing keys ahead of time? + How long do we generate denomination and signing keys ahead of time? LOOKAHEAD_PROVIDE - How long into the future do we provide signing and denomination keys - to clients? + How long into the future do we provide signing and denomination keys + to clients? TERMS_DIR - Directory where the terms of service of the exchange operator can be fund. The directory must contain sub-directories for every supported language, using the two-character language code in lower case, i.e. "en/" or "fr/". Each subdirectory must then contain files with the terms of service in various formats. The basename of the file of the current policy must be specified under TERMS_ETAG. The extension defines the mime type. Supported extensions include "html", "htm", "txt", "pdf", "jpg", "jpeg", "png" and "gif". For example, using a TERMS_ETAG of "0", the structure could be the following: + Directory where the terms of service of the exchange operator can be fund. The directory must contain sub-directories for every supported language, using the two-character language code in lower case, i.e. "en/" or "fr/". Each subdirectory must then contain files with the terms of service in various formats. The basename of the file of the current policy must be specified under TERMS_ETAG. The extension defines the mime type. Supported extensions include "html", "htm", "txt", "pdf", "jpg", "jpeg", "png" and "gif". For example, using a TERMS_ETAG of "0", the structure could be the following: - $TERMS_DIR/en/0.pdf - $TERMS_DIR/en/0.html - $TERMS_DIR/en/0.txt @@ -104,12 +104,12 @@ TERMS_DIR - $TERMS_DIR/de/0.txt TERMS_ETAG - Basename of the file(s) in the TERMS_DIR with the current terms of service. The value is also used for the "Etag" in the HTTP request to control caching. Whenever the terms of service change, the TERMS_ETAG MUST also change, and old values MUST NOT be repeated. For example, the date or version number of the terms of service SHOULD be used for the Etag. If there are minor (i.e. spelling) fixes to the terms of service, the TERMS_ETAG probably SHOULD NOT be changed. However, whenever users must approve the new terms, the TERMS_ETAG MUST change. + Basename of the file(s) in the TERMS_DIR with the current terms of service. The value is also used for the "Etag" in the HTTP request to control caching. Whenever the terms of service change, the TERMS_ETAG MUST also change, and old values MUST NOT be repeated. For example, the date or version number of the terms of service SHOULD be used for the Etag. If there are minor (i.e. spelling) fixes to the terms of service, the TERMS_ETAG probably SHOULD NOT be changed. However, whenever users must approve the new terms, the TERMS_ETAG MUST change. PRIVACY_DIR - Works the same as TERMS_DIR, just for the privacy policy. + Works the same as TERMS_DIR, just for the privacy policy. PRIVACY_ETAG - Works the same as TERMS_ETAG, just for the privacy policy. + Works the same as TERMS_ETAG, just for the privacy policy. EXCHANGE DATABASE OPTIONS @@ -118,17 +118,17 @@ EXCHANGE DATABASE OPTIONS The following options must be in the section "[exchangedb]". DURATION_OVERLAP - How much should validity periods for coins overlap? - Should be long enough to avoid problems with - wallets picking one key and then due to network latency - another key being valid. The DURATION_WITHDRAW period - must be longer than this value. + How much should validity periods for coins overlap? + Should be long enough to avoid problems with + wallets picking one key and then due to network latency + another key being valid. The DURATION_WITHDRAW period + must be longer than this value. IDLE_RESERVE_EXPIRATION_TIME - After which time period should reserves be closed if they are idle? + After which time period should reserves be closed if they are idle? LEGAL_RESERVE_EXPIRATION_TIME - After what time do we forget about (drained) reserves during garbage collection? + After what time do we forget about (drained) reserves during garbage collection? EXCHANGE POSTGRES BACKEND DATABASE OPTIONS @@ -138,8 +138,8 @@ The following options must be in section “[exchangedb-postgres]” if the “postgres” plugin was selected for the database. CONFIG - How to access the database, i.e. “postgres:///taler” to use the - “taler” database. Testcases use “talercheck”. + How to access the database, i.e. “postgres:///taler” to use the + “taler” database. Testcases use “talercheck”. EXCHANGE ACCOUNT OPTIONS @@ -151,11 +151,20 @@ arbitrary and should be chosen to uniquely identify the bank account for the operator. PAYTO_URI - Specifies the payto://-URL of the account. The general format is - payto://METHOD/DETAILS. + Specifies the payto://-URL of the account. The general format is + ``payto://$METHOD/$DETAILS``. Examples: + ``payto://x-taler-bank/localhost:8899/Exchange`` or + ``payto://iban/GENODEF1SLR/DE67830654080004822650/`` or + ``payto://iban/DE67830654080004822650/`` (providing the BIC is optional). WIRE_GATEWAY_URL - URL of the wire gateway + URL of the wire gateway. Typically of the form + ``https://$HOSTNAME[:$PORT]/taler-wire-gateway/$USERNAME/`` + where $HOSTNAME is the hostname of the system running the bank + (such as the Taler Python bank or the Nexus) and $USERNAME is + the username of the exchange's bank account (usually matching + the ``USERNAME`` option used for authentication). Example: + ``https://bank.demo.taler.net/taler-wire-gateway/Exchange/`` WIRE_GATEWAY_AUTH_METHOD This option determines how the exchange (auditor/wirewatch/aggregator) @@ -168,38 +177,22 @@ PASSWORD Password for ``basic`` authentication with the wire gateway. WIRE_RESPONSE - Specifies the name of the file in which the /wire response for this - account should be located. Used by the Taler exchange service and the - taler-exchange-wire tool. + Specifies the name of the file in which the /wire response for this + account should be located. Used by the Taler exchange service and the + taler-exchange-wire tool. Example: + ``${TALER_DATA_HOME}/exchange/wire-sigs/SOMETHING.json``. Note that + the file names must differ between all of the exchange bank accounts. + It is suggested to use the section name for ``SOMETHING`` to ensure + uniqueness. ENABLE_DEBIT - Must be set to YES for the accounts that the - taler-exchange-aggregator should debit. Not used by merchants. + Must be set to YES for the accounts that the + taler-exchange-aggregator and taler-exchange-closer should debit. ENABLE_CREDIT - Must be set to YES for the accounts that the taler-exchange-wirewatch - should check for credits. It is yet uncertain if the merchant - implementation may check this flag as well. - - -TALER-BANK AUTHENTICATION OPTIONS (for accounts) ------------------------------------------------- - -The following authentication options are supported by the “taler-bank” -wire plugin. They must be specified in the “[account-]” section that -uses the “taler-bank” plugin. - -TALER_BANK_AUTH_METHOD - Authentication method to use. “none” or “basic” are currently - supported. - -USERNAME - Username to use for authentication. Used with the “basic” - authentication method. - -PASSWORD - Password to use for authentication. Used with the “basic” - authentication method. + Must be set to YES for the accounts that the taler-exchange-wirewatch + should check for credits. It is yet uncertain if the merchant + implementation may check this flag as well. EXCHANGE WIRE FEE OPTIONS @@ -214,13 +207,13 @@ the fee should apply. Usually, fees should be given for several years in advance. WIRE-FEE-YEAR - Aggregate wire transfer fee merchants are charged in YEAR. Specified - as a Taler amount using the usual amount syntax - (CURRENCY:VALUE.FRACTION). + Aggregate wire transfer fee merchants are charged in YEAR. Specified + as a Taler amount using the usual amount syntax + (CURRENCY:VALUE.FRACTION). CLOSING-FEE-YEAR - Reserve closing fee customers are charged in YEAR. Specified as a - Taler amount using the usual amount syntax (CURRENCY:VALUE.FRACTION). + Reserve closing fee customers are charged in YEAR. Specified as a + Taler amount using the usual amount syntax (CURRENCY:VALUE.FRACTION). EXCHANGE COIN OPTIONS --------------------- @@ -329,15 +322,15 @@ $NAME is a merchant-given name for the auditor. The following options must be given in each “[merchant-auditor-$NAME]” section. AUDITOR_BASE_URL - Base URL of the auditor, i.e. “https://auditor.demo.taler.net/” + Base URL of the auditor, i.e. “https://auditor.demo.taler.net/” AUDITOR_KEY - Crockford Base32 encoded auditor public key. + Crockford Base32 encoded auditor public key. CURRENCY - Name of the currency for which this auditor is trusted, i.e. “KUDOS” - The entire section is ignored if the currency does not match the currency - we use, which must be given in the [taler] section. + Name of the currency for which this auditor is trusted, i.e. “KUDOS” + The entire section is ignored if the currency does not match the currency + we use, which must be given in the [taler] section. AUDITOR OPTIONS @@ -347,10 +340,10 @@ The following options must be in section “[auditor]” for the Taler auditor. DB - Plugin to use for the database, i.e. “postgres” + Plugin to use for the database, i.e. “postgres” AUDITOR_PRIV_FILE - Name of the file containing the auditor’s private key + Name of the file containing the auditor’s private key AUDITOR POSTGRES BACKEND DATABASE OPTIONS @@ -360,8 +353,8 @@ The following options must be in section “[auditordb-postgres]” if the “postgres” plugin was selected for the database. CONFIG - How to access the database, i.e. "postgres:///taler" to use the - "taler" database. Testcases use “talercheck”. + How to access the database, i.e. "postgres:///taler" to use the + "taler" database. Testcases use “talercheck”. SEE ALSO -- cgit v1.2.3 From 0fc949ee171bb7cb320de5593c59474684f440ea Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Mon, 6 Jul 2020 18:45:35 +0530 Subject: iso20022 notes --- libeufin/iso20022.rst | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/libeufin/iso20022.rst b/libeufin/iso20022.rst index d87098a3..06d929c2 100644 --- a/libeufin/iso20022.rst +++ b/libeufin/iso20022.rst @@ -22,15 +22,37 @@ The specifics of this mapping are: of message elements in the same schema. -Cash Management (camt) -====================== +Why does LibEuFin not use ISO 20022? +==================================== -LibEuFin combines camt.052, camt.053 and camt.054, as they essentially -have the same structure and serve the same purpose: Reporting transactions -on a customer's bank account. +While LibEuFin can ingest ISO 20022 messages (camt.05x, pain.002) and generate +them (pain.001), it does not use ISO 20022 in its API and internal data model. -We also flatten the hierarchy a bit and only have entries ("money movement in one go") -and transactions. +Reasons for not using ISO 20022 directly are: + +1. Impedence mismatch. ISO 20022 messages do not map well to query/response + APIs. +2. Cumbersome to use. Even when ISO 20022 messages are directly mapped + to JSON, they are difficult to use due to their verbosity. +3. Underspecification. Messages like camt.05x leave many "degrees of freedom" + when translating the underlying data into a message. +4. No interoperability. As a result of underspecification, different countries/organisations + define their own subset and interpretation rules for ISO 20022 messages. This can + lead to even contradictory usage rules. An example for this is how the Swiss and EPC + interpretations handle transaction amounts in the presence of multiple currencies. +5. Redundancy. ISO 20022 are redundant, and often mix aspects of the "presentation logic" + with the underlying data model. An example of this is the optional "summary" information + in camt.05x messages. + +Instead of using ISO 20022 messages directly, LibEuFin leverages the standard in other ways: + +* As the data exchange format with banks +* As a guideline for naming in data formats +* As a guideline for which concepts need to be understood by LibEuFin + + +Implementation notes for camt.05x +================================= Types of amounts in camt messages --------------------------------- -- cgit v1.2.3 From 5fb356c455f1bca1368c09389960b9100dde4632 Mon Sep 17 00:00:00 2001 From: MS Date: Wed, 8 Jul 2020 10:49:17 +0200 Subject: API that offers the list of initiated payments. --- libeufin/api-nexus.rst | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index 666fe1f3..ebb24533 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -138,6 +138,23 @@ manages payment initiations of the account and tracks the of payment initiations preparationDate: string; } +.. http:get:: {nexusBase}/bank-accounts/{my-acct}/payment-initiations + + Ask nexus the list of initiated payments. At this stage of the API, + **all** is returned: submitted and non submitted payments. + + **Response** + + .. ts:def:: InitiatedPayments + + interface InitiatedPayments { + + // list of all the initiated payments' UID. + initiatedPayments: string[]; + + } + + .. http:post:: {nexusBase}/bank-accounts/{my-acct}/payment-initiations Ask nexus to prepare instructions for a new payment. -- cgit v1.2.3 From 95f5de12dc3bd05723d8f312ca323ba9036d6690 Mon Sep 17 00:00:00 2001 From: MS Date: Wed, 8 Jul 2020 12:21:50 +0200 Subject: more details in response --- libeufin/api-nexus.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index ebb24533..d58b43bd 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -150,8 +150,7 @@ manages payment initiations of the account and tracks the of payment initiations interface InitiatedPayments { // list of all the initiated payments' UID. - initiatedPayments: string[]; - + initiatedPayments: PaymentStatus[]; } -- cgit v1.2.3 From 3dd24bd40d15bdd10e1fd183995935d4e7786e31 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 8 Jul 2020 15:29:45 +0200 Subject: update specification for #6416 --- core/api-common.rst | 14 +++++++++++++- core/api-exchange.rst | 5 +++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/core/api-common.rst b/core/api-common.rst index 272dfd6c..987ba664 100644 --- a/core/api-common.rst +++ b/core/api-common.rst @@ -672,6 +672,7 @@ within the struct GNUNET_CRYPTO_EccSignaturePurpose purpose; struct GNUNET_HashCode h_contract_terms; struct GNUNET_HashCode h_wire; + struct GNUNET_HashCode h_denom_pub; struct GNUNET_TIME_AbsoluteNBO timestamp; struct GNUNET_TIME_AbsoluteNBO refund_deadline; struct TALER_AmountNBO amount_with_fee; @@ -711,6 +712,7 @@ within the */ struct GNUNET_CRYPTO_EccSignaturePurpose purpose; struct GNUNET_HashCode session_hash; + struct GNUNET_HashCode h_denom_pub; struct TALER_AmountNBO amount_with_fee; struct TALER_AmountNBO melt_fee; union TALER_CoinSpendPublicKeyP coin_pub; @@ -958,7 +960,17 @@ within the .. _TALER_RecoupRefreshConfirmationPS: .. sourcecode:: c - // FIXME: put definition here + struct TALER_RecoupRefreshConfirmationPS { + + /** + * purpose.purpose = TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH + */ + struct GNUNET_CRYPTO_EccSignaturePurpose purpose; + struct GNUNET_TIME_AbsoluteNBO timestamp; + struct TALER_AmountNBO recoup_amount; + struct TALER_CoinSpendPublicKeyP coin_pub; + struct TALER_CoinSpendPublicKeyP old_coin_pub; + }; .. _TALER_RecoupConfirmationPS: .. sourcecode:: c diff --git a/core/api-exchange.rst b/core/api-exchange.rst index 9b18a18d..b461733e 100644 --- a/core/api-exchange.rst +++ b/core/api-exchange.rst @@ -770,6 +770,11 @@ denomination. // only present if ``type`` is "DEPOSIT" h_wire?: HashCode; + // Hash of the public denomination key used to sign the coin. + // only present if ``type`` is "DEPOSIT", "RECOUP", + // "RECOUP-REFRESH", "OLD-COIN-RECOUP" or "MELT". + h_denom_pub?: HashCode; + // Deposit fee in case of type "REFUND". refund_fee?: Amount; -- cgit v1.2.3 From 31e66d9753efc06841bdffac0e1897dcdb1d1385 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 8 Jul 2020 19:52:51 +0200 Subject: update API specification for #6416 --- core/api-exchange.rst | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/core/api-exchange.rst b/core/api-exchange.rst index b461733e..309e070e 100644 --- a/core/api-exchange.rst +++ b/core/api-exchange.rst @@ -625,13 +625,18 @@ denomination. place. The response will include a `DepositSuccess` object. :status 401 Unauthorized: One of the signatures is invalid. - :status 403 Forbidden: - The deposit operation has failed because the coin has insufficient - residual value; the request should not be repeated again with this coin. - In this case, the response is a `DepositDoubleSpendError`. :status 404 Not Found: Either the denomination key is not recognized (expired or invalid) or the wire type is not recognized. + :status 409 Conflict: + The deposit operation has either failed because the coin has insufficient + residual value, or because the same public key of the coin has been + previously used with a different denomination. Which case it is + can be decided by looking at the error code + (``TALER_EC_DEPOSIT_INSUFFICIENT_FUNDS`` or ``TALER_EC_COIN_CONFLICTING_DENOMINATION_KEY``). + The fields of the response are the same in both cases. + The request should not be repeated again with this coin. + In this case, the response is a `DepositDoubleSpendError`. **Details:** @@ -847,12 +852,16 @@ the API during normal operation. One of the signatures is invalid. :status 200 OK: The request was succesful. The response body is `MeltResponse` in this case. - :status 403 Forbidden: - The operation is not allowed as at least one of the coins has insufficient funds. The response - is `MeltForbiddenResponse` in this case. :status 404: the exchange does not recognize the denomination key as belonging to the exchange, or it has expired + :status 409 Conflict: + The operation is not allowed as the coin has insufficient + residual value, or because the same public key of the coin has been + previously used with a different denomination. Which case it is + can be decided by looking at the error code + (``TALER_EC_MELT_INSUFFICIENT_FUNDS`` or ``TALER_EC_COIN_CONFLICTING_DENOMINATION_KEY``). + The response is `MeltForbiddenResponse` in both cases. **Details:** @@ -1121,13 +1130,17 @@ in using this API. coin is not lost. :status 401 Unauthorized: The coin's signature is invalid. - :status 403 Forbidden: - The coin was already used for payment. - The response is a `DepositDoubleSpendError`. :status 404 Not Found: The denomination key is not in the set of denomination keys where emergency pay back is enabled, or the blinded coin is not known to have been withdrawn. + :status 409 Conflict: + The operation is not allowed as the coin has insufficient + residual value, or because the same public key of the coin has been + previously used with a different denomination. Which case it is + can be decided by looking at the error code + (``TALER_EC_RECOUP_COIN_BALANCE_ZERO`` or ``TALER_EC_COIN_CONFLICTING_DENOMINATION_KEY``). + The response is a `DepositDoubleSpendError`. **Details:** -- cgit v1.2.3 From 2f705cc5d651a7eb05519ebc86d275b1008000e7 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 8 Jul 2020 21:02:27 +0200 Subject: further spec updates with respect to data to be returned for coin histories --- core/api-exchange.rst | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/core/api-exchange.rst b/core/api-exchange.rst index 309e070e..59abccd1 100644 --- a/core/api-exchange.rst +++ b/core/api-exchange.rst @@ -762,7 +762,8 @@ denomination. // exchange, possibly zero if refunds are not allowed. Only for "DEPOSIT" operations. refund_deadline?: Timestamp; - // Signature by the coin, only present if ``type`` is "DEPOSIT" or "MELT" + // Signature by the coin, only present if ``type`` is "DEPOSIT", "MELT", "RECOUP", + // "OLD-COIN-RECOUP" or "RECOUP-REFRESH" coin_sig?: EddsaSignature; // Deposit fee in case of type "MELT". @@ -777,7 +778,7 @@ denomination. // Hash of the public denomination key used to sign the coin. // only present if ``type`` is "DEPOSIT", "RECOUP", - // "RECOUP-REFRESH", "OLD-COIN-RECOUP" or "MELT". + // "RECOUP-REFRESH", or "MELT". h_denom_pub?: HashCode; // Deposit fee in case of type "REFUND". @@ -792,6 +793,14 @@ denomination. // "REFUND" rtransaction_id?: Integer; + // Coin blinding key. Only present if ``type`` is + // "RECOUP" or "RECOUP-REFRESH" + coin_blind?: DenominationBlindingKeyP; + + // Reserve receiving the recoup. Only present if ``type`` is + // "RECOUP" + reserve_pub?: EddsaPublicKey; + // `EdDSA Signature ` authorizing the REFUND. Made with // the `public key of the merchant `. // Only present if ``type`` is "REFUND" -- cgit v1.2.3 From bc7722eeee3655a44edf3a245a8a4a74977332ed Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Thu, 9 Jul 2020 18:58:00 +0530 Subject: wallet API docs, WIP --- taler-wallet.rst | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/taler-wallet.rst b/taler-wallet.rst index ed081363..c65ea3b6 100644 --- a/taler-wallet.rst +++ b/taler-wallet.rst @@ -398,6 +398,59 @@ Refunds contractTermsHash: string; } +Exchange Management: List Exchanges +----------------------------------- + +:name: ``"listExchanges"`` +:description: + List all exchanges. Can be used on the CLI + as ``taler-wallet-cli exchanges list``. +:response: + .. ts:def:: ExchangesListRespose + + interface ExchangesListRespose { + exchanges: ExchangeListItem[]; + } + + .. ts:def:: ExchangeListItem + + interface ExchangeListItem { + exchangeBaseUrl: string; + currency: string; + paytoUris: string[]; + } + +Exchange Management: Add Exchange +--------------------------------- + +:name: ``"addExchange"`` +:description: + Add an exchange. Can be used on the CLI as ``taler-wallet-cli exchanges add $URL``. +:request: + .. ts:def:: ExchangeAddRequest + + interface ExchangeAddRequest { + exchangeBaseUrl: string; + } +:response: + On success, the response is an empty object. + +Withdrawal: Get Manual Withdrawal Info +-------------------------------------- + +:name: ``"getWithdrawalDetailsForAmount"`` +:description: + Get information about fees and exchange for a manual withdrawal of a given amount. +:request: + .. ts:def:: GetManualWithdrawalDetailsRequest + + interface ExchangeAddRequest { + exchangeBaseUrl: string; + amount: string; + } +:response: + An ``ExchangeWithdrawDetails`` object (to be documented, see `here + `__). Integration Tests ================= -- cgit v1.2.3 From c2bd5b95d3a32eeedb4cf0d9dbd15d0cd7191f8e Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Thu, 9 Jul 2020 19:35:02 +0530 Subject: docs --- taler-wallet.rst | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/taler-wallet.rst b/taler-wallet.rst index c65ea3b6..8d348efc 100644 --- a/taler-wallet.rst +++ b/taler-wallet.rst @@ -403,8 +403,9 @@ Exchange Management: List Exchanges :name: ``"listExchanges"`` :description: - List all exchanges. Can be used on the CLI - as ``taler-wallet-cli exchanges list``. + List all exchanges. +:cli: + ``taler-wallet-cli exchanges list`` :response: .. ts:def:: ExchangesListRespose @@ -425,7 +426,9 @@ Exchange Management: Add Exchange :name: ``"addExchange"`` :description: - Add an exchange. Can be used on the CLI as ``taler-wallet-cli exchanges add $URL``. + Add an exchange. +:cli: + ``taler-wallet-cli exchanges add $URL`` :request: .. ts:def:: ExchangeAddRequest @@ -441,6 +444,8 @@ Withdrawal: Get Manual Withdrawal Info :name: ``"getWithdrawalDetailsForAmount"`` :description: Get information about fees and exchange for a manual withdrawal of a given amount. +:cli: + ``taler-wallet-cli advanced manual-withdrawal-details $URL $AMOUNT`` :request: .. ts:def:: GetManualWithdrawalDetailsRequest -- cgit v1.2.3 From e1ba8dad8c87f23bbbfc917ef5e7718ca6ce3065 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 10 Jul 2020 22:33:33 +0200 Subject: coin_sig is useless in OLD-COIN-RECOUP context, remove from spec --- core/api-exchange.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/api-exchange.rst b/core/api-exchange.rst index 59abccd1..cba9a6d3 100644 --- a/core/api-exchange.rst +++ b/core/api-exchange.rst @@ -763,7 +763,7 @@ denomination. refund_deadline?: Timestamp; // Signature by the coin, only present if ``type`` is "DEPOSIT", "MELT", "RECOUP", - // "OLD-COIN-RECOUP" or "RECOUP-REFRESH" + // or "RECOUP-REFRESH" coin_sig?: EddsaSignature; // Deposit fee in case of type "MELT". -- cgit v1.2.3 From 6036cea5f598620ac4b6e9553d84bef2aa93ad7c Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Sat, 11 Jul 2020 14:02:31 +0530 Subject: wallet-core API docs --- taler-wallet.rst | 110 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 86 insertions(+), 24 deletions(-) diff --git a/taler-wallet.rst b/taler-wallet.rst index 8d348efc..35210cb5 100644 --- a/taler-wallet.rst +++ b/taler-wallet.rst @@ -137,9 +137,9 @@ Transactions Transactions are all operations or events that are affecting the balance. -:name: ``"getTransactions"`` -:description: Get a list of past and pending transactions. -:request: +:Name: ``"getTransactions"`` +:Description: Get a list of past and pending transactions. +:Request: .. ts:def:: TransactionsRequest interface TransactionsRequest { @@ -149,7 +149,7 @@ Transactions are all operations or events that are affecting the balance. // if present, results will be limited to transactions related to the given search string search?: string; } -:response: +:Response: .. ts:def:: TransactionsResponse interface TransactionsResponse { @@ -382,15 +382,15 @@ Transactions are all operations or events that are affecting the balance. Refunds ------- -:name: ``"applyRefund"`` -:description: Process a refund from a ``taler://refund`` URI. -:request: +:Name: ``"applyRefund"`` +:Description: Process a refund from a ``taler://refund`` URI. +:Request: .. ts:def:: WalletApplyRefundRequest interface WalletApplyRefundRequest { talerRefundUri: string; } -:response: +:Response: .. ts:def:: WalletApplyRefundResponse interface WalletApplyRefundResponse { @@ -401,12 +401,12 @@ Refunds Exchange Management: List Exchanges ----------------------------------- -:name: ``"listExchanges"`` -:description: +:Name: ``"listExchanges"`` +:Description: List all exchanges. -:cli: +:CLI: ``taler-wallet-cli exchanges list`` -:response: +:Response: .. ts:def:: ExchangesListRespose interface ExchangesListRespose { @@ -424,38 +424,100 @@ Exchange Management: List Exchanges Exchange Management: Add Exchange --------------------------------- -:name: ``"addExchange"`` -:description: +:Name: ``"addExchange"`` +:Description: Add an exchange. -:cli: +:CLI: ``taler-wallet-cli exchanges add $URL`` -:request: +:Request: .. ts:def:: ExchangeAddRequest interface ExchangeAddRequest { exchangeBaseUrl: string; } -:response: +:Response: + On success, the response is an empty object. + +Exchange Management: Get Terms of Service +----------------------------------------- + +:Name: ``"getExchangeTos"`` +:Description: + Get the exchange's current ToS and which version of the ToS (if any) + the user has accepted. +:CLI: + ``taler-wallet-cli exchanges tos $URL`` +:Request: + .. ts:def:: ExchangeGetTosRequest + + interface ExchangeGetTosRequest { + exchangeBaseUrl: string; + } +:Response: + .. ts:def:: ExchangeGetTosResult + + export interface GetExchangeTosResult { + // Markdown version of the current ToS. + tos: string; + + // Version tag of the current ToS. + currentEtag: string; + + // Version tag of the last ToS that the user has accepted, + // if any. + acceptedEtag: string | undefined; + } + +Exchange Management: Set Accepted Terms of Service Version +---------------------------------------------------------- + +:Name: ``"setExchangeTosAccepted"`` +:Description: + Store that the user has accepted a version of the exchange's ToS. +:CLI: + ``taler-wallet-cli exchanges accept-tos $URL $ETAG`` +:Request: + .. ts:def:: ExchangeSetTosAccepted + + interface ExchangeGetTosRequest { + exchangeBaseUrl: string; + acceptedEtag: string; + } +:Response: On success, the response is an empty object. Withdrawal: Get Manual Withdrawal Info -------------------------------------- -:name: ``"getWithdrawalDetailsForAmount"`` -:description: +:Name: ``"getWithdrawalDetailsForAmount"`` +:Description: Get information about fees and exchange for a manual withdrawal of a given amount. -:cli: +:CLI: ``taler-wallet-cli advanced manual-withdrawal-details $URL $AMOUNT`` -:request: +:Request: .. ts:def:: GetManualWithdrawalDetailsRequest interface ExchangeAddRequest { exchangeBaseUrl: string; amount: string; } -:response: - An ``ExchangeWithdrawDetails`` object (to be documented, see `here - `__). +:Response: + .. ts:def:: ManualWithdrawalDetails + + export interface ManualWithdrawalDetails { + // Did the user accept the current version of the exchange's + // terms of service? + tosAccepted: boolean; + + // Amount that the user will transfer to the exchange. + rawAmount: AmountString; + + // Amount that will be added to the user's wallet balance. + effectiveAmount: AmountString; + + // Ways to pay the exchange. + paytoUris: string[]; + } Integration Tests ================= -- cgit v1.2.3