summaryrefslogtreecommitdiff
path: root/taler-mcig.rst
diff options
context:
space:
mode:
Diffstat (limited to 'taler-mcig.rst')
-rw-r--r--taler-mcig.rst563
1 files changed, 0 insertions, 563 deletions
diff --git a/taler-mcig.rst b/taler-mcig.rst
deleted file mode 100644
index c69d838c..00000000
--- a/taler-mcig.rst
+++ /dev/null
@@ -1,563 +0,0 @@
-..
- 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
- {
- "payto_uris": ["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: :http: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: :http: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: :http: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: :http: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: :http: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).