diff options
Diffstat (limited to 'orphaned')
-rw-r--r-- | orphaned/README | 2 | ||||
-rw-r--r-- | orphaned/python-guidelines.rst | 56 | ||||
-rw-r--r-- | orphaned/qa-0.9.4.rst | 228 | ||||
-rw-r--r-- | orphaned/taler-mcig.rst | 563 | ||||
-rw-r--r-- | orphaned/taler-nfc-guide.rst | 285 |
5 files changed, 1134 insertions, 0 deletions
diff --git a/orphaned/README b/orphaned/README new file mode 100644 index 00000000..4035e4b4 --- /dev/null +++ b/orphaned/README @@ -0,0 +1,2 @@ +This document contains documentation that we currently don't link anywhere, +but that we might still want to salvage sometime. diff --git a/orphaned/python-guidelines.rst b/orphaned/python-guidelines.rst new file mode 100644 index 00000000..8a644ced --- /dev/null +++ b/orphaned/python-guidelines.rst @@ -0,0 +1,56 @@ +Guidelines for Python Packages +============================== + +This document describes conventions used for Python repos in the Taler project. + + +Packaging +--------- + +* We use `poetry <https://github.com/python-poetry/poetry>`__ for managing dependencies and dev-dependencies. +* The ``poetry.lock`` file must be committed to repo. +* Entry points **must not** be defined as shell scripts. Instead, use poetry's script facility to define entry points. This makes the package work on different platforms properly. + + +GNU Compatibility Layer +----------------------- + +In addition to the Python-native tooling, we provide a GNU-style interface for the build system. +The commands supported by every Python repo should be: + +* ``./bootstrap``: Only necessary when the repo is checked out via git. + Initializes the build system and checks out git submodules if applicable. +* ``./configure``: Should check for build-time dependencies, **including** Python tooling. +* ``make``: Invoking make without a target should create the Python wheel for the project. +* ``make install``: Installation should **only** install the Python package + based on the wheel via ``pip``. Note that we can't do dependency tracking + properly, so the ``install`` target will always re-build the wheel and + install it. +* ``make pretty``: Should invoke the pretty-printer (``black`` for Python projects). +* ``make dist``: This should create the source tarball. +* ``make clean``: Should delete generated files. + +The `build-common.git <https://git.taler.net/build-common.git/>`__ repository contains helpers +to make the GNU compatibility easier. Here are some hints for using it: + +* The ``build-common.git`` repo should added as a submodule in the path ``build-system/taler-build-scripts`` + of the repository. +* The `bootstrap template <https://git.taler.net/build-common.git/tree/bootstrap.template>`__ should + be copied as ``./bootstrap`` to the root of the repository. +* The configure script is automatically created by ``./bootstrap``. +* Dependencies for the configure file are defined in ``build-system/configure.py``. + There is no documentation yet, but adjusting the `example file <https://git.taler.net/build-common.git/tree/testconfigure.py>`__ is a good starting point. +* The source distribution (``make dist``) should either be created via ``poetry build -f sdist`` + or using the `git-archive-all <https://git.taler.net/build-common.git/tree/archive-with-submodules/git_archive_all.py>`__. + +Formatting +---------- + +* We follow `pep8 <https://www.python.org/dev/peps/pep-0008/>`__. +* Code should be auto-formatted with `black <https://github.com/psf/black>`__. + + +Distro Packaging +---------------- + +For Debian, we should try to use `wheel2deb <https://github.com/upciti/wheel2deb>`__. diff --git a/orphaned/qa-0.9.4.rst b/orphaned/qa-0.9.4.rst new file mode 100644 index 00000000..77e51081 --- /dev/null +++ b/orphaned/qa-0.9.4.rst @@ -0,0 +1,228 @@ +Taler 0.9.4 QA Plan +------------------- + +Wallet Platforms +^^^^^^^^^^^^^^^^ + +Platforms listed here are the officially supported platforms for this release. + +* Overview / Installation Page + + * https://taler.net/en/wallet.html + +* Android + + * Google Play: https://play.google.com/store/apps/details?id=net.taler.wallet + * F-Droid: https://f-droid.org/en/packages/net.taler.wallet.fdroid/ + * APK Download: TBD + +* Browser + + * Chrome: https://chromewebstore.google.com/detail/gnu-taler-wallet/millncjiddlpgdmkklmhfadpacifaonc + * Firefox: https://addons.mozilla.org/en-US/firefox/addon/taler-wallet/ + +* iOS + + +Running Deployments +^^^^^^^^^^^^^^^^^^^ + +These deployments are maintained by us and should work for the release: + +* Sandcastle-based: + + * demo.taler.net + + * test.taler.net + +* Regio-based: + + * regio-taler.fdold.eu + + +Wallet Flows +^^^^^^^^^^^^ + +* Bank-integrated withdrawal + + * webext: "Continue with Mobile Wallet" flow + +* Manual withdrawal + + * ``taler://withdraw-exchange`` flow + + * Currency conversion withdrawal + +* Peer push payments ("Send Money") + +* Peer pull payments ("Receive Money") + +* Deposit into bank account + + * Check that deposit arrived + +* Payment at merchant + + * on blog merchant + * on survey + * directly initiated via merchant SPA + * webext: "Pay with Mobile Wallet" flow + +* Pay templates + + * Payment TOTP codes + +* Exchange management + + * Reloading exchange keys + * Deleting an exchange + + +libeufin-bank Flows +^^^^^^^^^^^^^^^^^^^ + +* Admin functionality + + * Login + + * Credential change + + * Conversion settings + + * Bank account creation + + * Test transfers + +* Normal account functionality + + * Transfers + + * Transfer to the exchange should bounce + + * Withdrawals + + * (conversion-only): Test cash-in + + * (conversion-only): Test cash-out + + * Lower cash-out limit enforced + + * 2FA for withdrawals, cash-out + + +Merchant Backend SPA Flows +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* Instance creation + +* Simple bank account setup + +* Order creation + + * Pay order (with short wire transfer deadline) + + * Check that money from order arrive at the bank with the right subject + +* Extended bank account setup + + * Add Taler Bank Revenue API + + * Check bank transfer list (for wire transfer of previously paid+wired order) + + * Check order payment status goes to "final" automatically + +* TOTP Device Management + + * Add device + + * Edit device (set new secret, export new secret as QR code) + + * Delete device + +* Templates + + * Add template + + * Edit template + + * Add TOTP device to template + + * Edit TOTP device associated with template + + * Pay template + + * Check TOTP code matches + + * Remove TOTP device from template + + * Delete template + + + +Regio Deployment +^^^^^^^^^^^^^^^^ + +* Deployment Automation (deployment.git/regional-currency) + + * Test with Debian bookworm + + * Test with Ubuntu mantic + + * Check logs for errors + + * Test with telesign (SMS) + + * Set up EBICS integration + + * Check that ToS is configured + +* Deployment Functionality + + * All flows of the wallet should work (see ``Wallet Flows`` above) + + * All flows of libeufin-bank should work (see ``libeufin-bank Flows`` above) + + * Merchant backend should work (see ``Merchant Backend SPA Flows`` above) + + * Check logs + + +Android Merchant PoS +^^^^^^^^^^^^^^^^^^^^ + +* Test against demo.taler.net + + +Android Cashier App +^^^^^^^^^^^^^^^^^^^ + +* Test against demo.taler.net + + +CI +^^ + +* https://buildbot.taler.net/#/waterfall +* CI should pass + + +Debian Repository +^^^^^^^^^^^^^^^^^ + +* Debian + + * repo at https://deb.taler.net/apt/debian/ + * supported codename(s): bookworm + + +* Ubuntu: + + * repo at https://deb.taler.net/apt/ubuntu/ + * supported codename(s): mantic + + +GNU Release +^^^^^^^^^^^ + +* Release announcement +* FTP upload diff --git a/orphaned/taler-mcig.rst b/orphaned/taler-mcig.rst new file mode 100644 index 00000000..1950f4af --- /dev/null +++ b/orphaned/taler-mcig.rst @@ -0,0 +1,563 @@ +.. + This file is part of GNU TALER. + Copyright (C) 2021 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 Thien-Thi Nguyen + + +Merchant/Customer Interaction Guide +################################### + +The audience for the Mechant/Customer Interaction Guide is the merchant +who wishes to set up a "web shop" that works with the Taler payment system. + + +Introduction +============ + +.. include:: frags/taler-payment-cycle.rst + +This guide focuses on step 4, the interaction between the customer and the +merchant. In particular, we first review two basic interaction flows +(with and without shopping cart), then describe Taler features involved in the +interaction, the decisions you (the merchant) must make, and +how to configure the Taler merchant backend to best support those decisions. +Lastly, we present protocol *traces* for various fictitious interaction flows. + + +Two Basic Flows +=============== + +.. index:: shopping cart experience +.. index:: individual product selection / purchase experience +.. index:: inventory management +.. index:: repurchase detection / prevention + +There are two basic payment flows, the first involving a shopping cart, +and the second, without (individual product selection / purchase). +We distinguish these because for some purchases, a shopping cart is overkill. +In either case, Taler can integrate +with your *inventory management* system. +Additionally, Taler offers *repurchase detection / prevention*, +most suitable for digital goods. + +In the shopping cart experience, you first offer a product on the website. +The customer adds the product to their shopping cart, at which point you may +optionally *lock* the product in the inventory system for a certain period of +time. +The accumulated set of products in the shopping cart is the *order*. +This process repeats until the customer is ready to move to the +*checkout* phase. + +At checkout, you may optionally support different payment methods (and make +this choice available to the customer) for the order. +This guide assumes you and the customer agree to use the Taler payment system. + +At this point, you generate a *contract* and present it to the customer for +authorization. +The contract includes: + +- the total amount due; +- a short summary; +- a *fulfillment URI*; +- the *duration* of the offer (how long the customer has to authorize before timeout); +- (optional) an itemized product list, with: + + - (optional) some kind of identification for the selected product(s); + +- (optional) applicable taxes and fee limits; +- (optional) an order ID (if omitted, the backend will auto-generate one); +- (optional) information which details are *forgettable*; +- (optional) a *claim token* that the customer can use later; +- (optional) information on the *refund deadline*; +- (optional) information on the *auto-refund period* (how long does the wallet check for refunds without user prompting for it). + +If the customer does nothing (timeout / the contract expires), +the merchant backend automatically *unlocks* the product(s), +allowing other consumers to add more items of the limited stock +to their orders. + +On the other hand, if the customer authorizes payment, +the customer's wallet transfers payment coins to you, +previously locked products are removed from inventory, +and (if possible) the wallet redirects the customer +to the *fulfillment URI*. + +The individual product selection / purchase experience is like the shopping +cart experience with the following exceptions: +- there is no shopping cart -- the order is solely the selected product; +- Taler payment method is assumed; +- customer selection moves directly to checkout; +- *repurchase detection / prevention* can be useful (for digital products). + + +Taler Details +============= + +This section describes aspects of Taler involved +in the basic payment flows in more detail. +Each aspect also includes one or more backend API calls that +are demonstrated in the next section. + +**product locking** + Taler can integrate with your inventory system to set aside + a certain quantity of a product for some duration of time. + This is called *product locking*. + This is useful for physical goods, or for goods that have a limited supply, + such as airline tickets. + Even for digital goods, product locking may be useful to effect exclusivity. + + To lock a product, use: + :http:post:`[/instances/$INSTANCE]/private/products/$PRODUCT_ID/lock`, + specifying a ``duration`` and a ``quantity``. + + If the customer removes a product from the shopping cart, you can *unlock* + the product by using the same API call, specifying a ``quantity`` of 0 (zero). + (Products are also unlocked automatically on timeout / contract expiration.) + + Before you can lock products, you need to manage the inventory, creating + an entry for the product (assigning a $PRODUCT_ID) and configure the + available stock. This can be done using the + Taler merchant backoffice Web interface. + + .. note:: + + Once we have documentation for that web interface, we should link to it here. + +**taxes** + The default taxes for each product is part of the product ``price`` + maintained by the backend. + Taxes can be set when the product is added to the inventory, + prior to any customer purchase experience + (see :http:post:`[/instances/$INSTANCE]/private/products`, + :http:get:`[/instances/$INSTANCE]/private/products`, + and :http:get:`[/instances/$INSTANCE]/private/products/$PRODUCT_ID`) + or specified explicitly by the frontend when adding + products to an order that are not managed by the backend inventory + (see :http:post:`[/instances/$INSTANCE]/private/orders`). + +**fees** + The Taler protocol charges a *deposit fee* (see step 5, above), + which you may choose to pay or to pass on to the customer. + This can be configured to a maximum amount, per order. + + You can set ``default_max_deposit_fee`` in :http:post:`/management/instances`, + or override the default by setting ``max_fee`` when creating an order. + + There is also the *wire fee* (see step 6, above), + which you may choose to pay or to pass on to the customer. + + You can set ``default_max_wire_fee`` in :http:post:`/management/instances`, + and ``max_wire_fee`` in the contract. + If unspecified, the default value is zero (meaning you bear the entire fee). + + You can *amortize* the wire fee across a number of customers + by setting ``default_wire_fee_amortization`` in :http:post:`/management/instances`, + and ``wire_fee_amortization`` in the contract. + This is the number of customer transactions over which you expect to + amortize wire fees on average. + If unspecified, the default value is one. + + .. Note:: :http:post:`/management/instances` must be done at + instance-setup time (prior to any purchase). + +**forgettable customer details** + Although Taler allows the customer to remain anonymous, you may need to + collect customer details (e.g. for shipping). + Taler has support for forgetting such details, to comply with GDPR + (for example). + This can occur even in the face of refunds (see below). + + To forget a set of details, first the details that are to be forgotten + must be marked by including the names of the respective fields + in one or more special ``_forgettable`` field(s) in the contract. + + Then, you can use: + :http:patch:`[/instances/$INSTANCE]/private/orders/$ORDER_ID/forget` + to forget those details. + +**claim token** + The claim token is a sort of handle on the order and its payment. + It is useful when the order ID is easily guessable + (e.g. incrementing serial number), + to prevent one customer hijacking the order of another. + On the other hand, even if the order ID is not easily guessable, + if you don't care about order theft (e.g. infinite supply, digital goods) + and you wish to reduce the required processing (e.g. smaller QR code), + you can safely disable the claim token. + + By default, Taler creates a claim token for each order. + To disable this, you can specify ``create_token`` to be ``false`` + in :http:post:`[/instances/$INSTANCE]/private/orders`. + +**refund deadline** + The refund deadline specifies the time after which you will prohibit + refunds. + Refunds may be full or partial. + Refunds do not require customer details. + You can configure the deadline to expire immediately to effect + an "all sales are final" policy. + + To set the deadline, specify ``refund_delay`` + in :http:post:`[/instances/$INSTANCE]/private/orders`. + To disable refunds altogether, omit this field. + +**auto-refund period** + The Taler protocol can automatically offer refunds to the customer's + wallet without their explicit prompting during the auto-refund period. + + This is useful in the case where the purchase cannot be fulfilled + (e.g. jammed vending machine), but there is no way to notify the + customer about a refund. + + If specified, after contract authorization, the customer's wallet will + repeatedly check for either fulfillment or refund, up to the end of + the auto-refund period. + (If neither occur within that period, the customer should complain + to you for breach of contract.) + + To set the auto-refund period, specify ``auto_refund`` + in :http:post:`[/instances/$INSTANCE]/private/orders`. + +**repurchase detection / prevention** + Taler can detect a repurchase attempt and prevent it from going through. + This feature allows customers to purchase a digital good only once, + but to later access the same digital good repeatedly (e.g. reload + in browser, after network trouble, etc.) without having to pay again. + + This feature is automatic in the protocol; + you do not need to do anything to enable it. + + .. note:: + For repurchase detection / prevention to work reliably, + you must use the same fulfillment URI for the same product + and likewise different fulfillment URIs for different products. + +**fulfillment URI** + This may be the actual product (digital goods), + or a tracking URL (physical goods). + If you issue a claim token with the contract, the customer can + access the fulfillment URI from a different device than the + one where the wallet is installed. + + The fulfillment URI is normally included in the contract. + You specify it in :http:post:`[/instances/$INSTANCE]/private/orders`. + + If the fulfillment URI contains the literal string ``${ORDER_ID}`` + (including curly braces), that will be replaced by the order ID when + POSTing to the merchant. (FIXME: What does "POSTing to the merchant" mean?) + This is useful when the backend auto-generates the order ID. + + +Sample Interaction Traces +========================= + +In the following descriptions, ``C`` stands for *customer*, ``W`` stands for +*customer's wallet*, ``M`` stands for *merchant* (you), and ``E`` stands for +*exchange*. +Unless otherwise noted, all API calls are directed toward the Taler backend. + +Also, all the traces share the initial pre-sales configuration step. + + +Pre-Sales Configuration +----------------------- + +In the pre-sales configuration step, you set up the *default instance*, +and add products to the inventory. + +NOTE: not sure we want to ultimately document this HERE. Most merchants +should do _this_ part via the Merchant Web interface that Sebastian is +building right now, and for that we want a separate guide that explains +the API (as you do here), and the Web interface. In this document, +we should focus on how the merchant integrates the (Web)front-end with the +backend, not how the backend itself is configured. +(This also applies to the other instance setup parts you described +above => refer to other guide, but of course specify how we can +override defaults from instance setup per-order.) + + +M: :http:post:`/management/instances` + +.. code-block:: javascript + + // InstanceConfigurationMessage + { + "accounts": [{"payto_uri":"payto://iban/CH9300762011623852957"}], + "id": "default", + "name": "Pretty Pianos", + "auth": + // InstanceAuthConfigurationMessage + { + "method": "external", + "token": "secret-token:eighty-eight-keys" + }, + "default_max_wire_fee": "KUDOS:5.0", + "default_wire_fee_amortization": 1, + "default_max_deposit_fee": "KUDOS:10.0", + "default_wire_transfer_delay": "2 days", + "default_pay_delay": "5 hours" + } + // (backend returns 204 No content) + +The fictitious store, Pretty Pianos, has only two products: +- pianos (physical good); +- *Beethoven Sonatas* (sheet music PDF files, digital good). + +M: POST ``/instances/default/private/products`` + +.. code-block:: javascript + + // ProductAddDetail + { + "product_id": "p001", + "description": "piano", + "unit": "unit", + "image": "data:image/png;base64,AAA=", + "price": "KUDOS:20000.0", + "taxes": [], + "total_stock": 3, + "next_restock": "2021-04-22", + "_forgettable": ["image"] + } + // (backend returns 204 No content) + +Note that the ``image`` field is mentioned by name in the ``_forgettable`` +field's list value. +This means the ``image`` value is *marked as forgettable*. +This will come into play later (see below). + +M: POST ``/instances/default/private/products`` + +.. code-block:: javascript + + // ProductAddDetail + { + "product_id": "f001", + "description": "Beethoven Sonatas", + "unit": "file", + "price": "KUDOS:9.87", + "taxes": [], + "total_stock": -1 + } + // (backend returns 204 No content) + +Note that there is no ``next_restock`` field in this ``ProductAddDetail`` +object. +This is because the ``total_stock`` field has value ``-1`` (meaning "infinite") +since the product is a PDF file. + + +Scenario 1: Simple File Purchase +-------------------------------- + +The first scenario is a simple file purchase, without shopping cart, +similar to the `GNU Essay demo <https://shop.demo.taler.net/en/>`_ experience. + +.. We hardcode "en/" for now because support for other + languages is not yet available (at time of writing). + (FIXME: Drop "en/" when other languages are supported.) + +Because there are infinite supplies of product ``f001``, +there is really no need for inventory management. +However, you choose to anyway generate a separate order ID +in the backend for accounting purposes. +Also, since the product is an easily reproduced digital good, +you decline to offer the customer the ability to select a "quantity" +other than 1 (one), and decide that "all sales are final" +(no refund possible). +On the other hand, you wish to enable repurchase detection / +prevention feature, so that once customers pay for the PDF file, +they need never pay again for it. + +When the customer clicks on the product's "buy" button, +you first POST to ``/private/orders`` to create an order: + +M: POST ``/instances/default/private/orders`` + +.. code-block:: javascript + + // PostOrderRequest + { + "order": + // Order (MinimalOrderDetail) + { + "amount": "KUDOS:9.87", + "summary": "Beethoven Sonatas", + "fulfillment_URI": "https://example.com/f001?${ORDER_ID}" + }, + "create_token": true + } + +Notes: + +- There is no ``refund_delay`` field (no refunds possible). +- We show the ``create_token`` field with value ``true`` even though that is the default (for illustrative purposes). +- The ``order`` value is actually a ``MinimalOrderDetail`` object. +- The ``fulfillment_URI`` value includes the product ID and the literal string ``${ORDER_ID}``, to be replaced by the backend-generated order ID. + +The backend returns ``200 OK`` with the body: + +.. code-block:: javascript + + // PostOrderResponse + { + "order_id": "G93420934823", + "token": "TEUFHEFBQALK" + } + +Notes: +- The backend-generated order ID is ``G93420934823``. +- The claim token is ``TEUFHEFBQALK``. + +(FIXME: Replace w/ more realistic examples?) + +Now that there is an order in the system, the wallet *claims* the order. + +W: POST ``/orders/G93420934823/claim`` + +.. code-block:: javascript + + // ClaimRequest + { + "nonce": "lksjdflaksjfdlaksjf", + "token": "TEUFHEFBQALK" + } + +Notes: + +- The ``nonce`` value is a randomly-generated string. +- The POST endpoint includes the order ID ``G93420934823``. +- The ``token`` value is the claim token ``TEUFHEFBQALK`` received in the ``PostOrderResponse``. + +The backend returns ``200 OK`` with body: + +.. code-block:: javascript + + // ContractTerms + { + "summary": "one copy of Beethoven Sonatas", + "order_id": "G93420934823", + "amount": "KUDOS:9.87000000", + "fulfillment_url": "https://example.com/f001?G93420934823", + "max_fee": "KUDOS:0.01500000", + "max_wire_fee": "KUDOS:0.01500000", + "wire_fee_amortization": 1, + "products": [ + // Product + { + "product_id": "f001", + "description": "Beethoven Sonatas" + } + ], + "timestamp": { "t_ms": 1616537665000 }, + "refund_deadline": { "t_ms": 1616537665000 }, + "pay_deadline": { "t_ms": 1616537725000 }, + "wire_transfer_deadline": { "t_ms": 1616537785000 }, + "merchant_pub": FIXME, + "merchant_base_url": "https://example.com/", + "merchant": + // Merchant + { + }, + "h_wire": FIXME, + "wire_method": FIXME, + "auditors": [ + // Auditor + ], + "exchanges": [ + // Exchange + ], + "nonce": "lksjdflaksjfdlaksjf" + } + +Notes: + +- The backend determined both fees to be 0.015 KUDOS. + Because the amortization is 1 (one), both fees (processing and wire + transfer) are included in full. + Thus, the total due by the customer is 9.87 + 0.015 + 0.015 = 9.900 KUDOS. +- The ``order_id`` value is the one given in the ``PostOrderResponse``. +- The ``timestamp`` value represents 2021-03-23 22:14:25 UTC + in milliseconds after the `epoch <https://en.wikipedia.org/wiki/Unix_epoch>`__. +- The ``refund_deadline`` value is the same as the ``timestamp`` value + (no refunds possible). +- The ``pay_deadline`` value is one minute after the ``timestamp`` value. +- The ``wire_transfer_deadline`` value is two minutes after + the ``timestamp`` value. +- The ``products`` value is a list of one element (one ``Product`` object), + which omits the ``price`` field since that is included in the + ``ContractTerms.amount`` value. Also, its ``quantity`` defaults to 1 (one). +- The ``nonce`` value is the same one specified by the wallet. + +At this point, the wallet displays the contract terms (or a subset of them) +to the customer, who now has the option to accept the contract or reject it +(either explicitly by pressing a "cancel" button, or implicitly by waiting +for the offer to time out). + +The customer accepts the contract: + +W: POST ``/orders/G93420934823/pay`` + +.. code-block:: javascript + + // PayRequest + { + "coins": [ + // CoinPaySig + { + "coin_sig": ..., + "coin_pub": ..., + "ub_sig": ..., + "h_denom": ..., + "contribution": "KUDOS:8.0", + "exchange_url": ... + }, + { + "coin_sig": ..., + "coin_pub": ..., + "ub_sig": ..., + "h_denom": ..., + "contribution": "KUDOS:2.0", + "exchange_url": ... + } + ] + } + +Notes: + +- There is no session ID in the ``PayRequest`` object. +- The total of the contribution is 8.0 + 2.0 = 10.0 KUDOS, + which is enough to cover the purchase price (9.900 KUDOS + from 9.87 + 0.015 + 0.015). + +The backend returns ``200 OK`` with body: + +.. code-block:: javascript + + // PaymentResponse + { + "sig": "..." // EddsaSignature + } + +FIXME: At this point, does the wallet need to query (status)? +Also, does the frontend need to do anything else? + +The wallet then redirects to the fulfillment URI, which displays +(or makes available for download) the PDF file "Beethoven Sonatas". + + + + +TODO/FIXME: Add more scenarios (including JSON). diff --git a/orphaned/taler-nfc-guide.rst b/orphaned/taler-nfc-guide.rst new file mode 100644 index 00000000..d025d347 --- /dev/null +++ b/orphaned/taler-nfc-guide.rst @@ -0,0 +1,285 @@ +GNU Taler NFC Guide +################### + +This guide explains how NFC (near-field communication) is +used in the GNU Taler payment system. + +Introduction +============ + +NFC is currently used for two different purposes: + +1. Operations in the wallet (payment, withdrawal, ...) can be triggered by a + merchant PoS (Point-of-Sale) terminal or Taler-capable ATM. +2. When either the wallet or the merchant do not have Internet connectivity, + the protocol messages to the exchange or merchant backend service can be + tunneled via NFC through the party that has Internet connectivity. + + +Background: Payment Processing with GNU Taler +============================================= + +The following steps show a simple payment process with GNU Taler. Examples are +written in `Bash <https://www.gnu.org/software/bash/>`_ syntax, +using `curl <https://curl.haxx.se/docs/manpage.html>`_ to make HTTP(S) requests. +They make use of the :http:post:`[/instances/$INSTANCE]/private/orders` +and :http:get:`[/instances/$INSTANCE]/private/orders` endpoints. + +1. The merchant creates an *order*, which contains the details of the payment + and the product/service that the customer will receive. + An order is identified by an alphanumeric *order ID*. + + The *fulfillment URL* is an URL that the wallet will redirect the customer + to once the payment is complete. For digital products, this is typically an + ``https(s)://`` URL that renders the purchased content. For physical + products and in-store purchases, a ``taler://fulfillment-success/<message>`` + URL should be specified instead. The wallet will display the URL-encoded + UTF-8 text ``<message>`` when the payment has succeeded. + + .. hint:: + + When an ``http(s)://`` URL is used as the fulfillment URL in an in-store / NFC payment, + the user might not be able to view the page, as request tunneling only works for requests + made by the wallet to the merchant backend / exchange. + + In these situations, wallets should display to the user that a page to view the purchase + can be opened, and give a warning if it is detected that the devices does not have Internet + connectivity. + + The following POST ``/private/orders`` request to the merchant backend creates a + simple order: + + .. code-block:: console + + $ backend_base_url=https://backend.demo.taler.net/ + $ auth_header='Authorization: ApiKey sandbox' + $ order_req=$(cat <<EOF + { + "order": { + "summary": "one ice cream", + "amount": "KUDOS:1.5", + "fulfillment_url": + "taler://fulfillment-success/Enjoy+your+ice+cream!" + } + } + EOF + ) + $ 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 + GET ``/private/orders/$ORDER_ID``: + + .. code-block:: console + + $ backend_base_url=https://backend.demo.taler.net/ + $ auth_header='Authorization: ApiKey sandbox' + $ curl -XGET -H"$auth_header" \ + "$backend_base_url/private/orders/2019.255-02YDHMXCBQP6J" + # Response: + { + "taler_pay_uri": "taler://pay/backend.demo.taler.net/-/-/2019.255-02YDHMXCBQP6J", + "paid": false, + # ... (some fields omitted) + } + + As expected, the order is not paid. To actually proceed with the payment, the value of ``taler_pay_uri`` + must be processed by the customer's wallet. There are multiple ways for the wallet to obtain the ``taler://pay/`` URI + + * in a QR code + * in the ``Taler:`` HTTP header of a Web site + * by manually entering it in the command-line wallet + * **via NFC** (explained in this guide) + + The details of ``taler://`` URIs are specified in `LSD 0006 <https://lsd.gnunet.org/lsd0006/>`_. + +3. The wallet processes the ``taler://pay/`` URI. In this example, we use the + command-line wallet: + + .. code-block:: console + + # Withdraw some toy money (KUDOS) from the demo bank + $ taler-wallet-cli test-withdraw \ + -e https://exchange.demo.taler.net/ \ + -b https://bank.demo.taler.net/ \ + -a KUDOS:10 + # Pay for the order from the merchant. + $ taler-wallet-cli pay-uri 'taler://pay/backend.demo.taler.net/-/-/2019.255-02YDHMXCBQP6J' + # [... User is asked to confirm the payment ...] + + .. hint:: + + The command-line wallet is typically used by developers and not by end-users. + See the :ref:`wallet manual <command-line-wallet>` for installation instructions. + + +4. The merchant checks the payment status again: + + .. code-block:: console + + $ backend_base_url=https://backend.demo.taler.net/ + $ auth_header='Authorization: ApiKey sandbox' + $ curl -XGET -H"$auth_header" \ + "$backend_base_url/private/orders/2019.255-02YDHMXCBQP6J" + # Response: + { + "paid": true, + # ... (some fields omitted) + } + + .. note:: + + When paying for digital products displayed on a Web site identified by the + fulfillment URL, the merchant only needs to check the payment status + 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 ``timeout_ms`` parameter + of GET ``/private/orders/$ORDER_ID`` + should be used. + + +Taler NFC Basics +================ + +The NFC communication in GNU Taler follows the ISO-DEP (`ISO 14443-4 +<https://www.iso.org/standard/73599.html>`_) standard. The wallet always acts +as a tag (or more precisely, emulated card), while the merchant PoS terminal +and bank terminal act as a reader. + +The basic communication unit is the application protocol data unit (`APDU +<https://en.wikipedia.org/wiki/Smart_card_application_protocol_data_unit>`_), with the structure +and commands defined in `ISO 7816 <https://cardwerk.com/iso-7816-smart-card-standard>`_. + +The GNU Taler wallet uses the AID (application identifier) ``F00054414c4552``. +The ``F`` prefix indicates the proprietary/unregistered namespace of AIDs, and +the rest of the identifier is the hex-encoded ASCII-string ``TALER`` (with one +0-byte left padding). + +During the time that the wallet is paired with a reader, there is state +associated with the communication channel. Most importantly, the first message +sent by the reader to the wallet must be a ``SELECT FILE (=0xA4)`` that selects +the GNU Taler AID. Messages that are sent before the correct ``SELECT FILE`` +message results in implementation-defined behavior, such as the tag disconnecting, +ignoring the message or an app other than the wallet receiving the message. + +The reader sends commands to the wallet with the ``PUT DATA (=0xDA)`` +instruction, using the instruction parameters ``0x0100``, denoting a +proprietary instruction. + +The command data of the ``PUT DATA`` APDU is prefixed by a one-byte Taler +instruction ID (TID). Currently, the following TIDs are used: + +.. list-table:: + :widths: 5 50 + :header-rows: 1 + + * - TID (reader to wallet) + - Description + * - ``0x01`` + - Dereference the UTF-8 encoded ``taler://`` URI in the remainder of the command data. + * - ``0x02`` + - Accept the UTF-8 encoded JSON object in the remainder of the command data as a request tunneling response. + + +The ``GET DATA (=0xCA)`` instruction (again with the instruction parameters +``0x0100`` is used to request a command from the wallet. The APDU with this +instruction must be sent with a ``0x0000`` trailer to indicate that up to 65536 +bytes of data are expected in the response from the wallet. Note that the +wallet itself cannot initiate communication, and thus the reader must "poll" +the wallet for commands. + +The response to the ``GET DATA`` instruction has a Taler instruction ID in the +first byte. The rest of the +body is interpreted depending on the TID. + +.. list-table:: + :widths: 15 50 + :header-rows: 1 + + * - TID + (wallet to reader) + - Description + * - ``0x03`` + - Accept the UTF-8 encoded JSON object in the remainder of the command data as a request tunneling request. + + +Sending taler:// URIs to the Wallet via NFC +=========================================== + +To make the wallet process a ``taler://`` URI via NFC, the merchant PoS +terminal sends a ``SELECT FILE`` command with the GNU Taler AID, and a ``PUT +DATA`` command with TID ``0x01`` and the URI in the rest +of the command data. + +Here is an example protocol trace from an interaction which caused the wallet +to dereference the ``taler://pay`` URI from the example above: + +.. code-block:: none + + # SELECT FILE + m->w 00A4040007F00054414c4552 + # success response with no data + m<-w 9000 + + # PUT DATA (TID=0x01) + m->w 00DA01007c0174616c65723a2f2f7061792f6261636b656e642e64656d6f2e74 + 616c65722e6e65742f2d2f2d2f323031392e3235352d30325944484d58434251 + 50364a + # success response with no data + m<-w 9000 + +(Note that this process works analogously for communication with a bank/ATM +terminal.) + + +Request tunneling +================= + +Request tunneling allows tunneling a (very) restricted subset of HTTP through +NFC. In particular, only JSON request and response bodies are allowed. + +It is currently assumed that the requests and responses fit into one APDU frame. +For devices with more limited maximum APDU sizes, additional TIDs for segmented +tunnel requests/responses may be defined in the future. + +A request for tunneling is initiated with TID ``0x03`` and responded to with +TID ``0x02`` (see tables above). A tunneling request is identified by a +numeric ID, which must be unique during one pairing between reader and tag. + +The request tunneling request/response JSON messages have the following schema: + +.. code-block:: tsref + + interface TalerRequestTunnelRequest { + // Identifier for the request + id: number; + + // Request URL + url: string; + + // HTTP method to use + method: "post" | "get"; + + // Request headers + headers?: { [name: string]: string }; + + // JSON body for the request, only applicable to POST requests + body?: object; + } + + interface TalerRequestTunnelResponse { + // Identifier for the request + id: number; + + // Response HTTP status code, + // "0" if there was no response. + status: number; + + // JSON body of the response, or undefined + // if the response wasn't JSON. + // May contain error details if 'status==0' + body?: object; + } |