commit ad486bbbe544898cbac16f74a4ad8dbc76f0ca01
parent c694d7bdcadbe054db1bde682f717d3c42609ed7
Author: Christian Grothoff <grothoff@gnunet.org>
Date: Fri, 11 Apr 2025 14:52:44 +0200
Merge branch 'master' of git+ssh://git.taler.net/taler-docs
Diffstat:
13 files changed, 305 insertions(+), 1207 deletions(-)
diff --git a/conf.py b/conf.py
@@ -281,13 +281,13 @@ latex_documents = [
"GNU Taler team",
"manual",
),
- (
- "taler-merchant-api-tutorial",
- "taler-merchant-api-tutorial.tex",
- "GNU Taler Merchant API Tutorial",
- "GNU Taler team",
- "manual",
- ),
+ # (
+ # "taler-merchant-api-tutorial",
+ # "taler-merchant-api-tutorial.tex",
+ # "GNU Taler Merchant API Tutorial",
+ # "GNU Taler team",
+ # "manual",
+ # ),
(
"taler-developer-manual",
"taler-developer-manual.tex",
@@ -901,15 +901,15 @@ texinfo_documents = [
"Backend for merchants accepting Taler payments",
"Network applications",
),
- (
- "taler-merchant-api-tutorial",
- "taler-merchant-api-tutorial",
- "Taler Merchant API Tutorial",
- "GNU Taler team",
- "GNU Taler Merchant API",
- "Tutorial for using the merchant backend API",
- "Network applications",
- ),
+ # (
+ # "taler-merchant-api-tutorial",
+ # "taler-merchant-api-tutorial",
+ # "Taler Merchant API Tutorial",
+ # "GNU Taler team",
+ # "GNU Taler Merchant API",
+ # "Tutorial for using the merchant backend API",
+ # "Network applications",
+ # ),
(
"taler-developer-manual",
"taler-developer-manual",
diff --git a/core/api-common.rst b/core/api-common.rst
@@ -1292,21 +1292,17 @@ within the
* Purpose is #TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW
*/
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
-
-
/**
* Amount to withdraw, excluding fees, i.e.
* the total sum of the denominations of the coins.
* Note that the reserve must have a value of at least amount+fee.
*/
struct TALER_Amount amount;
-
/**
* Total fee for the withdrawal.
* Note that the reserve must have a value of at least amount+fee.
*/
struct TALER_Amount fee;
-
/**
* This is the running SHA512-hash over all
* `TALER_BlindedCoinHashP` values of the coins.
@@ -1324,7 +1320,11 @@ within the
* in the subsequent call to /reveal-withdraw
*/
struct TALER_HashPlanchetsP h_planchets;
-
+ /**
+ * The master seed that was used in the call to /blinding-prepare blinding,
+ * or all zeros, if no denomination of cipher type Clause-Schnorr is used.
+ */
+ struct TALER_BlindingMasterSecretP blinding_seed;
/**
* If age restriction proof is required, the maximum age _group_
* to commit to, 0 otherwise. Note that in this case, all
@@ -1335,17 +1335,13 @@ within the
* the age group to a given age (in years).
*/
uint32_t max_age_group;
-
/**
* The age groups as configured for the exchange, represented as a mask.
* If max_age_group is > 0, the mask MUST be non-zero, too.
*/
struct TALER_AgeMask mask;
-
};
-
-
.. _TALER_WithdrawConfirmationPS:
.. sourcecode:: c
diff --git a/core/api-exchange.rst b/core/api-exchange.rst
@@ -5538,12 +5538,12 @@ regulatory compliance.
.. ts:def:: ExchangeKycUploadFormRequest
- interface ExchangeKycUploadFormRequest {
+ interface ExchangeKycUploadFormRequest {
- // Which form is being submitted. Further details depend on the form.
- // @since protocol **v26**.
- form_id: string;
- }
+ // Which form is being submitted. Further details depend on the form.
+ // @since protocol **v26**.
+ form_id: string;
+ }
.. http:post:: /kyc-start/$ID
diff --git a/core/index.rst b/core/index.rst
@@ -19,9 +19,9 @@
@author Marcello Stanisci
@author Christian Grothoff
----------------------------
-Core Protocol Specification
----------------------------
+-----------------
+API Specification
+-----------------
This chapter describes the APIs used in the GNU Taler project. It includes
both APIs that are pre-existing as well as APIs specific to the project.
diff --git a/deployments/tops.rst b/deployments/tops.rst
@@ -281,15 +281,19 @@ FIXME-#9678: we should put these into GANA.
* Identifies the sanction list entry that the account matched against
(best match, does not mean it was a good match)
-* ``SANCTION_LIST_RATING :: float``
+* ``SANCTION_LIST_RATING :: Integer``
- * [0,1] score for how good the sanction list match was
- (0: none, 1: perfect match)
+ * [0,10**9] score for how good the sanction list match was
+ (0: none, 10**9: perfect match)
-* ``SANCTION_LIST_CONFIDENCE :: float``
+* ``SANCTION_LIST_CONFIDENCE :: Integer``
- * [0,1] score for how much supporting data we had for
- the sanction list match (0: none, 1: all fields available)
+ * [0,10**9] score for how much supporting data we had for
+ the sanction list match (0: none, 10**9: all fields available)
+
+* ``SANCTION_LIST_SUPPRESS :: Boolean``
+
+ * Suppress flagging this account when it creates a hit on a sanctions list, this is a false-positive.
Events
diff --git a/index.rst b/index.rst
@@ -44,6 +44,8 @@ In this documentation, we describe the REST-based APIs between the various
components, how to use the system, the internal architecture of key
components, and how to get them installed and configured.
+Tutorials are available `here <https://tutorials.taler.net/>`_. They demonstrate installation steps, configuration options,
+and overall usage of the different Taler components in text and video formats.
Documentation Overview
@@ -54,9 +56,7 @@ Documentation Overview
:maxdepth: 1
core/index
- taler-user-guide
taler-merchant-manual
- taler-merchant-api-tutorial
taler-merchant-pos-terminal
taler-wallet
taler-exchange-manual
@@ -75,3 +75,4 @@ Documentation Overview
:hidden:
fdl-1.3
+ tutorials
diff --git a/libeufin/index.rst b/libeufin/index.rst
@@ -18,8 +18,8 @@
@author Christian Grothoff
-LibEuFin
-########
+LibEuFin Manual
+###############
LibEuFin is a project providing free software tooling for European FinTech.
diff --git a/system-administration/index.rst b/system-administration/index.rst
@@ -15,8 +15,8 @@
@author Javier Sepulveda
-System Administration
-#####################
+System Administration Manual
+############################
.. toctree::
:maxdepth: 1
diff --git a/taler-merchant-api-tutorial.rst b/taler-merchant-api-tutorial.rst
@@ -1,697 +0,0 @@
-..
- This file is part of GNU TALER.
- Copyright (C) 2014-2023 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU Affero 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 Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-
- @author Marcello Stanisci
- @author Florian Dold
- @author Christian Grothoff
-
-.. _merchant-api-tutorial:
-
-Merchant API Tutorial
-#####################
-
-.. contents:: Table of Contents
- :depth: 2
- :local:
-
-Introduction
-============
-
-About GNU Taler
----------------
-
-GNU Taler is an open protocol for an electronic payment system with a
-free software reference implementation. GNU Taler offers secure, fast
-and easy payment processing using well understood cryptographic
-techniques. GNU Taler allows customers to remain anonymous, while
-ensuring that merchants can be held accountable by governments. Hence,
-GNU Taler is compatible with anti-money-laundering (AML) and
-know-your-customer (KYC) regulation, as well as data protection
-regulation (such as GDPR).
-
-About this tutorial
--------------------
-
-This tutorial addresses how to process payments using the GNU Taler merchant
-Backend. The audience for this tutorial are *developers* of merchants (such
-as Web shops) that are working on integrating GNU Taler with the
-customer-facing Frontend and the staff-facing Backoffice.
-
-This chapter explains some basic concepts. In the
-second chapter, you will learn how to do basic payments.
-
-This version of the tutorial has examples for Python3. It uses the
-``requests`` library for HTTP requests. Versions for other
-languages/environments are available as well.
-
-If you want to look at some simple, running examples, check out these:
-
-- The `essay
- merchant <https://git.taler.net/taler-merchant-demos.git/tree/talermerchantdemos/blog>`__
- that sells single chapters of a book.
-
-- The `donation
- page <https://git.taler.net/taler-merchant-demos.git/tree/talermerchantdemos/donations>`__
- that accepts donations for software projects and gives donation
- receipts.
-
-- The `WooCommerce plugin <https://git.taler.net/gnu-taler-payment-for-woocommerce.git/>`__
- which is a comprehensive integration into a Web shop including the refund business
- process.
-
-
-Architecture overview
----------------------
-
-The Taler software stack for a merchant consists of the following main
-components:
-
-.. index:: 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 tutorial describes how to
- develop a Taler frontend.
-
-.. index:: backend
-
-- A Taler-specific payment backend which makes it easy for the frontend
- to process financial transactions with Taler. For this tutorial, you
- will use a public sandbox backend. For production use, you must
- either set up your own backend or ask another person to do so for
- you.
-
-The following image illustrates the various interactions of these key
-components:
-
-.. image:: images/arch-api.png
-
-The backend provides the cryptographic protocol support, stores
-Taler-specific financial information 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 are
-encapsulated within the Taler backend.
-
-Some functionality of the backend (the “public interface“) is exposed to the
-customer’s browser directly. In the HTTP API, all private endpoints (for the
-Backoffice) are prefixed with ``/private/``. This tutorial focuses on the
-``/private/`` endpoints. The public interface is directly used by the wallet
-and not relevant for the merchant (other than that the API must be exposed).
-
-
-.. index:: sandbox, authorization
-
-Public Sandbox Backend and Authentication
------------------------------------------
-
-How the frontend authenticates to the Taler backend depends on the
-configuration. See :doc:`taler-merchant-manual`.
-
-The public sandbox backend https://backend.demo.taler.net/instances/sandbox/
-uses an API key in the ``Authorization`` header. The value of this header must
-be ``Bearer secret-token:sandbox`` for the public sandbox backend.
-
-.. code-block:: python
-
- >>> import requests
- >>> requests.get("https://backend.demo.taler.net/instances/sandbox/private/orders",
- ... headers={"Authorization": "Bearer secret-token:sandbox"})
- <Response [200]>
-
-If an HTTP status code other than 200 is returned, something went wrong.
-You should figure out what the problem is before continuing with this
-tutorial.
-
-The sandbox backend https://backend.demo.taler.net/instances/sandbox/ uses
-``KUDOS`` as an imaginary currency. Coins denominated in ``KUDOS`` can be
-withdrawn from https://bank.demo.taler.net/.
-
-.. index:: instance
-
-Merchant Instances
-------------------
-
-A single Taler merchant backend server can be used by multiple
-merchants that are separate business entities. Each of these separate
-business entities is assigned a *merchant instance* which is identified by
-an alphanumeric *instance id*. If the instance is omitted, the instance
-id ``admin`` is assumed.
-
-The following merchant instances are configured on
-https://backend.demo.taler.net/:
-
-- ``GNUnet`` (The GNUnet project), reachable at https://backend.demo.taler.net/instances/gnunet/
-
-- ``FSF`` (The Free Software Foundation), reachable at https://backend.demo.taler.net/instances/fsf/
-
-- ``Tor`` (The Tor Project), reachable at https://backend.demo.taler.net/instances/tor/
-
-- ``admin`` (Kudos Inc.), reachable at https://backend.demo.taler.net/
-
-- ``sandbox`` (for testing.), reachable at https://backend.demo.taler.net/instances/sandbox/
-
-.. Note:: These are fictional merchants used for our demonstrators and
- not affiliated with or officially approved by the respective projects.
-
-All endpoints for instances offer the same API. Thus, which instance
-to be used is simply included in the base URL of the merchant backend.
-
-
-.. _Merchant-Payment-Processing:
-
-Merchant Payment Processing
-===========================
-
-.. index:: order
-
-Creating an Order for a Payment
--------------------------------
-
-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
-such an order.
-
-This is done by POSTing a JSON object to the backend’s ``/private/orders`` API
-endpoint. At least the following fields must be given inside the ``order``
-field:
-
-.. index:: summary
-.. index:: fulfillment URL
-
-- ``amount``: The amount to be paid, as a string in the format
- ``CURRENCY:DECIMAL_VALUE``, for example ``EUR:10`` for 10 Euros or
- ``KUDOS:1.5`` for 1.5 KUDOS.
-
-- ``summary``: A human-readable summary for what the payment is about. The
- summary should be short enough to fit into titles, though no hard
- limit is enforced.
-
-- ``fulfillment_url``: A URL that will be displayed once the payment is
- completed. For digital goods, this should be a page that displays the
- product that was purchased. On successful payment, the wallet
- automatically appends the ``order_id`` as a query parameter, as well
- as the ``session_sig`` for session-bound payments (discussed below).
-
-Orders can have many more fields, see `The Taler Order
-Format <#The-Taler-Order-Format>`__. When POSTing an order,
-you can also specify additional details such as an override
-for the refund duration and instructions for inventory
-management. These are rarely needed and not covered in this
-tutorial; please see the :doc:`core/api-merchant` reference
-manual for details.
-
-A minimal Python snippet for creating an order would look like this:
-
-.. code-block:: python
-
- >>> import requests
- >>> body = dict(order=dict(amount="KUDOS:10",
- ... summary="Donation",
- ... fulfillment_url="https://example.com/thanks.html"),
- ... create_token=False)
- >>> response = requests.post("https://backend.demo.taler.net/instances/sandbox/private/orders",
- ... json=body,
- ... headers={"Authorization": "Bearer secret-token:sandbox"})
- <Response [200]>
-
-
-.. index:: claim token
-
-The backend will fill in some details missing in the order, such as the
-address of the merchant instance. The full details are called the
-*contract terms*.
-
-.. index:: contract terms
-
-.. note::
- The above request disables the use of claim tokens by setting the
- ``create_token`` option to ``false``. If you need claim tokens,
- you must adjust the code to construct the ``taler://pay/`` URI
- given below to include the claim token.
-
-After successfully ``POST``\ ing to ``/private/orders``, a JSON with just an
-``order_id`` field with a string representing the order ID will be returned.
-If you also get a claim token, please double-check that you used the request
-as described above.
-
-Together with the merchant ``instance``, the order id uniquely identifies the
-order within a merchant backend. Using the order ID, you can trivially
-construct the respective ``taler://pay/`` URI that must be provided to the
-wallet. Let ``example.com`` be the domain name where the public endpoints of
-the instance are reachable. The Taler pay URI is then simply
-``taler://pay/example.com/$ORDER_ID/`` where ``$ORDER_ID`` must be replaced
-with the ID of the order that was returned.
-
-You can put the ``taler://`` URI as the target of a link to open the Taler
-wallet via the ``taler://`` schema, or put it into a QR code. However, for a
-Web shop, the easiest way is to simply redirect the browser to
-``https://example.com/orders/$ORDER_ID``. That page will then trigger the
-Taler wallet. Here the backend generates the right logic to trigger the
-wallet, supporting the various types of Taler wallets in existence. Instead
-of constructing the above URL by hand, it is also possible to obtain
-it by checking for the payment status as described in the next section.
-
-When manually constructing this URL, make sure to supply the
-claim token (unless it was disabled) and **if** the backend is
-running without TLS to use ``taler+http://`` (note that the
-latter is only supported by wallets running in debug mode).
-
-.. note::
- A trivial way to obtain the correct ``payment_redirect_url``
- is to check the status of the payment (see below).
- So if you are still unsure how to construct it, you can simply
- ask the backend to do for you. However, in production you
- should probably construct it manually and avoid the extra
- request to the backend.
-
-
-Checking Payment Status and Prompting for Payment
--------------------------------------------------
-
-Given the order ID, the status of a payment can be checked with the
-``/private/orders/$ORDER_ID`` endpoint. If the payment is yet to be completed
-by the customer, ``/private/orders/$ORDER_ID`` will give the frontend a URL
-(under the name ``payment_redirect_url``) that will trigger the customer’s
-wallet to execute the payment. This is basically the
-``https://example.com/orders/$ORDER_ID`` URL we discussed above.
-
-
-.. code-block:: python
-
- >>> import requests
- >>> r = requests.get("https://backend.demo.taler.net/instances/sandbox/private/orders/" + order_id,
- ... headers={"Authorization": "Bearer secret-token:sandbox"})
- >>> print(r.json())
-
-If the ``order_status`` field in the response is ``paid``, you will not
-get a ``payment_redirect_url`` and instead information about the
-payment status, including:
-
-- ``contract_terms``: The full contract terms of the order.
-
-- ``refunded``: ``true`` if a (possibly partial) refund was granted for
- this purchase.
-
-- ``refunded_amount``: Amount that was refunded
-
-Once the frontend has confirmed that the payment was successful, it
-usually needs to trigger the business logic for the merchant to fulfill
-the merchant’s obligations under the contract.
-
-.. Note::
- You do not need to keep querying to notice changes
- to the order's transaction status. The endpoints
- support long polling, simply specify a ``timeout_ms``
- query parameter with how long you want to wait at most
- for the order status to change to ``paid``.
-
-
-.. _Giving-Refunds:
-.. index:: refunds
-
-Giving 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.
-Refunds are time-limited and can only happen while the exchange holds
-funds for a particular payment in escrow. The time during which a refund
-is possible can be controlled by setting the ``refund_deadline`` in an
-order. The default value for this refund deadline is specified in the
-configuration of the merchant’s backend.
-
-The frontend can instruct the merchant backend to authorize a refund by
-``POST``\ ing to the ``/private/orders/$ORDER_ID/refund`` endpoint.
-
-The refund request JSON object has only two fields:
-
-- ``refund``: Amount to be refunded. If a previous refund was authorized
- for the same order, the new amount must be higher, otherwise the
- operation has no effect. The value indicates the total amount to be
- refunded, *not* an increase in the refund.
-
-- ``reason``: Human-readable justification for the refund. The reason is
- only used by the Back Office and is not exposed to the customer.
-
-If the request is successful (indicated by HTTP status code 200), the
-response includes a ``taler_refund_uri``. The frontend must redirect
-the customer’s browser to that URL to allow the refund to be processed
-by the wallet.
-
-This code snipped illustrates giving a refund:
-
-.. code-block:: python
-
- >>> import requests
- >>> refund_req = dict(refund="KUDOS:10",
- ... reason="Customer did not like the product")
- >>> requests.post("https://backend.demo.taler.net/instances/sandbox/private/orders/"
- ... + order_id + "/refund", json=refund_req,
- ... headers={"Authorization": "Bearer secret-token:sandbox"})
- <Response [200]>
-
-.. Note::
- After granting a refund, the public
- ``https://example.com/orders/$ORDER_ID`` endpoint will
- change its wallet interaction from requesting payment to
- offering a refund. Thus, frontends may again redirect
- browsers to this endpoint. However, to do so, a
- ``h_contract`` field must be appended
- (``?h_contract=$H_CONTRACT``) as the public endpoint requires
- it to authenticate the client. The required
- ``$H_CONTRACT`` value is returned in the refund response
- under the ``h_contract`` field.
-
-
-.. index:: repurchase
-.. _repurchase:
-
-Repurchase detection and fulfillment URLs
-=========================================
-
-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. 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.
-
-
-.. _Advanced-topics:
-
-Advanced topics
-===============
-
-.. _Session_002dBound-Payments:
-
-Session-Bound Payments
-----------------------
-
-.. index:: session
-
-Sometimes checking if an order has been paid for is not enough. For
-example, when selling access to online media, the publisher may want to
-be paid for exactly the same product by each customer. Taler supports
-this model by allowing the mechant to check whether the “payment
-receipt” is available on the user’s current device. This prevents users
-from easily sharing media access by transmitting a link to the
-fulfillment page. Of course, sophisticated users could share payment
-receipts as well, but this is not as easy as sharing a link, and in this
-case they are more likely to just share the media directly.
-
-To use this feature, the merchant must first assign the user’s current
-browser an ephemeral ``session_id``, usually via a session cookie. When
-executing or re-playing a payment, the wallet will receive an additional
-signature (``session_sig``). This signature certifies that the wallet
-showed a payment receipt for the respective order in the current
-session.
-
-.. index:: cookie
-
-Session-bound payments are triggered by passing the ``session_id``
-parameter to the ``/check-payment`` endpoint. The wallet will then
-redirect to the fulfillment page, but include an additional
-``session_sig`` parameter. The frontend can query ``/check-payment``
-with both the ``session_id`` and the ``session_sig`` to verify that the
-signature is correct.
-
-The last session ID that was successfully used to prove that the payment
-receipt is in the user’s wallet is also available as ``last_session_id``
-in the response to ``/check-payment``.
-
-.. _Product-Identification:
-
-Product Identification
-----------------------
-
-.. index:: resource url
-
-In some situations the user may have paid for some digital good, but the
-frontend does not know the exact order ID, and thus cannot instruct the
-wallet to reveal the existing payment receipt. This is common for simple
-shops without a login system. In this case, the user would be prompted
-for payment again, even though they already purchased the product.
-
-To allow the wallet to instead find the existing payment receipt, the
-shop must use a unique fulfillment URL for each product. Then, the
-frontend must provide an additional ``resource_url`` parameter to to
-``/check-payment``. It should identify this unique fulfillment URL for
-the product. The wallet will then check whether it has paid for a
-contract with the same ``resource_url`` before, and if so replay the
-previous payment.
-
-
-.. _The-Taler-Order-Format:
-
-The Taler Order Format
-----------------------
-
-A Taler order can specify many details about the payment. This section
-describes each of the fields in depth.
-
-Financial amounts are always specified as a string in the format
-``"CURRENCY:DECIMAL_VALUE"``.
-
-.. index:: amount
-
-amount
- Specifies the total amount to be paid to the merchant by the
- customer.
-
-.. index:: fees
-.. index:: maximum deposit fee
-
-max_fee
- This is the maximum total amount of deposit fees that the merchant is
- willing to pay. If the deposit fees for the coins exceed this amount,
- the customer has to include it in the payment total. The fee is
- specified using the same format used for ``amount``.
-
-.. index:: fees
-.. index:: maximum wire fee
-
-max_wire_fee
- 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.
-
-.. index:: fees
-.. index:: maximum fee amortization
-
-wire_fee_amortization
- 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. Zero and negative values are invalid and also
- interpreted as 1.
-
-.. index:: pay_url
-
-pay_url
- Which URL accepts payments. This is the URL where the wallet will
- POST coins.
-
-.. index:: fulfillment URL
-
-fulfillment_url
- Which URL should the wallet go to for obtaining the fulfillment, for
- example the HTML or PDF of an article that was bought, or an order
- tracking system for shipments, or a simple human-readable Web page
- indicating the status of the contract.
-
-.. index:: order ID
-
-order_id
- Alphanumeric identifier, freely definable by the merchant. Used by
- the merchant to uniquely identify the transaction.
-
-.. index:: summary
-
-summary
- Short, human-readable summary of the contract. To be used when
- displaying the contract in just one line, for example in the
- transaction history of the customer.
-
-timestamp
- Time at which the offer was generated.
-
-.. index:: payment deadline
-
-pay_deadline
- Timestamp of the time by which the merchant wants the exchange to
- definitively wire the money due from this contract. Once this
- deadline expires, the exchange will aggregate all deposits where the
- contracts are past the ``refund_deadline`` and execute one large wire
- payment for them. Amounts will be rounded down to the wire transfer
- unit; if the total amount is still below the wire transfer unit, it
- will not be disbursed.
-
-.. index:: refund deadline
-
-refund_deadline
- Timestamp until which the merchant willing (and able) to give refunds
- for the contract using Taler. Note that the Taler exchange will hold
- the payment in escrow at least until this deadline. Until this time,
- the merchant will be able to sign a message to trigger a refund to
- the customer. After this time, it will no longer be possible to
- refund the customer. Must be smaller than the ``pay_deadline``.
-
-.. index:: product description
-
-products
- Array of products that are being sold to the customer. Each entry
- contains a tuple with the following values:
-
- description
- Description of the product.
-
- quantity
- Quantity of the items to be shipped. May specify a unit (e.g. ``1 kg``)
- or just the count.
-
- price
- Price for ``quantity`` units of this product shipped to the given
- ``delivery_location``. Note that usually the sum of all of the prices
- should add up to the total amount of the contract, but it may be
- different due to discounts or because individual prices are
- unavailable.
-
- product_id
- Unique ID of the product in the merchant’s catalog. Can generally
- be chosen freely as it only has meaning for the merchant, but
- should be a number in the range :math:`[0,2^{51})`.
-
- taxes
- Map of applicable taxes to be paid by the merchant. The label is
- the name of the tax, i.e. VAT, sales tax or income tax, and the
- value is the applicable tax amount. Note that arbitrary labels are
- permitted, as long as they are used to identify the applicable tax
- regime. Details may be specified by the regulator. This is used to
- declare to the customer which taxes the merchant intends to pay,
- and can be used by the customer as a receipt. The information is
- also likely to be used by tax audits of the merchant.
-
- delivery_date
- Time by which the product is to be delivered to the
- ``delivery_location``.
-
- delivery_location
- This should give a label in the ``locations`` map, specifying where
- the item is to be delivered.
-
- Values can be omitted if they are not applicable. For example, if a
- purchase is about a bundle of products that have no individual prices
- or product IDs, the ``product_id`` or ``price`` may not be specified in the
- contract. Similarly, for virtual products delivered directly via the
- fulfillment URI, there is no ``delivery_location``.
-
-merchant
- address
- This should give a label in the ``locations`` map, specifying where
- the merchant is located.
-
- name
- This should give a human-readable name for the merchant’s
- business.
-
- jurisdiction
- This should give a label in the ``locations`` map, specifying the
- jurisdiction under which this contract is to be arbitrated.
-
-.. index:: location
-
-locations
- Associative map of locations used in the contract. Labels for
- locations in this map can be freely chosen and used whenever a
- location is required in other parts of the contract. This way, if the
- same location is required many times (such as the business address of
- the customer or the merchant), it only needs to be listed (and
- transmitted) once, and can otherwise be referred to via the label. A
- non-exhaustive list of location attributes is the following:
-
- name
- Receiver name for delivery, either business or person name.
-
- country
- Name of the country for delivery, as found on a postal package,
- e.g. “France”.
-
- state
- Name of the state for delivery, as found on a postal package, e.g.
- “NY”.
-
- region
- Name of the region for delivery, as found on a postal package.
-
- province
- Name of the province for delivery, as found on a postal package.
-
- city
- Name of the city for delivery, as found on a postal package.
-
- zip_code
- ZIP code for delivery, as found on a postal package.
-
- street
- Street name for delivery, as found on a postal package.
-
- street_number
- Street number (number of the house) for delivery, as found on a
- postal package.
-
-
-.. Note::
- Locations are not required to specify all of these fields,
- 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.
diff --git a/taler-merchant-manual.rst b/taler-merchant-manual.rst
@@ -75,7 +75,7 @@ The Taler software stack for a merchant consists of four main 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 :ref:`Merchant API Tutorial <merchant-api-tutorial>` gives an
+ The `Merchant API Tutorial <https://tutorials.taler.net/merchant/api/taler-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
@@ -851,8 +851,8 @@ in the :ref:`Merchant Backend API documentation <merchant-api>`.
.. _instance-account-setup:
-Instance account setup
-======================
+Instance bank account setup
+===========================
Before you can use an instance productively, you need to configure one or more
bank accounts. These bank accounts will be provided to the Taler exchange
@@ -947,17 +947,28 @@ your bank login name and password in the :ref:`instance-account-setup` dialog.
Manually creating an order using the SPA
========================================
+Arbitrary orders can also be created manually using the Web interface of
+the GNU Taler merchant backend. For this, log into the single page app (SPA)
+of the merchant backend using the authorization token of the respective
+instance you want to use.
+
Click on ``Orders`` at the top left corner of the merchant backoffice page; the
following page should appear
.. image:: screenshots/create_orders.png
-After having filled the required fields, the interface should show the
-following page with the related links to check the status of the order and let
-wallets pay for it.
+You can then set up orders by providing all of the required fields of an
+order, in particular an order summary and a price. You can also set various
+optional fields or override instance default settings.
+
+After this the interface should show the following page with the related links
+to check the status of the order and let wallet pay for it.
.. image:: screenshots/payment_links.png
+The order status page also shows you the progress of the order, including when
+a wallet has made the payment. You can also use the backend to approve refunds.
+
In order to test the setup, it should be now possible to use the command line wallet
to withdraw Taler coins and spend them to pay for the order we just created.
@@ -969,6 +980,240 @@ to provide the respective front-ends with the URL of your instance
(e.g. ``https://backend.$DOMAIN/instances/$NAME``) and your access token.
+Paying an order
+===============
+
+The payer simply scans the (dynamic) QR code to initiate the payment. If a
+website is interacting with a WebExtension wallet, it may also directly
+trigger the GNU Taler wallet without requiring the user to explicitly scan the
+QR code. The payer should now review the contract terms and applicable fees.
+Selecting "pay" will complete the transaction. Typically, the wallet will
+then redirect the user to the fulfillment page where they can track the order
+or directly view the digital product that they purchased.
+
+
+Setting up a template
+=====================
+
+A template provides all or part of the information needed to setup an order
+and allows GNU Taler wallets to create an order. Usually, the creation of
+orders is a privileged process that requires knowledge of the authorization
+code for the respective instance. With templates, a customer's wallet can
+directly create an order on-demand. The information of a template can be
+partial, in which case the customer is expected to provide the remaining
+details, typically the summary and/or amount of the order.
+
+When setting up a template you need to specify all of the fixed inputs that
+the customer cannot change. You can then generate a template QR code where
+you may additionally specify editable defaults for the order, such as a
+default summary or a default amount which may still be changed by the wallet.
+The resulting template QR code encodes the specific merchant backend, instance
+and template ID as well as the (editable) default values. The resulting
+static QR code can then be printed and put on display.
+
+Customers can scan the QR code with their GNU Taler wallet, complete the
+missing details or edit the defaults (if any), and pay the resulting order.
+
+To secure template-based payments, you may specify a TOTP secret as part of
+the template. In this case, the merchant backend will send a set of TOTP
+payment confirmation codes to the GNU Taler wallet upon receiving a payment
+for an order created based on the template. If the point-of-sale has a TOTP
+generator with the same secret, they can compare their TOTP code with the
+codes shown by the customer on their wallet. This provides additional
+assurance that the customer actually made the payment instead of just showing
+a fake confirmation screen.
+
+
+Paying with static QR codes
+===========================
+
+The payer simply scans the (static) QR code to initiate the payment. If the
+template does not specify a fixed amount, the payer will be prompted to enter
+the amount to be paid (and possibly given the opportunity to specify or alter
+the summary). Selecting "pay" will complete the transaction. If payment
+confirmations are configured by the merchant backend, the wallet will then
+display a TOTP confirmation code that can be shown to the merchant as a proof
+of payment.
+
+
+
+Setting up a webhook
+====================
+
+To receive notifications when a purchase has been made or a refund was given
+to a wallet, you can set up webhooks in the GNU Taler merchant backend.
+Webhooks allow you to trigger HTTP(S) requests based on certain events. A
+webhook is thus simply an HTTP request that the GNU Taler merchant backend
+will make when a certain event (such as a payment) happens.
+
+There are various providers that can send an SMS to a phone number based on an
+HTTP request. Thus, by configuring such a provider in a webhook you can
+receive an SMS notification whenever a customer makes a payment.
+
+Webhooks are configured per instance. In the Webhook configuration,
+you can specify which URL, which HTTP headers, which HTTP method and what HTTP
+body to send to the Webhook. Webhooks are automatically retried (with
+increasing delays) when the target server returns a temporary error.
+
+`Mustach templates <https://mustache.github.io/mustache.5.html>`__ and limited
+version of it are used when defining the contents of Webhooks.
+Depending on the triggering event, the templates will be expanded with event-specific
+data. Limited in this case means that only a specific string is being replaced
+with the event-specific data, no support for parsing conditions or nested structures
+is provided.
+
+
+Order pay events
+----------------
+
+For "pay" events, the backend will provide the following
+information to the Mustache templating engine:
+
+* :ref:`contract_terms <contract-terms>`: the contract terms of the paid order.
+* order_id: the ID of the order that received the refund.
+
+
+Order refund events
+-------------------
+
+For "refund" events, the backend will provide the following information to the
+Mustache templating engine:
+
+* timestamp: time of the refund (in nanoseconds since 1970).
+* order_id: the ID of the order that received the refund.
+* :ref:`contract_terms <contract-terms>`: the full JSON of the contract terms of the refunded order.
+* refund_amount: the amount that was being refunded.
+* reason: the reason entered by the merchant staff for granting the refund;
+ be careful, you probably want to inform your staff if a webhook may expose
+ this information to the consumer.
+
+
+Order settled events
+--------------------
+
+For "order_settled" events, the backend will provide the following information to the limited
+Mustache templating engine:
+
+* order_id: The unique identifier of the order that has been fully settled (all payments completed and wired to the merchant).
+
+
+Category added events
+---------------------
+
+For "category_added" events, the backend will provide the following information to the limited
+Mustache templating engine:
+
+* webhook_type: "category_added".
+* category_serial: The unique identifier of the newly added category.
+* category_name: The name of the newly added category.
+* merchant_serial: The unique identifier of the merchant associated with the category.
+
+
+Category updated events
+-----------------------
+
+For "category_updated" events, the backend will provide the following information to the limited
+Mustache templating engine:
+
+* webhook_type: "category_updated".
+* category_serial: The unique identifier of the updated category.
+* old_category_name: The name of the category before the update.
+* category_name: The name of the category after the update.
+* category_name_i18n: The internationalized name of the category after the update.
+* old_category_name_i18n: The internationalized name of the category before the update.
+
+
+Category deleted events
+-----------------------
+
+For "category_deleted" events, the backend will provide the following information to the limited
+Mustache templating engine:
+
+* webhook_type: "category_deleted".
+* category_serial: The unique identifier of the deleted category.
+* category_name: The name of the deleted category.
+
+
+Inventory added events
+----------------------
+
+For "inventory_added" events, the backend will provide the following information to the limited
+Mustache templating engine:
+
+* webhook_type: "inventory_added".
+* product_serial: The unique identifier of the newly added product.
+* product_id: The ID of the newly added product.
+* description: The description of the newly added product.
+* description_i18n: The internationalized description of the newly added product.
+* unit: The unit of the newly added product.
+* image: The image of the newly added product.
+* taxes: The taxes of the newly added product.
+* price: The price of the newly added product.
+* total_stock: The total stock of the newly added product.
+* total_sold: The total sold of the newly added product.
+* total_lost: The total lost of the newly added product.
+* address: The address of the newly added product.
+* next_restock: The next restock of the newly added product.
+* minimum_age: The minimum age for buying the newly added product.
+
+Inventory updated events
+------------------------
+
+For "inventory_updated" events, the backend will provide the following information to the limited
+Mustache templating engine:
+
+* webhook_type: "inventory_updated".
+* product_serial: The unique identifier of the updated product.
+* product_id: The ID of the product.
+* old_description: The description of the product before the update.
+* description: The description of the product after the update.
+* old_description_i18n: The internationalized description of the product before the update.
+* description_i18n: The internationalized description of the product after the update.
+* old_unit: The unit of the product before the update.
+* unit: The unit of the product after the update.
+* old_image: The image of the product before the update.
+* image: The image of the product after the update.
+* old_taxes: The taxes of the product before the update.
+* taxes: The taxes of the product after the update.
+* old_price: The price of the product before the update.
+* price: The price of the product after the update.
+* old_total_stock: The total stock of the product before the update.
+* total_stock: The total stock of the product after the update.
+* old_total_sold: The total sold of the product before the update.
+* total_sold: The total sold of the product after the update.
+* old_total_lost: The total lost of the product before the update.
+* total_lost: The total lost of the product after the update.
+* old_address: The address of the product before the update.
+* address: The address of the product after the update.
+* old_next_restock: The next restock of the product before the update.
+* next_restock: The next restock of the product after the update.
+* old_minimum_age: The minimum age for buying the product before the update.
+* minimum_age: The minimum age for buying the product after the update.
+
+
+Inventory deleted events
+------------------------
+
+For "inventory_deleted" events, the backend will provide the following information to the limited
+Mustache templating engine:
+
+* webhook_type: "inventory_deleted".
+* product_serial: The unique identifier of the deleted product.
+* product_id: The ID of the deleted product.
+* description: The description of the deleted product.
+* description_i18n: The internationalized description of the deleted product.
+* unit: The unit of the deleted product.
+* image: The image of the deleted product.
+* taxes: The taxes of the deleted product.
+* price: The price of the deleted product.
+* total_stock: The total stock of the deleted product.
+* total_sold: The total sold of the deleted product.
+* total_lost: The total lost of the deleted product.
+* address: The address of the deleted product.
+* next_restock: The next restock of the deleted product.
+* minimum_age: The minimum age for buying the deleted product.
+
+
.. _Secure-setup:
Secure setup
diff --git a/taler-merchant-pos-terminal.rst b/taler-merchant-pos-terminal.rst
@@ -17,8 +17,8 @@
.. _taler-merchant-pos-app:
-Merchant Point of Sale App
-##########################
+Merchant Point of Sale App Manual
+#################################
The GNU Taler merchant point of sale (POS) App allows sellers to
diff --git a/taler-user-guide.rst b/taler-user-guide.rst
@@ -1,457 +0,0 @@
-..
- This file is part of GNU TALER.
- Copyright (C) 2014-2023 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU Affero 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 Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-
- @author Christian Grothoff
-
-
-User Guide
-##########
-
-.. contents:: Table of Contents
- :depth: 1
- :local:
-
-Introduction
-============
-
-About GNU Taler
----------------
-
-.. include:: frags/about-taler.rst
-
-
-About this guide
-----------------
-
-This guide explains various ways how users can interact with a GNU Taler
-installation. It assumes that a bank, exchange and merchant backend are
-running and that the user has a GNU Taler wallet installed is able to create
-an account at the bank. Some operations also require access to the merchant
-backend.
-
-
-Withdrawing from bank accounts
-==============================
-
-Withdrawing is the step where money is moved from a bank account into
-a GNU Taler wallet. There are two main ways to do this.
-
-Bank integrated withdrawal
---------------------------
-
-If the bank supports it, you can withdraw money into your GNU Taler wallet
-directly from your banking app or online banking website. If supported, there
-should be an option in your online banking to withdraw money to a GNU Taler
-wallet. The bank should ask for the amount and then generate a QR code that
-you need to scan with your GNU Taler wallet. Alternatively, if the
-WebExtension wallet is installed, the bank website may directly switch to the
-GNU Taler wallet. In the GNU Taler wallet, you may have to first confirm the
-terms of service of the selected GNU Taler exchange. Afterwards, applicable
-fees will be shown and you will be given the option to accept the withdrawal.
-Next, you need to authorize the withdraw operation in the bank. If possible,
-the GNU Taler wallet may automatically switch to the bank's website, it is
-also possible that you have to go back to the banking app explicitly. After
-authorizing the withdraw operation, you will have to wait a bit for the money
-to be wired to the exchange. Depending on the banking system, this can take
-anywhere from a few seconds to many hours. Afterwards, the money will show up
-in your wallet.
-
-Wallet initiated withdrawal
----------------------------
-
-In this case, you will start the withdraw process from the GNU Taler wallet.
-Under "Settings", you will find a list of exchanges. If the list is empty or
-does not contain the desired exchange, you may have to first add the exchange
-by providing the respective URL. The payment service provider operating the
-exchange service should have such a QR code on their Web site.
-
-Next to the exchange, there is a drop-down menu with an option to "withdraw".
-(If you already have money in your wallet, you will also find the same button
-when viewing the transaction history of the respective currency.) The wallet
-will ask you to enter the amount to withdraw and accept the terms of service
-and to pay the applicable fees (if any). Afterwards, the wallet will give you
-wire instructions, telling you which amount to wire to which bank account.
-Most importantly, the wallet will give you a wire transfer subject that must
-be specified for the wire transfer. If you make a typo in the subject, the
-wallet will not be topped up and the exchange will send the money back to your
-bank account eventually (possibly minus a fee). Simply make the wire transfer
-as instructed by the wallet. Once the money has arrived at the exchange, the
-wallet will automatically withdraw the funds.
-
-
-Depositing into bank accounts
-=============================
-
-If you have money in your wallet, you can use the "deposit" button to deposit
-the funds into a bank account. The wallet will ask you to specify the amount
-and the target bank account.
-
-
-Sending digital cash
-====================
-
-Once you have digital cash, you can send it to another GNU Taler
-wallet. Simply specify the amount and a human-readable reason for the
-transfer. The wallet will then show a QR code (and give the option to export
-the payment as a taler://-URL). Send the image of the QR code to the
-receiving wallet (or send the taler://-URL securely to the target wallet).
-
-The target wallet should scan the QR code (or enter the text of the
-taler://-URL into the URL import dialog which is available by holding or
-clicking the QR code scan button). Afterwards, review the reason text and
-accept the funds to complete the transaction.
-
-
-Receiving digital cash
-======================
-
-To receive funds from another user, you can send a payment request to another GNU
-Taler wallet. Simply specify the amount and a human-readable reason for the
-payment request. The wallet will then show a QR code (and give the option to export
-the payment request as a taler://-URL). Send the image of the QR code to the payer
-wallet (or send the taler://-URL to the target wallet).
-
-The target wallet should scan the QR code (or enter the text of the
-taler://-URL into the URL import dialog which is available by holding or
-clicking the QR code scan button). Afterwards, review the reason for
-the payment request and decide whether or not to pay it. Selecting
-"pay" will complete the transaction.
-
-Depending on the configuration of the exchange, the receiving wallet may have
-to undergo some KYC check before the funds are actually released to the
-receiver.
-
-
-.. index:: instance
-.. _Instance-account-configuration:
-
-Configuring Accounts at a Merchant Instance
-===========================================
-
-Before you can setup a merchant instance, you need somebody to operate a
-`Taler Merchant Backend <taler-merchant-backend-operator-manual>`_ and `grant
-you access to an instance <Instance-setup>`_ at that backend. For this, you
-should receive the base URL of the instance and an access token.
-
-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://``-URI.
-See `RFC 8905 <https://tools.ietf.org/html/rfc8905>`_
-for the format of ``payto://``-URIs. Note that the "receiver-name" is
-optional in RFC 8905 but mandatory in GNU Taler.
-
-For first tests, you may want to sign up for a KUDOS bank account at
-`https://bank.demo.taler.net/ <https://bank.demo.taler.net/>`_. In this case,
-the ``payto://``-URI will be of the form
-``payto://iban/$IBAN?receiver-name=$NAME`` where ``$IBAN`` must be replaced
-with the IBAN shown on the main page of the account shown at
-`https://bank.demo.taler.net/ <https://bank.demo.taler.net/>`_ after logging
-in.
-
-When deploying Taler with the real banking system, you primarily need to
-change the currency of the configuration from KUDOS to the actual currency
-(such as EUR, USD, CHF) and provide a ``payto://``-URI of your actual bank
-account. In Europe, this will involve knowing your IBAN number. If you have an
-IBAN, the corresponding ``payto://``-URI is simply
-``payto://iban/$IBAN?receiver-name=$NAME`` where ``$IBAN`` must be replaced
-with the actual IBAN number and ``$NAME`` with your actual name. Make sure to
-URI-encode your name. The merchant SPA will do this automatically when you
-use it to configure the bank account.
-
-
-
-Using the Point-of-Sale App
-===========================
-
-A simple way for merchants to accept GNU Taler payments is the use of the
-point-of-sale app. The app can be installed on an Android phone or tablet
-and is configured via a simple JSON file on a Web site:
-
-* In the app settings you need to specify the URL of the Web site where
- the app can download the categories, products and prices from which
- orders are to be compiled. You can optionally specify a username and
- password to authenticate to the Web server.
-
-* The syntax of the JSON file is described in the point-of-sale app
- manual. However, you may simply want to download the sample JSON
- file from our documentation and use it as a starting point.
-
-* A key option is the merchant backend with the authorization key
- which must be included in this JSON configuration. You may point
- the point-of-sale app to any instance of a merchant backend.
-
-Once configured, the point-of-sale app allows the user to select a product
-category and then to quickly add products from that category to an order. You
-can easily edit the order, and finally use the "complete" button to generate a
-QR code. The QR code must then be scanned by the GNU Taler wallet to initiate
-the payment. Multiple orders can be entered concurrently, for example in a
-restaurant where multiple tables are waited on at the same time.
-
-
-Setting up an order in the merchant backoffice SPA
-==================================================
-
-Arbitrary orders can also be created manually using the Web interface of
-the GNU Taler merchant backend. For this, log into the single page app (SPA)
-of the merchant backend using the authorization token of the respective
-instance you want to use.
-
-You can then set up orders by providing all of the required fields of an
-order, in particular an order summary and a price. You can also set various
-optional fields or override instance default settings.
-
-When the order has been setup, you can follow a link to the payment page
-which will show the QR code (and/or URL) that a GNU Taler wallet would need
-to receive to initiate the payment process. The order status page also
-shows you the progress of the order, including when a wallet has made the
-payment. You can also use the backend to approve refunds.
-
-
-Paying an order
-===============
-
-The payer simply scans the (dynamic) QR code to initiate the payment. If a
-website is interacting with a WebExtension wallet, it may also directly
-trigger the GNU Taler wallet without requiring the user to explicitly scan the
-QR code. The payer should now review the contract terms and applicable fees.
-Selecting "pay" will complete the transaction. Typically, the wallet will
-then redirect the user to the fulfillment page where they can track the order
-or directly view the digital product that they purchased.
-
-
-Setting up a template
-=====================
-
-A template provides all or part of the information needed to setup an order
-and allows GNU Taler wallets to create an order. Usually, the creation of
-orders is a privileged process that requires knowledge of the authorization
-code for the respective instance. With templates, a customer's wallet can
-directly create an order on-demand. The information of a template can be
-partial, in which case the customer is expected to provide the remaining
-details, typically the summary and/or amount of the order.
-
-When setting up a template you need to specify all of the fixed inputs that
-the customer cannot change. You can then generate a template QR code where
-you may additionally specify editable defaults for the order, such as a
-default summary or a default amount which may still be changed by the wallet.
-The resulting template QR code encodes the specific merchant backend, instance
-and template ID as well as the (editable) default values. The resulting
-static QR code can then be printed and put on display.
-
-Customers can scan the QR code with their GNU Taler wallet, complete the
-missing details or edit the defaults (if any), and pay the resulting order.
-
-To secure template-based payments, you may specify a TOTP secret as part of
-the template. In this case, the merchant backend will send a set of TOTP
-payment confirmation codes to the GNU Taler wallet upon receiving a payment
-for an order created based on the template. If the point-of-sale has a TOTP
-generator with the same secret, they can compare their TOTP code with the
-codes shown by the customer on their wallet. This provides additional
-assurance that the customer actually made the payment instead of just showing
-a fake confirmation screen.
-
-
-Paying with static QR codes
-===========================
-
-The payer simply scans the (static) QR code to initiate the payment. If the
-template does not specify a fixed amount, the payer will be prompted to enter
-the amount to be paid (and possibly given the opportunity to specify or alter
-the summary). Selecting "pay" will complete the transaction. If payment
-confirmations are configured by the merchant backend, the wallet will then
-display a TOTP confirmation code that can be shown to the merchant as a proof
-of payment.
-
-
-
-Setting up a webhook
-====================
-
-To receive notifications when a purchase has been made or a refund was given
-to a wallet, you can set up webhooks in the GNU Taler merchant backend.
-Webhooks allow you to trigger HTTP(S) requests based on certain events. A
-webhook is thus simply an HTTP request that the GNU Taler merchant backend
-will make when a certain event (such as a payment) happens.
-
-There are various providers that can send an SMS to a phone number based on an
-HTTP request. Thus, by configuring such a provider in a webhook you can
-receive an SMS notification whenever a customer makes a payment.
-
-Webhooks are configured per instance. In the Webhook configuration,
-you can specify which URL, which HTTP headers, which HTTP method and what HTTP
-body to send to the Webhook. Webhooks are automatically retried (with
-increasing delays) when the target server returns a temporary error.
-
-`Mustach templates <https://mustache.github.io/mustache.5.html>`__ and limited
-version of it are used when defining the contents of Webhooks.
-Depending on the triggering event, the templates will be expanded with event-specific
-data. Limited in this case means that only a specific string is being replaced
-with the event-specific data, no support for parsing conditions or nested structures
-is provided.
-
-
-Order pay events
-----------------
-
-For "pay" events, the backend will provide the following
-information to the Mustache templating engine:
-
-* :ref:`contract_terms <contract-terms>`: the contract terms of the paid order.
-* order_id: the ID of the order that received the refund.
-
-
-Order refund events
--------------------
-
-For "refund" events, the backend will provide the following information to the
-Mustache templating engine:
-
-* timestamp: time of the refund (in nanoseconds since 1970).
-* order_id: the ID of the order that received the refund.
-* :ref:`contract_terms <contract-terms>`: the full JSON of the contract terms of the refunded order.
-* refund_amount: the amount that was being refunded.
-* reason: the reason entered by the merchant staff for granting the refund;
- be careful, you probably want to inform your staff if a webhook may expose
- this information to the consumer.
-
-
-Order settled events
---------------------
-
-For "order_settled" events, the backend will provide the following information to the limited
-Mustache templating engine:
-
-* order_id: The unique identifier of the order that has been fully settled (all payments completed and wired to the merchant).
-
-
-Category added events
----------------------
-
-For "category_added" events, the backend will provide the following information to the limited
-Mustache templating engine:
-
-* webhook_type: "category_added".
-* category_serial: The unique identifier of the newly added category.
-* category_name: The name of the newly added category.
-* merchant_serial: The unique identifier of the merchant associated with the category.
-
-
-Category updated events
------------------------
-
-For "category_updated" events, the backend will provide the following information to the limited
-Mustache templating engine:
-
-* webhook_type: "category_updated".
-* category_serial: The unique identifier of the updated category.
-* old_category_name: The name of the category before the update.
-* category_name: The name of the category after the update.
-* category_name_i18n: The internationalized name of the category after the update.
-* old_category_name_i18n: The internationalized name of the category before the update.
-
-
-Category deleted events
------------------------
-
-For "category_deleted" events, the backend will provide the following information to the limited
-Mustache templating engine:
-
-* webhook_type: "category_deleted".
-* category_serial: The unique identifier of the deleted category.
-* category_name: The name of the deleted category.
-
-
-Inventory added events
-----------------------
-
-For "inventory_added" events, the backend will provide the following information to the limited
-Mustache templating engine:
-
-* webhook_type: "inventory_added".
-* product_serial: The unique identifier of the newly added product.
-* product_id: The ID of the newly added product.
-* description: The description of the newly added product.
-* description_i18n: The internationalized description of the newly added product.
-* unit: The unit of the newly added product.
-* image: The image of the newly added product.
-* taxes: The taxes of the newly added product.
-* price: The price of the newly added product.
-* total_stock: The total stock of the newly added product.
-* total_sold: The total sold of the newly added product.
-* total_lost: The total lost of the newly added product.
-* address: The address of the newly added product.
-* next_restock: The next restock of the newly added product.
-* minimum_age: The minimum age for buying the newly added product.
-
-Inventory updated events
-------------------------
-
-For "inventory_updated" events, the backend will provide the following information to the limited
-Mustache templating engine:
-
-* webhook_type: "inventory_updated".
-* product_serial: The unique identifier of the updated product.
-* product_id: The ID of the product.
-* old_description: The description of the product before the update.
-* description: The description of the product after the update.
-* old_description_i18n: The internationalized description of the product before the update.
-* description_i18n: The internationalized description of the product after the update.
-* old_unit: The unit of the product before the update.
-* unit: The unit of the product after the update.
-* old_image: The image of the product before the update.
-* image: The image of the product after the update.
-* old_taxes: The taxes of the product before the update.
-* taxes: The taxes of the product after the update.
-* old_price: The price of the product before the update.
-* price: The price of the product after the update.
-* old_total_stock: The total stock of the product before the update.
-* total_stock: The total stock of the product after the update.
-* old_total_sold: The total sold of the product before the update.
-* total_sold: The total sold of the product after the update.
-* old_total_lost: The total lost of the product before the update.
-* total_lost: The total lost of the product after the update.
-* old_address: The address of the product before the update.
-* address: The address of the product after the update.
-* old_next_restock: The next restock of the product before the update.
-* next_restock: The next restock of the product after the update.
-* old_minimum_age: The minimum age for buying the product before the update.
-* minimum_age: The minimum age for buying the product after the update.
-
-
-Inventory deleted events
-------------------------
-
-For "inventory_deleted" events, the backend will provide the following information to the limited
-Mustache templating engine:
-
-* webhook_type: "inventory_deleted".
-* product_serial: The unique identifier of the deleted product.
-* product_id: The ID of the deleted product.
-* description: The description of the deleted product.
-* description_i18n: The internationalized description of the deleted product.
-* unit: The unit of the deleted product.
-* image: The image of the deleted product.
-* taxes: The taxes of the deleted product.
-* price: The price of the deleted product.
-* total_stock: The total stock of the deleted product.
-* total_sold: The total sold of the deleted product.
-* total_lost: The total lost of the deleted product.
-* address: The address of the deleted product.
-* next_restock: The next restock of the deleted product.
-* minimum_age: The minimum age for buying the deleted product.
diff --git a/tutorials.rst b/tutorials.rst
@@ -0,0 +1,6 @@
+Tutorials
+=========
+
+You can access the tutorials at:
+
+`https://tutorials.taler.net/ <https://tutorials.taler.net/>`_