summaryrefslogtreecommitdiff
path: root/doc/merchant-api.content.texi
diff options
context:
space:
mode:
Diffstat (limited to 'doc/merchant-api.content.texi')
-rw-r--r--doc/merchant-api.content.texi1068
1 files changed, 0 insertions, 1068 deletions
diff --git a/doc/merchant-api.content.texi b/doc/merchant-api.content.texi
deleted file mode 100644
index 4ab09bda..00000000
--- a/doc/merchant-api.content.texi
+++ /dev/null
@@ -1,1068 +0,0 @@
-@c *****************************************
-@c This file is supposed to be included from
-@c the language-specific tutorial.
-@c *****************************************
-
-@c Define a new index for options.
-@defcodeindex op
-@c Combine everything into one index (arbitrarily chosen to be the
-@c concept index).
-@syncodeindex op cp
-@c %**end of header
-
-@copying
-This document is a tutorial for the GNU Taler Merchant API (version @value{VERSION}, @value{UPDATED})
-
-Copyright @copyright{} 2018 Taler Systems SA
-
-@quotation
-Permission is granted to copy, distribute and/or modify this document
-under the terms of the GNU Free Documentation License, Version 1.3 or
-any later version published by the Free Software Foundation; with no
-Invariant Sections, with no Front-Cover Texts, and with no Back-Cover
-Texts. A copy of the license is included in the section entitled
-``GNU Free Documentation License''.
-@end quotation
-@end copying
-@c If your tutorial is published on paper by the FSF, it should include
-@c The standard FSF Front-Cover and Back-Cover Texts, as given in
-@c maintain.texi.
-@c
-@c Titlepage
-@c
-@titlepage
-@title The GNU Taler Merchant API tutorial
-@subtitle Version @value{VERSION}
-@subtitle @value{UPDATED}
-@author Christian Grothoff (@email{christian@@grothoff.org})
-@author Marcello Stanisci (@email{marcello.stanisci@@inria.fr})
-@author Florian Dold (@email{florian.dold@@inria.fr})
-@page
-@vskip 0pt plus 1filll
-@insertcopying
-@end titlepage
-
-@summarycontents
-@contents
-
-@ifnottex
-@node Top
-@top The GNU Taler Merchant API Tutorial (Version for @value{LANGNAME})
-@insertcopying
-@end ifnottex
-
-
-@menu
-* Introduction:: What this tutorial is about
-* Accepting a Simple Payment:: How to accept simple payments
-* Giving Refunds:: How to give refunds to customers
-* Giving Customers Tips:: How to reward customers with tips
-* Advanced topics:: Detailed solutions to specific issues
-
-
-Appendices
-
-* GNU-LGPL:: The GNU Lesser General Public License says how you
- can use the code of libtalermerchant.so in your own projects.
-* GNU-FDL:: The GNU Free Documentation License says how you
- can copy and share the documentation of GNU Taler.
-
-Indices
-
-* Concept Index:: Index of concepts and programs.
-@end menu
-
-
-@node Introduction
-@chapter Introduction
-
-@section 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).
-
-
-@section About this tutorial
-
-This tutorial addresses how to process payments using the GNU Taler merchant
-Backend. This chapter explains some basic concepts. In the second chapter, you
-will learn how to do basic payments.
-
-@clear GOT_LANG
-@ifset LANG_PYTHON
-@set GOT_LANG 1
-This version of the tutorial has examples for Python3.
-It uses the requests library for HTTP requests.
-@end ifset
-@ifset LANG_CURL
-@set GOT_LANG 1
-This version of the tutorial has examples for the
-command line with cURL.
-@end ifset
-@ifset LANG_PHP
-This version of the tutorial has examples for PHP,
-using libcurl.
-@end ifset
-@c
-Versions for other languages/environments are available as well.
-
-@cindex examples
-@cindex git
-If you want to look at some simple, running examples, check out these:
-@itemize
-@item
-The @url{https://git.taler.net/blog.git/tree/talerblog/blog/blog.py, essay merchant} that
-sells single chapters of a book.
-@item
-The @url{https://git.taler.net/donations.git/tree/talerdonations/donations/donations.py, donation page} that
-accepts donations for software projects and gives donation receipts.
-@item
-The @url{https://git.taler.net/survey.git/tree/talersurvey/survey/survey.py,survey} that
-gives users who answer a question a small reward.
-@end itemize
-
-@section Architecture overview
-
-The Taler software stack for a merchant consists of the following
-main components:
-
-@itemize
-@cindex frontend
-@item 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.
-@cindex backend
-@item 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.
-@end itemize
-
-The following image illustrates the various interactions of these
-key components:
-
-@image{arch-api, 3in}
-
-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 also exposed to the
-customer's browser directly. In the HTTP API, all public endpoints are prefixed with @code{/public/}.
-
-@section Public Sandbox Backend and Authentication
-@cindex sandbox
-@cindex authorization
-
-How the frontend authenticates to the Taler backend depends on the configuration. @xref{Top,,, manual, Taler Merchant Operating Manual}.
-
-The public sandbox backend @url{https://backend.demo.taler.net/} uses an API key
-in the @code{Authorization} header. The value of this header must be
-@code{ApiKey sandbox} for the public sandbox backend.
-
-@clear GOT_LANG
-@ifset LANG_CURL
-@set GOT_LANG 1
-@example
-curl -i 'https://backend.demo.taler.net/' \
- --header "Authorization: ApiKey sandbox"
-# HTTP/1.1 200 OK
-# [...]
-#
-# Hello, I'm a merchant's Taler backend. This HTTP server is not for humans.
-@end example
-@end ifset
-@ifset LANG_PYTHON
-@set GOT_LANG 1
-@example
-@verbatim
->>> import requests
->>> requests.get("https://backend.demo.taler.net",
-... headers={"Authorization": "ApiKey sandbox"})
-<Response [200]>
-@end verbatim
-@end example
-@end ifset
-@ifset LANG_PHP
-@set GOT_LANG 1
-@example
-@verbatim
-php > $c = curl_init("https://backend.demo.taler.net/");
-php > $options = array(CURLOPT_RETURNTRANSFER => true,
-php ( CURLOPT_CUSTOMREQUEST => "GET",
-php ( CURLOPT_HTTPHEADER => array("Authorization: ApiKey sandbox"));
-php > curl_setopt_array ($c, $options);
-php > $r = curl_exec ($c);
-php > echo curl_getinfo ($c, CURLINFO_HTTP_CODE);
-200
-php > echo $r;
-Hello, I'm a merchant's Taler backend. This HTTP server is not for humans.
-@end verbatim
-@end example
-@end ifset
-@ifclear GOT_LANG
-@example
-(example not available for this language)
-@end example
-@end ifclear
-
-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 @url{https://backend.demo.taler.net/} uses @code{KUDOS} as
-an imaginary currency. Coins denominated in @code{KUDOS} can be withdrawn
-from @url{https://bank.demo.taler.net/}.
-
-@section Merchant Instances
-@cindex instance
-
-The same Taler merchant backend server can be used by multiple separate
-merchants that are separate business entities. Each of these separate business
-entities is called a @emph{merchant instance}, and is identified by an
-alphanumeric @emph{instance id}. If the instance is omitted, the instance id
-@code{default} is assumed.
-
-The following merchant instances are configured on @url{https://backend.demo.taler.net/}:
-@itemize
-@item @code{GNUnet} (The GNUnet project)
-@item @code{FSF} (The Free Software Foundation)
-@item @code{Tor} (The Tor Project)
-@item @code{default} (Kudos Inc.)
-@end itemize
-
-Note that these are fictional merchants used for our demonstrators and
-not affiliated with or officially approved by the respective projects.
-
-
-@node Accepting a Simple Payment
-@chapter Accepting a Simple Payment
-
-@section Creating an Order for a Payment
-@cindex order
-
-Payments in Taler revolve around an @emph{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 @code{/order} API endpoint. At least the
-following fields must be given:
-
-@itemize
-@item @var{amount}: The amount to be paid, as a string in the format
-@code{CURRENCY:DECIMAL_VALUE}, for example @code{EUR:10} for 10 Euros or
-@code{KUDOS:1.5} for 1.5 KUDOS.
-
-@item @var{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.
-
-@item @var{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 @code{order_id} as a query parameter, as well as the @code{session_sig} for
-session-bound payments (discussed later).
-@end itemize
-
-Orders can have many more fields, see @ref{The Taler Order Format}.
-
-After successfully @code{POST}ing to @code{/order}, an @code{order_id} will be
-returned. Together with the merchant @code{instance}, the order id uniquely
-identifies the order within a merchant backend.
-
-@clear GOT_LANG
-@ifset LANG_CURL
-@set GOT_LANG 1
-@example
-@verbatim
-ORDER='
-{"order": {
- "amount": "KUDOS:10",
- "summary": "Donation",
- "fulfillment_url": "https://example.com/thanks.html"}}
-'
-
-curl -i -X POST 'https://backend.demo.taler.net/order' \
- --header "Authorization: ApiKey sandbox" -d "$ORDER"
-# HTTP/1.1 200 OK
-# [...]
-#
-# {
-# "order_id": "2018.058.21.46.06-024C85K189H8P"
-# }
-@end verbatim
-@end example
-@end ifset
-@ifset LANG_PYTHON
-@set GOT_LANG 1
-@example
-@verbatim
->>> import requests
->>> order = dict(order=dict(amount="KUDOS:10",
-... summary="Donation",
-... fulfillment_url="https://example.com/thanks.html"))
->>> order_resp = requests.post("https://backend.demo.taler.net/order", json=order,
-... headers={"Authorization": "ApiKey sandbox"})
-<Response [200]>
-@end verbatim
-@end example
-@end ifset
-@ifset LANG_PHP
-@set GOT_LANG 1
-@example
-@verbatim
-php > $c = curl_init("https://backend.demo.taler.net/order");
-php > $json = array("order"=>
-php ( array("amount"=>"KUDOS:1",
-php ( "fulfillent_url"=>"https://example.com/thanks.html",
-php ( "summary"=>"nice product"));
-php > $options = array(CURLOPT_RETURNTRANSFER=>true,
-php ( CURLOPT_CUSTOMREQUEST=>"POST",
-php ( CURLOPT_POSTFIELDS=>json_encode($json),
-php ( CURLOPT_HTTPHEADER=>array("Authorization: ApiKey sandbox"));
-php > curl_setopt_array($c, $options);
-php > $r = curl_exec($c);
-php > echo curl_getinfo($c, CURLINFO_HTTP_CODE);
-200
-php > echo $r;
-{
- "order_id": "2018.072.12.48.51-014DKDKBMHPDP"
-}
-@end verbatim
-@end example
-@end ifset
-@ifclear GOT_LANG
-@example
-(example not available for this language)
-@end example
-@end ifclear
-
-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 @emph{contract
-terms}.
-@cindex contract
-@cindex terms
-
-@section Checking Payment Status and Prompting for Payment
-The status of a payment can be checked with the @code{/check-payment} endpoint. If the payment
-is yet to be completed by the customer, @code{/check-payment} will give the frontend a URL (the @var{payment_redirect_url})
-that will trigger the customer's wallet to execute the payment.
-
-Note that the only way to obtain the @var{payment_redirect_url} is to check the status of the payment,
-even if you know that the user did not pay yet.
-
-@clear GOT_LANG
-@ifset LANG_CURL
-@set GOT_LANG 1
-@example
-@verbatim
-ORDER_ID="2018.058.21.46.06-024C85K189H8P"
-curl -i "https://backend.demo.taler.net/check-payment?order_id=$ORDER_ID" \
- --header "Authorization: ApiKey sandbox"
-# HTTP/1.1 200 OK
-# [...]
-#
-# {
-# "payment_redirect_url":
-# "https://backend.demo.taler.net/public/trigger-pay?[...]",
-# "paid": false
-# }
-@end verbatim
-@end example
-@end ifset
-@ifset LANG_PYTHON
-@set GOT_LANG 1
-@example
-@verbatim
->>> import requests
->>> r = requests.get("https://backend.demo.taler.net/check-payment",
-... params=dict(order_id=order_resp.json()["order_id"]),
-... headers={"Authorization": "ApiKey sandbox"})
->>> print(r.json())
-@end verbatim
-@end example
-@end ifset
-@ifset LANG_PHP
-@set GOT_LANG 1
-@example
-@verbatim
-php > $ORDER_ID = "2018.072.12.48.51-014DKDKBMHPDP";
-php > curl_init ("https://backend.demo.taler.net/check-payment?order_id=$ORDER_ID");
-php > $options = array(CURLOPT_RETURNTRANSFER=>true,
-php ( CURLOPT_CUSTOMREQUEST=>"GET",
-php ( CURLOPT_HTTPHEADER=>array(
-php ( "Authorization: ApiKey sandbox"));
-php > curl_setopt_array($c, $options);
-php > $r = curl_exec($c);
-php > echo $r;
-@end verbatim
-@end example
-@end ifset
-@ifclear GOT_LANG
-@example
-(example not available for this language)
-@end example
-@end ifclear
-
-If the @var{paid} field in the response is @code{true}, the other
-fields in the response will be different. Once the payment was
-completed by the user, the response will contain the following fields:
-
-@itemize
-@item @var{paid}: Set to @var{true}.
-@item @var{contract_terms}: The full contract terms of the order.
-@item @var{refunded}: @code{true} if a (possibly partial) refund was granted for this purchase.
-@item @var{refunded_amount}: Amount that was refunded
-@item @var{last_session_id}: Last session ID used by the customer's wallet. @xref{Session-Bound Payments}.
-@end itemize
-
-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.
-
-
-@node Giving Refunds
-@chapter Giving Refunds
-@cindex 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 @code{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 @code{POST}ing to the @code{/refund} endpoint.
-
-The refund request JSON object has the following fields:
-@itemize
-@item @var{order_id}: Identifies for which order a customer should be refunded.
-@c NOTE: the merchant does NOT default to instance "default".
-@item @var{instance}: Merchant instance to use.
-@item @var{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, @emph{not} an increase in the refund.
-@item @var{reason}: Human-readable justification for the refund. The reason is only used by the Back Office and is not exposed to the customer.
-@end itemize
-
-If the request is successful (indicated by HTTP status code 200), the response
-includes a @code{refund_redirect_url}. 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:
-@clear GOT_LANG
-@ifset LANG_CURL
-@set GOT_LANG 1
-@example
-@verbatim
-REFUND_REQ='
-{"order_id": "2018.058.21.46.06-024C85K189H8P",
- "refund": "KUDOS:10",
- "instance": "default",
- "reason": "Customer did not like the product"}
-'
-
-curl -i -X POST 'https://backend.demo.taler.net/refund' \
- --header "Authorization: ApiKey sandbox" -d "$REFUND_REQ"
-# HTTP/1.1 200 OK
-# [...]
-#
-# {
-# [...]
-# "refund_redirect_url": "[...]"
-# }
-@end verbatim
-@end example
-@end ifset
-@ifset LANG_PYTHON
-@set GOT_LANG 1
-@example
-@verbatim
->>> import requests
->>> refund_req = dict(order_id="2018.058.21.46.06-024C85K189H8P",
-... refund="KUDOS:10",
-... instance="default",
-... reason="Customer did not like the product")
->>> requests.post("https://backend.demo.taler.net/refund", json=refund_req,
-... headers={"Authorization": "ApiKey sandbox"})
-<Response [200]>
-@end verbatim
-@end example
-@end ifset
-
-@ifset LANG_PHP
-@set GOT_LANG 1
-@example
-@verbatim
-php > $REFUND_REQ = array("order_id"=>$ORDER_ID,
-php ( "refund"=>"KUDOS:0.5",
-php ( "instance"=>"default",
-php ( "reason"=>"Customer did not like product");
-php > $options = array(CURLOPT_RETURNTRANSFER=>true,
-php ( CURLOPT_CUSTOMREQUEST=>"POST",
-php ( CURLOPT_HTTPHEADER=>array(
-php ( "Authorization: ApiKey sandbox"),
-php ( CURLOPT_POSTFIELDS=>json_encode($REFUND_REQ));
-php > $c = curl_init("https://backend.demo.taler.net/refund");
-php > curl_setopt_array($c, $options);
-php > $r = curl_exec($c);
-php > echo $r;
-php > echo curl_getinfo($c, CURLINFO_HTTP_CODE);
-200 # Make sure you paid first!
-@end verbatim
-@end example
-@end ifset
-@ifclear GOT_LANG
-@example
-(example not available for this language)
-@end example
-@end ifclear
-
-@node Giving Customers Tips
-@chapter Giving Customers Tips
-@cindex tips
-
-@c NOTE: Terminology should not be merchant/customer here, as
-@c the relationship is completely different. So I use
-@c ``site'' and ``visitor'', as that is right now the proper
-@c context. We may want to use more payment-ish terminology
-@c in the future, but ``donor'' and ``grantee'' sound excessive
-@c in the context of ``tips''.
-
-GNU Taler allows Web sites to grant small amounts directly to the
-visitor. The idea is that some sites may want incentivize actions
-such as filling out a survey or trying a new feature. It is important
-to note that tips are not enforceable for the visitor, as there is no
-contract. It is simply a voluntary gesture of appreciation of the site
-to its visitor. However, once a tip has been granted, the visitor
-obtains full control over the funds provided by the site.
-
-The ``merchant'' backend of the site must be properly configured for
-tipping, and sufficient funds must be made available for tipping @xref{Top,,, manual,
-Taler Merchant Operating Manual}.
-
-To check if tipping is configured properly and if there are
-sufficient funds available for tipping, query the @code{/tip-query} endpoint:
-
-@clear GOT_LANG
-@ifset LANG_CURL
-@set GOT_LANG 1
-@example
-@verbatim
-curl -i 'https://backend.demo.taler.net/tip-query?instance=default' --header "Authorization: ApiKey sandbox"
-# HTTP/1.1 200 OK
-# [...]
-#
-# {
-# [...]
-# "amount_available": "KUDOS:153.47",
-# "amount_authorized": "KUDOS:10"
-# }
-@end verbatim
-@end example
-@end ifset
-@ifset LANG_PYTHON
-@set GOT_LANG 1
-@example
-@verbatim
->>> import requests
->>> requests.get("https://backend.demo.taler.net/tip-query?instance=default",
-... headers={"Authorization": "ApiKey sandbox"})
-<Response [200]>
-@end verbatim
-@end example
-@end ifset
-@ifset LANG_PHP
-@set GOT_LANG 1
-@example
-@verbatim
-php > $c = curl_init("https://backend.demo.taler.net/tip-query?instance=default");
-php > $options = array(CURLOPT_RETURNTRANSFER=>true,
-php ( CURLOPT_CUSTOMREQUEST=>"GET",
-php ( CURLOPT_HTTPHEADER=>array(
-php ( "Authorization: ApiKey sandbox"));
-php > curl_setopt_array($c, $options);
-php > $r = curl_exec($c);
-php > echo curl_getinfo($c, CURLINFO_HTTP_CODE);
-200
-@end verbatim
-@end example
-@end ifset
-@ifclear GOT_LANG
-@example
-(example not available for this language)
-@end example
-@end ifclear
-
-@cindex authorize tip
-To authorize a tip, @code{POST} to @code{/tip-authorize}. The following fields are recognized in the JSON
-request object:
-
-@itemize
-@item @var{amount}: Amount that should be given to the visitor as a tip.
-@item @var{instance}: Merchant instance that grants the tip (each instance may have its own independend tipping funds configured).
-@item @var{justification}: Description of why the tip was granted. Human-readable text not exposed to the customer, but used by the Back Office.
-@item @var{next_url}: The URL that the user's browser should be redirected to by the wallet, once the tip has been processed.
-@end itemize
-
-The response from the backend contains a @code{tip_redirect_url}. The customer's browser must be
-redirected to this URL for the wallet to pick up the tip.
-@cindex pick up tip
-
-This code snipped illustrates giving a tip:
-@clear GOT_LANG
-@ifset LANG_CURL
-@set GOT_LANG 1
-@example
-@verbatim
-TIP_REQ='
-{"amount": "KUDOS:0.5",
- "instance": "default",
- "justification": "User filled out survey",
- "next_url": "https://merchant.com/thanks.html"}
-'
-
-curl -i -X POST 'https://backend.demo.taler.net/tip-authorize' \
- --header "Authorization: ApiKey sandbox" -d "$TIP_REQ"
-# HTTP/1.1 200 OK
-# [...]
-#
-# {
-# [...]
-# "tip_redirect_url": "[...]"
-# }
-@end verbatim
-@end example
-@end ifset
-@ifset LANG_PYTHON
-@set GOT_LANG 1
-@example
-@verbatim
->>> import requests
->>> tip_req = dict(amount="KUDOS:0.5",
-... instance="default",
-... justification="User filled out survey",
-... next_url="https://merchant.com/thanks.html")
->>> requests.post("https://backend.demo.taler.net/tip-authorize", json=tip_req,
-... headers={"Authorization": "ApiKey sandbox"})
-<Response [200]>
-@end verbatim
-@end example
-@end ifset
-
-@ifset LANG_PHP
-@set GOT_LANG 1
-@example
-@verbatim
-php > $TIP_REQ = array(
-php ( "amount"=>"KUDOS:1",
-php ( "instance"=>"default",
-php ( "justification"=>"surveying",
-php ( "next_url"=>"https://example.com/survey-thanks.html");
-php > $options = array(CURLOPT_RETURNTRANSFER=>true,
-php ( CURLOPT_CUSTOMREQUEST=>"POST",
-php ( CURLOPT_POSTFIELDS=>json_encode($TIP_REQ),
-php ( CURLOPT_HTTPHEADER=>array("Authorization: ApiKey sandbox"));
-php > $c = curl_init("https://backend.demo.taler.net/tip-authorize");
-php > curl_setopt_array($c, $options);
-php > $r = curl_exec($c);
-php > echo curl_getinfo($c, CURLINFO_HTTP_CODE);
-200
-@end verbatim
-@end example
-@end ifset
-
-@ifclear GOT_LANG
-@example
-(example not available for this language)
-@end example
-@end ifclear
-
-
-@node Advanced topics
-@chapter Advanced topics
-
-@menu
-* Detecting the Presence of the Taler Wallet:: Detecting the Presence of the Taler Wallet
-* Integration with the Back Office:: Integration with the Back Office
-* Session-Bound Payments:: Session-bound payments for digital goods
-* Product Identification:: Product Identification
-* The Taler Order Format:: The Taler Order Format
-@end menu
-
-@node Detecting the Presence of the Taler Wallet
-@section Detecting the Presence of the Taler Wallet
-@cindex wallet
-
-Taler offers ways to detect whether a user has the wallet installed in
-their browser. This allows Web sites to adapt accordingly. Note that
-not all platforms can do presence detection reliably. Some platforms
-might have a Taler wallet installed as a separate App instead of using
-a Web extension. In these cases, presence detection will fail. Thus,
-sites may want to allow users to request Taler payments even if a
-wallet could not be detected, especially for visitors using mobiles.
-
-@subsection Presence detection without JavaScript
-Presence detection without JavaScript is based on CSS classes. You can hide or
-show elements selectively depending on whether the wallet is detected or not.
-
-In order to work correctly, a special fallback stylesheet must be included that
-will be used when the wallet is not present. The stylesheet can be put into
-any file, but must be included via a @code{link} tag with the @code{id}
-attribute set to @code{taler-presence-stylesheet}. If a wallet is present, it
-will ``hijack'' this stylesheet to change how elements with the following
-classes are rendered:
-
-The following CSS classes can be used:
-@table @code
-@item taler-installed-hide
-A CSS rule will set the @code{display} property for this class to @code{none} once the Taler wallet is installed and enabled.
-If the wallet is not installed, @code{display} will be @code{inherit}.
-
-@item taler-installed-show
-A CSS rule will set the @code{display} property for this class to @code{inherit} once the Taler wallet is installed and enabled.
-If the wallet is not installed, @code{display} will be @code{none}.
-
-@end table
-
-The following is a complete example:
-
-@smallexample
-<!DOCTYPE html>
-<html data-taler-nojs="true">
- <head>
- <title>Tutorial</title>
- <link rel="stylesheet"
- type="text/css"
- href="/web-common/taler-fallback.css"
- id="taler-presence-stylesheet" />
- </head>
- <body>
- <p class="taler-installed-hide">
- No wallet found.
- </p>
- <p class="taler-installed-show">
- Wallet found!
- </p>
- </body>
-</html>
-@end smallexample
-
-The @code{taler-fallback.css} is part of the Taler's @emph{web-common} repository,
-available at @url{https://git.taler.net/web-common.git/tree/taler-fallback.css}.
-You may have to adjust the @code{href} attribute in the HTML code above to point
-to the correct location of the @code{taler-fallback.css} file on your Web site.
-
-@subsection Detection with JavaScript
-
-The following functions are defined in the @code{taler} namespace of the @code{taler-wallet-lib} helper library
-available at @url{https://git.taler.net/web-common.git/tree/taler-wallet-lib.js}.
-
-@table @code
-@item onPresent(callback: () => void)
-Adds a callback to be called when support for Taler payments is detected.
-
-@item onAbsent(callback: () => void)
-Adds a callback to be called when support for Taler payments is disabled.
-
-@end table
-
-Note that the registered callbacks may be called more than once. This may
-happen if a user disables or enables the wallet in the browser's extension
-settings while a shop's frontend page is open.
-
-@c FIXME: include full example of Web site including taler-wallet-lib.js
-@c and using JS detection actions. (alert()?)
-
-@node Integration with the Back Office
-@section Integration with the Back Office
-
-Taler ships a Back Office application as a stand-alone Web application.
-The Back Office has its own documentation at @url{https://docs.taler.net/backoffice/html/manual.html}.
-
-Developers wishing to tightly integrate back office support for
-Taler-based payments into an existing back office application should
-focus on the wire transfer tracking and transaction history sections
-of the Taler Backend API specification at
-@url{https://docs.taler.net/api/api-merchant.html}
-
-@node Session-Bound Payments
-@section Session-Bound Payments
-@cindex 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 @code{session_id}, usually via a session cookie. When executing
-or re-playing a payment, the wallet will receive an additional signature
-(@code{session_sig}). This signature certifies that the wallet
-showed a payment receipt for the respective order in the current session.
-@cindex cookie
-
-Session-bound payments are triggerd by passing the @code{session_id} parameter
-to the @code{/check-payment} endpoint. The wallet will then redirect to the
-fulfillment page, but include an additional @code{session_sig} parameter. The
-frontend can query @code{/check-payment} with both the @code{session_id} and
-the @code{session_sig} to verify that the signature is correct.
-
-The last session ID that was successfuly used to prove that the payment
-receipt is in the user's wallet is also available as @code{last_session_id} in
-the response to @code{/check-payment}.
-@c FIXME: used for what?
-
-@node Product Identification
-@section Product Identification
-@cindex 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 reveil
-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 @code{resource_url} parameter to
-to @code{/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 @code{resource_url} before, and if so
-replay the previous payment.
-@c FIXME: design question (!): why do we not simply set a flag (``unique fulfillment url'')
-@c instead of passing the fulfillment URL a *second* time to the backend?
-@c (and having to worry about it being the same as in the order on /order)?
-
-
-@c Section describing the format of Taler contracts/proposals in detail
-
-@node The Taler Order Format
-@section The Taler Order Format
-@cindex contract
-@cindex terms
-@cindex order
-
-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 @code{"CURRENCY:DECIMAL_VALUE"}.
-
-@table @var
-@item amount
-@cindex amount
-Specifies the total amount to be paid to the merchant by the customer.
-
-@item max_fee
-@cindex fees
-@cindex maximum deposit 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 triplet used for @var{amount}.
-
-
-@item max_wire_fee
-@cindex fees
-@cindex maximum 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.
-
-
-@item wire_fee_amortization
-@cindex fees
-@cindex maximum 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. 0 and negative values are
-invalid and also interpreted as 1.
-
-@item pay_url
-@cindex pay_url
-Which URL accepts payments. This is the URL where the wallet will POST
-coins.
-
-@item fulfillment_url
-@cindex 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.
-
-@item order_id
-@cindex order ID
-Alphanumeric identifier, freely definable by the merchant.
-Used by the merchant to uniquely identify the transaction.
-
-@item summary
-@cindex 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.
-
-@item timestamp
-Time at which the offer was generated.
-@c FIXME: describe time format in detail here
-
-@item pay_deadline
-@cindex payment 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 @var{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.
-
-@item refund_deadline
-@cindex 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 @var{pay_deadline}.
-
-@item products
-@cindex product description
-Array of products that are being sold to the customer. Each
-entry contains a tuple with the following values:
-
-@table @var
-@item description
-Description of the product.
-@item quantity
-Quantity of the items to be shipped. May specify a unit (@code{1 kg})
-or just the count.
-@item price
-Price for @var{quantity} units of this product shipped to the
-given @var{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.
-@item 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})}.
-@item taxes
-Map of applicable taxes to be paid by the merchant. The label is the
-name of the tax, i.e. @var{VAT}, @var{sales tax} or @var{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.
-@c FIXME: a receipt not including the item's price?
-The information is also likely to be used by tax audits of the merchant.
-@item delivery_date
-Time by which the product is to be delivered to the
-@var{delivery_location}.
-@item delivery_location
-This should give a label in the @var{locations} map, specifying
-where the item is to be delivered.
-@end table
-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 @var{product_id} or @var{price} may not be
-specified in the contract. Similarly, for virtual products delivered
-directly via the fulfillment URI, there is no delivery location.
-
-@item merchant
-@table @var
-@item address
-This should give a label in the @var{locations} map, specifying
-where the merchant is located.
-@item name
-This should give a human-readable name for the merchant's business.
-@item jurisdiction
-This should give a label in the @var{locations} map, specifying
-the jurisdiction under which this contract is to be arbitrated.
-@end table
-
-@item locations
-@cindex location
-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:
-@table @var
-@item country
-Name of the country for delivery, as found on a postal package, i.e. ``France''.
-@item state
-Name of the state for delivery, as found on a postal package, i.e. ``NY''.
-@item region
-Name of the region for delivery, as found on a postal package.
-@item province
-Name of the province for delivery, as found on a postal package.
-@item city
-Name of the city for delivery, as found on a postal package.
-@item ZIP code
-ZIP code for delivery, as found on a postal package.
-@item street
-Street name for delivery, as found on a postal package.
-@item street number
-Street number (number of the house) for delivery, as found on a postal package.
-@item name receiver name for delivery, either business or person name.
-
-@end table
-
-Note that 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.
-
-@end table
-
-
-@c **********************************************************
-@c ******************* Appendices *************************
-@c **********************************************************
-
-@node GNU-LGPL
-@unnumbered GNU-LGPL
-@cindex license
-@cindex LGPL
-@include lgpl.texi
-
-@node GNU-FDL
-@unnumbered GNU-FDL
-@cindex license
-@cindex GNU Free Documentation License
-@include fdl-1.3.texi
-
-@node Concept Index
-@unnumbered Concept Index
-
-@printindex cp