taler-docs

Documentation for GNU Taler components, APIs and protocols
Log | Files | Refs | README | LICENSE

commit eda86e5f4883513a3586cc35ee355968d18c335a
parent dc5af7eebfd05cca4acca313c4c544f4cace59f6
Author: Christian Grothoff <christian@grothoff.org>
Date:   Tue,  4 Aug 2026 19:18:19 +0200

also allow '~' in slugs, for consistency with libeufin.
Also spec for multiple editable-amounts in paivana templates.

Diffstat:
Mcore/api-common.rst | 9+++++----
Mcore/api-merchant.rst | 51+++++++++++++++++++++++++++++++++++++++++++++++++--
Mcore/corebank/post-accounts.rst | 7+++++--
Mcore/merchant/get-templates-TEMPLATE_ID.rst | 4+++-
Mcore/merchant/post-templates-TEMPLATE_ID.rst | 38++++++++++++++++++++++++++++++++++++++
5 files changed, 100 insertions(+), 9 deletions(-)

diff --git a/core/api-common.rst b/core/api-common.rst @@ -292,8 +292,8 @@ without any escaping. We call such an identifier a *slug*. // Non-empty string that can be used as-is as a single path // component of a URL. A slug must only use ASCII alphanumeric - // characters ("A-Z", "a-z", "0-9") and the five punctuation - // characters "-", ".", "_", ":" and "=". Consequently a slug + // characters ("A-Z", "a-z", "0-9") and the six punctuation + // characters "-", ".", "_", ":", "=" and "~". Consequently a slug // never contains a "/" and never requires percent-encoding. // The strings "." and ".." are not valid slugs, as they have a // special meaning in URL paths. @@ -302,8 +302,9 @@ without any escaping. We call such an identifier a *slug*. // documented with the respective endpoint or field. type Slug = string; -This character set is deliberately narrower than what RFC 3986 permits in a -path segment: it excludes ``@``, ``~`` and all sub-delimiters except ``=``, +A slug is thus the set of RFC 3986 *unreserved* characters, plus ``:`` and +``=``. The character set is deliberately narrower than what RFC 3986 permits +in a path segment: it excludes ``@`` and all sub-delimiters except ``=``, which are legal in a URL path but cause trouble once a slug is embedded in other syntax, such as a shell command, a query string or a filename. ``=`` is permitted because base64-encoded identifiers may end in padding. diff --git a/core/api-merchant.rst b/core/api-merchant.rst @@ -29,7 +29,7 @@ Merchant Backend RESTful API Version History --------------- -The currently implemented protocol version is **v33**. +The currently implemented protocol version is **v34**. * The Android PoS app is currently targeting **v20**. * The SPA is currently targeting **vXX**. @@ -62,6 +62,10 @@ The currently implemented protocol version is **v33**. * ``v33``: adds ``build_version`` to :http:get:`/config </config>` and ``max_age_s`` to ``[/instances/$INSTANCE]/private/orders``, deprecating the ``max_age`` query parameter of that endpoint +* ``v34``: adds ``editable_amount`` to the choices of a Paivana template + together with the ``choice_amounts`` request field to instantiate them, + and ``min_amount``/``max_amount`` to bound client-chosen amounts for + templates of any type **Upcoming versions:** @@ -1106,6 +1110,24 @@ open or deferred. // if "amount" is given. currency?: string; + // Lower bound (inclusive) on amounts the client gets to choose + // when instantiating this template. Excludes any tip. Only + // amounts the client had an influence on are checked against + // this bound: the amount given in the request for a "fixed-order" + // template, the total of the selected products for an + // "inventory-cart" template, and the amount of an editable choice + // for a "paivana" template. Requires "currency" to be given and + // to match, and must not exceed "max_amount". + // Since protocol **v34**. + min_amount?: Amount; + + // Upper bound (inclusive) on amounts the client gets to choose + // when instantiating this template. Excludes any tip. Checked + // against the same amounts as "min_amount". Requires "currency" + // to be given and to match. + // Since protocol **v34**. + max_amount?: Amount; + // The time the customer need to pay before his order will be deleted. // It is deleted if the customer did not pay and if the duration is over. pay_duration?: RelativeTime; @@ -1180,9 +1202,17 @@ open or deferred. website_regex?: string; // Methods to pay for the contract. - choices: OrderChoice[]; + choices: TemplateOrderChoice[]; } + If exactly one of the ``choices`` of a Paivana template has + ``editable_amount`` set, the template may also carry an ``amount`` in its + ``editable_defaults`` to tell the user interface to offer a single amount + field with that default; the client then submits it as the ``amount`` of + the `UsingTemplateCommonRequest`. With more than one editable choice, the + defaults are the ``amount`` values of the choices themselves and the client + must use ``choice_amounts``. + .. _template-choice: Template Choices @@ -1225,6 +1255,23 @@ Template Choices max_fee?: Amount; } + A choice of a *template* contract may additionally allow the client to + replace the amount when the template is instantiated. + + .. ts:def:: TemplateOrderChoice + + interface TemplateOrderChoice extends OrderChoice { + // If true, the client may replace "amount" when instantiating + // the template; "amount" then merely provides the default. The + // client may only change the value, never the currency. The + // resulting amount is subject to the "min_amount" and + // "max_amount" bounds of the template (if any). + // Defaults to false, in which case the amount is fixed by the + // merchant. + // Since protocol **v34**. + editable_amount?: boolean; + } + .. ts:def:: OrderInput // For now, only token inputs are supported. diff --git a/core/corebank/post-accounts.rst b/core/corebank/post-accounts.rst @@ -9,8 +9,11 @@ .. ts:def:: RegisterAccountRequest interface RegisterAccountRequest { - // Username of the account - // Must match [a-zA-Z0-9-._~]{1, 126} + // Username of the account. + // Must be at most 126 characters long. Implementations + // may further restrict the character set; libeufin-bank + // accepts only the RFC 3986 unreserved characters (that + // is, a slug without ":" and "="). username: Slug; // Password of the account used for authentication diff --git a/core/merchant/get-templates-TEMPLATE_ID.rst b/core/merchant/get-templates-TEMPLATE_ID.rst @@ -47,7 +47,9 @@ // may reject requests if the ``template_contract`` // or ``editable_defaults`` do // specify an amount in a different currency. - // This parameter is optional. + // This parameter is optional; since protocol **v34** it is + // returned whenever the ``template_contract`` specifies a + // ``currency``. // Since protocol **v13**. required_currency?: string; } diff --git a/core/merchant/post-templates-TEMPLATE_ID.rst b/core/merchant/post-templates-TEMPLATE_ID.rst @@ -24,6 +24,17 @@ The template, instance, or product is unknown. Returned with ``TALER_EC_MERCHANT_GENERIC_TEMPLATE_UNKNOWN`` or ``TALER_EC_MERCHANT_GENERIC_PRODUCT_UNKNOWN``. + :http:statuscode:`409 Conflict`: + The request contradicts the template. In particular, this is + returned with ``TALER_EC_MERCHANT_POST_USING_TEMPLATES_AMOUNT_CONFLICT_TEMPLATES_CONTRACT_AMOUNT`` + if the template fixes the amount but the request provides one, if + ``amount`` and ``choice_amounts`` are both given, if ``amount`` is + used as a shorthand but the template has no or more than one choice + with ``editable_amount``, if a ``choice_amounts`` entry selects a + choice without ``editable_amount``, or if a client-chosen amount + violates the ``min_amount`` or ``max_amount`` of the template. + Returned with ``TALER_EC_MERCHANT_GENERIC_CURRENCY_MISMATCH`` if a + client-chosen amount is in the wrong currency. :http:statuscode:`413 Request entity too large`: The uploaded body is to long, it exceeds the size limit. Returned with an error code of @@ -60,6 +71,12 @@ summary?: string; // The amount to be paid, including tip. + // For a "paivana" template, this is a shorthand that is only + // allowed if exactly one of the choices of the template has + // "editable_amount" set: the amount then replaces the amount of + // that choice, the tip is added on top of it (as for a choice + // with a fixed amount), and the field is mutually exclusive with + // "choice_amounts". amount?: Amount; // Optional tip amount. Must match the currency of ``amount`` or the @@ -121,4 +138,25 @@ // access control. paivana_id: string; + // Amounts chosen by the client for the choices of the template + // that have "editable_amount" set. Choices that are not + // mentioned keep the amount given in the template. Mutually + // exclusive with the "amount" field. + // Since protocol **v34**. + choice_amounts?: TemplateChoiceAmount[]; + + } + + .. ts:def:: TemplateChoiceAmount + + interface TemplateChoiceAmount { + // Index of the choice in the "choices" array of the template + // contract. The choice must have "editable_amount" set. + choice_index: Integer; + + // Amount to use for that choice, excluding any tip. Must be in + // the currency of the choice, and within the "min_amount" and + // "max_amount" bounds of the template (if any). Any "tip" given + // in the request is added on top of this amount. + amount: Amount; }