.. This file is part of GNU TALER. Copyright (C) 2014, 2015, 2016 INRIA 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 ================================= Merchant Reference Implementation ================================= ----------------------- Architectural Overview ----------------------- The merchant reference implementationis divided into two independent compontents, the `frontend` and the `backend`. The `frontend` is the existing shopping portal of the merchant. The architecture tries to minimize the amount of modifications necessary to the `frontend` as well as the trust that needs to be placed into the `frontend` logic. Taler requires the frontend to facilitate two JSON-based interactions between the wallet and the `backend`, and one of those is trivial. The `backend` is a standalone C application intended to implement all the cryptographic routines required to interact with the Taler wallet and a Taler exchange. ------------------------------ The Frontent HTTP API ------------------------------ .. http:get:: /taler/contract Triggers the contract generation. Note that the URL may differ between merchants. **Request:** The request depends entirely on the merchant implementation. **Response** :status 200 OK: The request was successful. The body contains an :ref:`offer `. :status 400 Bad Request: Request not understood. :status 500 Internal Server Error: In most cases, some error occurred while the backend was generating the contract. For example, it failed to store it into its database. ------------------------------ The Merchant Backend HTTP API ------------------------------ The following API are made available by the merchant's `backend` to the merchant's `frontend`. .. http:post:: /contract Ask the backend to add some missing (mostly related to cryptography) information to the contract. **Request:** The `proposition` that is to be sent from the frontend is a `contract` object without the fields * `exchanges` * `auditors` * `H_wire` * `merchant_pub` The `backend` then completes this information based on its configuration. **Response** :status 200 OK: The backend has successfully created the contract. It responds with a `ContractBackendResponse`_ object. This request should virtually always be successful. On success, the `frontend` should pass this response verbatim to the wallet. :status 403 Forbidden: The frontend used the same transaction ID twice. This is only allowed if the response from the backend was lost ("instant" replay), but to assure that frontends usually create fresh transaction IDs this is forbidden if the contract was already paid. So attempting to have the backend sign a contract for a contract that was already paid by a wallet (and thus was generated by the frontend a "long" time ago), is forbidden and results in this error. Frontends must make sure that they increment the transaction ID properly and persist the largest value used so far. **Details:** .. _ContractBackendResponse: .. code-block:: tsref interface ContractBackendResponse { // Contract with additional fields added by the backend. contract : Object; // Signature of the merchant over the contract. // Purpose: TALER_SIGNATURE_MERCHANT_CONTRACT merchant_sig: EddsaSignature; // Hash of the contract, technically redundant, but allows // the frontend to not have logic for canonicalizing the // contract and doing the hasing itself. H_contract: HashCode; } .. http:post:: /pay Asks the `backend` to execute the transaction with the exchange and deposit the coins. **Request:** The `frontend` passes the :ref:`deposit permission ` received from the wallet, and optionally adding a field named `pay_deadline`, indicating a deadline by which he would expect to receive the bank transfer for this deal. Note that the `pay_deadline` must be after the `refund_deadline`. The backend calculates the `pay_deadline` by adding the `wire_transfer_delay` value found in the configuration to the current time. **Response:** :status 200 OK: The exchange accepted all of the coins. The `frontend` should now fullfill the contract. This response has no meaningful body, the frontend needs to generate the fullfillment page. :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 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. 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.