     [file version.texi not included]

The GNU Taler manual for Web shops
**********************************

This manual is for the GNU Taler merchant backend (version VERSION, UPDATED),

Copyright © 2016 INRIA

     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''.

Introduction
************

This manual addresses how to integrate GNU Taler with Web shops.  It describes how to install a GNU Taler merchant backend and make it communicate with an existing Web shop frontend.

In detail, the manual shows how to install all the required dependencies of the backend and how to tune its configuration to serve your shop. We conclude the initial part with a tutorial about a minimalistic frontend having a donation button which uses Taler payments.

This manual is mainly addressed to system administrators, as the backend is a service, and Web developers, as their sites need to interact with the backend.

Architecture overview
=====================

The backend provides the cryptographic support, stores Taler-specific financial information in a DBMS and communicates with the GNU Taler exchange. 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 (such as the merchant's signing keys and bank account information).

Installation
************

This chapter describes how to install the GNU Taler merchant backend.

Generic instructions
====================

This section provides generic instructions for the merchant backend installation independent of any particular operating system. Operating system specific instructions are provided in the following sections.  You should follow the operating system specific instructions if those are available, and only consult the generic instructions if no system-specific instructions are provided for your specific operating system.

Dependencies
============

Installation of dependencies
----------------------------

The following packages need to be installed before we can compile the backend:

  * libcurl or libgnurl

  * GNU libmicrohttpd, including GnuTLS

  * GNU libgcrypt

  * libjansson

  * Postgres, including libpq

  * GNUnet

  * GNU Taler exchange

The first five are available in most GNU/Linux distributions and should just be installed using the respective package manager, for example using

     # apt-get install libcurl4-gnutls-dev \
       libmicrohttpd-dev \
       libgnutls-dev \
       libgcrypt20-dev \
       libjansson-dev \
       libpq-dev \
       postgresql-9.5

The following sections will provide detailed instructions for installing the GNUnet and GNU Taler exchange dependencies.

Installing GNUnet
-----------------

Note that a Web shop supporting GNU Taler does not actually need to run a GNUnet peer.  The requirement to have a minimal GNUnet installation arises from the fact that GNUnet provides some required routines for doing cryptography, string manupulation, interfacing with databases, JSON manipulation, logging and operating system abstractions.  Hence this manual does not describe how to actually run a GNUnet peer, and we also skip optional GNUnet dependencies that an ordinary peer might want to include in the installation.  Thus, do not be alarmed if the GNUnet build process warns you about missing (optional) dependencies.

Before you install GNUnet, you should download and install the dependencies mentioned in the previous section, otherwise GNUnet may install but fail to export some of the tooling required by Taler.

To download and install GNUnet, proceed as follows:

     $ svn checkout https://gnunet.org/svn/gnunet/
     $ cd gnunet/
     $ ./bootstrap
     $ ./configure [--prefix=GNUNETPFX]
     $ # Each dependency can be fetched from non standard locations via
     $ # the '--with-<LIBNAME>' option. See './configure --help'.
     $ make
     # make install

If you did not specify a prefix, GNUnet will install to /usr/local, which requires you to run the last step as root.

Installing the GNU Taler exchange
---------------------------------

After installing GNUnet, you can download and install the exchange as follows:

     $ git clone git://taler.net/exchange
     $ cd exchange
     $ ./bootstrap
     $ ./configure [--prefix=EXCHANGEPFX] \
                   [--with-gnunet=GNUNETPFX]
     $ # Each dependency can be fetched from non standard locations via
     $ # the '--with-<LIBNAME>' option. See './configure --help'.
     $ make
     # make install

If you did not specify a prefix, the exchange will install to /usr/local, which requires you to run the last step as root.  Note that you have to specify --with-gnunet=/usr/local if you installed GNUnet to /usr/local in the previous step.

Installing the GNU Taler merchant backend
-----------------------------------------

The following steps assume all dependencies are installed.

Use the following commands to download and install the merchant backend:

     $ git clone git://taler.net/merchant
     $ cd merchant
     $ ./bootstrap
     $ ./configure [--prefix=PFX] \
                   [--with-gnunet=GNUNETPFX] \
                   [--with-exchange=EXCHANGEPFX]
     $ # Each dependency can be fetched from non standard locations via
     $ # the '--with-<LIBNAME>' option. See './configure --help'.
     $ make
     $ make install

Note that you have to specify --with-exchange=/usr/local and/or --with-exchange=/usr/local if you installed the exchange and/or GNUnet to /usr/local in the previous steps.

Installing Taler with GNU Guix
==============================

This section has not yet been written.

Installing Taler using Docker
=============================

This section has not yet been written.

Installing Taler on Debian GNU/Linux
====================================

This section has not yet been written.

Installing Taler on Arch Linux
==============================

This section has not yet been written.

Installing Taler on Windows
===========================

This section has not yet been written.

Installing Taler on OS X
========================

This section has not yet been written.

How to configure the merchant's backend
***************************************

The installation already provides reasonable defaults for most of the configuration options. However, some of them must be tuned to the particular Web shop.  By default, the file $HOME/.config/taler.conf is where the Web shop administrator specifies configuration values that augment or override the defaults.

The following table describes the options that commonly need to be modified. Here, the notation [section]/option denotes the option option under the section [section] in the configuration file.

Service address
     The following option sets the transport layer address used by the Merchant backend:

          [merchant]/serve = TCP | UNIX

     If given,

       * TCP, then we need to set the TCP port in [merchant]/port

       * UNIX, then we need to set the unix domain socket path and mode in [merchant]/unixpath and [merchant]/unixpath_mode. The latter takes the usual permission mask given as a number, e.g. 660 for user/group read-write access.

     The frontend can then connect to the backend over HTTP using the specified address. If frontend and backend run within the same operating system, the use of a UNIX domain socket is recommended to avoid accidentally exposing the backend to the network.

Currency
     Which currency the Web shop deals in, i.e. ``EUR'' or ``USD'', is specified using the option

          [merchant]/currency

     For testing purposes, the currency should match ``KUDOS'' which is used by the Taler demonstration exchange at https://exchange.demo.taler.net/.

Database
     In principle is possible for the backend to support different DBMSs. The option

          [merchant]/db

     specifies which DBMS is to be used. However, currently only the value "postgres" is supported.

     In addition to selecting the DBMS software, the backend requires DBMS-specific options to access the database.

     For postgres, you need to provide:

          [merchantdb-postgres]/config

     This option specifies a postgres access path using the format "postgres:///DBNAME", where DBNAME is the name of the Postgres database you want to use.  Suppose USER is the name of the user who will run the backend process.  Then, you need to first run

          $ createuser -d USER

     as the postgres database administrator to grant USER the ability to create new databases.  Next, you should as USER run

          $ createdb DBNAME

     to create the backend's database.  Here, DBNAME must match the database name given in the configuration file.

Exchange
     To add an exchange to the list of trusted payment service providers, you create a section with a name that starts with ``merchant-exchange-'' and set the following options in that section:

          [merchant-exchange-MYEXCHANGE]/uri

     Takes the exchanges base URL, e.g. https://exchange.demo.taler.net/.

          [merchant-exchange-MYEXCHANGE]/master_key

     Takes the base32 encoding of the exchange's master public key, e.g.

          CQQZ9DY3MZ1ARMN5K1VKDETS04Y2QCKMMCFHZSWJWWVN82BTTH00.

     Note that multiple exchanges can be added to the system by using different tokens in place of MYEXCHANGE in the example above.

Wireformat

     In order to receive payments, the merchant backend needs to communicate bank account details to the exchange.  The banking system used is specified using the following global option:

          [merchant]/wireformat

     The value test can be used to interact with the Taler demonstrator at https://bank.demo.taler.net/.  Other wireformats will be supported in the future to interact with actual banks.

Instances

     The backend allows the user to run multiple instances of shops with distinct business entities against a single backend.  Each instance uses its own bank account and key for signing contracts.  It is mandatory to configure a "default" instance using the following options:

          [merchant-instance-default]/keyfile

     Specifies the path to the instance's private key.  You do not need to create a key at this time, the backend will generate it automatically if it is missing.  While generally unnecessary, it is possible to generate the key and to display the public key using the gnunet-ecc command-line tool.

          [merchant-instance-wireformat-default]/test_response_file

     This option specifies the path to a file that describes the instance's wire details in JSON format.  The specific format depends slightly on the banking system selected via the wireformat option.

     For the test wire format, a sample specification looks as follows:

     {
       "type": "test",
       "bank_uri": "https://bank.test.taler.net/",
       "account_number": 5,
       "salt": "RANDOMSALT"
     }

     Those bank details above, are included in the contract in their hashed form, so the 'salt' field is needed to make harder brute-forcing them.

     In order to get an account number, register at our demonstration bank: https://bank.demo.taler.net/

     Note that additional instances can be specified using different tokens in the section name instead of default.

Sample backend configuration
============================

The following is an example for a complete backend configuration:

     [merchant]
     wireformat = TEST
     serve = TCP
     port = 9898
     currency = EUR
     database = postgres

     [merchant-instance-default]
     KEYFILE = $DATADIR/key.priv

     [merchant-instance-wireformat-default]
     TEST_RESPONSE_FILE = $DATADIR/test.json

     [merchantdb-postgres]
     config = postgres:///donations

     [merchant-demoexchange]
     uri = https://exchange.demo.taler.net/
     master_key = CQQZ9DY3MZ1ARMN5K1VKDETS04Y2QCKMMCFHZSWJWWVN82BTTH00

The configuration file is typically located at $HOME/.config/taler.conf.  An alternative location can be specified to taler-merchant-httpd using the -c option.

The contents of $DATADIR/test.json might look like this:

     {
       "type": "test",
       "bank_uri": "https://bank.example.com/",
       "account_number": 15,
       "salt": "1851695201"
     }

The resulting backend will be listening on port 9898.

The backend's private key will be located at $DATADIR/key.priv. You can determine the expaned path using

     $ taler-config -f -s merchant-instance-wireformat-default -o TEST_RESPONSE_FILE

The backend will use a database named donations within Postgresql.

The backend will deposit the coins it receives to the exchange at https://exchange.demo.taler.net/, which has the master key

"CQQZ9DY3MZ1ARMN5K1VKDETS04Y2QCKMMCFHZSWJWWVN82BTTH00".

Launching the backend
=====================

As mentioned previously, the system adminstrator should make sure that a database named donations is defined and accessible in the system. Once this configuration is ready, the merchant backend can be launched using:

     $ taler-merchant-httpd

If everything worked as expected, the command

     $ curl http://localhost:9898/

should return the message

     Hello, I'm a merchant's Taler backend. This HTTP server is not for humans.

Please note that your backend is right now likely globally reachable.  Production systems should be configured to bind to a UNIX domain socket or properly restrict access to the port.

Setting up a simple Web shop with GNU Taler
*******************************************

This section describes how to setup a simple shop, which exposes a button to get donations via Taler. The expected behaviour is that once the ``donate'' button is clicked, the customer will receive a Taler contract offering him the opportunity to make a fixed donation, for example to donate 1 KUDOS to the charity operating the shop.

Note that if the customer does not have the Taler wallet installed, they should instead be prompted to proceed with a classic dialog for credit card payments.

Prompting for payment
=====================

Our goal is to trigger a Taler payment once the customer has clicked on a donation button.  We will use a button that issues an HTTP POST to the frontend /donate URL.  For this, the HTML would be as follows:

     <form action="/donate">
       <input type="submit" value="Donate!"></input>
     <form>

When the server-side handler for /donate receives the form submission, it will return a HTML page that will take care of:

  * showing a credit card paywall to the user if no wallet is found, and

  * fetching a Taler contract and passing it to the wallet if one is found

A minimalistic /donate handler is shown below (in PHP):

     <?php
       http_response_code (402); // 402: Payment required
       header ('X-Taler-Contract-Url: /generate-contract');
     ?>
     <html>
       <head>
       <title>Select payment method</title>
       </head>
       <body>
         <!-- Put the credit card paywall here -->
       </body>
     </html>

Given this response, the Taler wallet will fetch the contract from /generate-contract and display it to the user.  If the wallet is not present, the HTML body will be shown and the Taler headers will be ignored by the browser.  Instead of specifying the contract via an URL, it is also possible to inline short contracts directly.

Note that we could have bypassed the POST request to trigger the payment, and performed the interaction with the wallet directly from the button's via JavaScript.  We will consider this case in a later chapter.

Generating the contract
=======================

The server-side handler for /generate-contract now has to generate a contract proposal about donating 1 KUDOS to the 'Taler charity program'.  This proposed contract is then be POSTed to the backend at /contract.  The main result of POSTing the proposal to the backend is that it will be cryptographically signed, as by design the frontend does not perform any cryptographic work.

A simple /generate-contract handler may look like this:

     function make_contract($transaction_id, $now) {
      $contract =
       array (
        'amount' => array (
         'value' => 1,
         'fraction' => 0,
         'currency' => "KUDOS"),
        'max_fee' => array (
         'value' => 3,
         'fraction' => 50000,
         'currency' => "KUDOS"),
        'transaction_id' => $transaction_id,
        'products' => array (
          array (
           'description' => "Donation to charity program",
           'quantity' => 1,
           'price' => array (
            'value' => 1,
            'fraction' => 0,
            'currency' => "KUDOS"),
           'product_id' => 0,
           'taxes' => array(), // No taxes for donations
           'delivery_date' => "Some Date Format",
           'delivery_location' => 'LNAME1')),
           'timestamp' => "/Date(" . $now->getTimestamp() . ")/",
           'expiry' =>
            "/Date(" . $now->add(new DateInterval('P2W'))->getTimestamp() . ")/",
           'refund_deadline' =>
            "/Date(" . $now->add(new DateInterval('P3M'))->getTimestamp() . ")/",
           'repurchase_correlation_id' => '',
           'fulfillment_url' =>
            "https://charity-shop.example.com/fulfillment?"
            . "transaction_id=$transaction_id&timestamp=$now",
           'merchant' => array (
            'address' => 'LNAME2',
            'name' => "Charity donations shop",
            'jurisdiction' => 'LNAME3'),
           'locations' => array (
            'LNAME1' =>
             array (
     	 'country' => 'Test Country',
       	 'city' => 'Test City',
       	 'state' => 'Test State',
       	 'region' => 'Test Region',
       	 'province' => 'Test Province',
       	 'ZIP code' => 4908,
       	 'street' => 'test street',
       	 'street number' => 20),
       	 'LNAME2' => array (
     	  'country' => 'Test Country',
       	  'city' => 'Test City',
       	  'state' => 'Test State',
       	  'region' => 'Test Region',
       	  'province' => 'Test Province',
       	  'ZIP code' => 4908,
       	  'street' => 'test street',
       	  'street number' => 20),
       	  'LNAME3' => array (
     	   'country' => 'Test Country',
                'city' => 'Test City',
                'state' => 'Test State',
                'region' => 'Test Region',
                'province' => 'Test Province',
                'ZIP code' => 4908)));
     }

     /* this variable is the JSON of a contract proposal,
      see https://api.taler.net/api-merchant.html#post--contract
      the second parameter is the transaction id */
     $transaction_id = rand(1,90000);
     $proposal = make_contract($transaction_id, new DateTime('now'));

     # Here the frontend POSTs the proposal to the backend
     $response = post_to_backend("/contract", $proposal);

     if (200 != $response->getResponseCode()) {
       echo json_encode(array(
         'error' => "internal error",
         'hint' => "failed to regenerate contract",
         'detail' => $resp->body->toString()
         ), JSON_PRETTY_PRINT);
       return;
     }
     echo $response->body;

After the browser has fetched the contract, the user will be given the opportunity to affirm the payment.

The function post_to_backend is shown in the figure below, as it's not strictly part of the handler.

     function post_to_backend($backend_relative_url, $json){
       $url = "https://charity-shop-backend.example.com$backend_relative_url";

       $req = new http\Client\Request("POST",
                                      $url,
                                      array ("Content-Type" => "application/json"));

       $req->getBody()->append($json);

       // Execute the HTTP request
       $client = new http\Client;
       $client->enqueue($req)->send();
       return $client->getResponse();
     }

Receiving payments via Taler
============================

The next step for the frontend is to accept the payment from the wallet, assuming the user accepts the contract.  For this, the frontend must implement a payment handler at the URI specified for as the X-Taler-Pay-Url in the example above.

The role of the /pay handler is to receive the payment from the wallet and forward it to the backend.  If the backend reports that the payment was successful, the handler needs to update the session state with the browser to remember that the user paid. The following code implements this in PHP:

     # Check if a session exists already
     session_start();
     if (! isset($_SESSION['paid'])) {
       echo "<p>There is no session for this purchase. Something is wrong.</p>";
       return;
     }
     # Get the HTTP POST body
     $payment = file_get_contents('php://input');
     $response = post_to_backend("/pay", $payment);
     if (200 != $response->getResponseCode()){
       echo json_encode(array(
         'error' => "internal error",
         'hint' => "failed to POST coins to the backend",
         'detail' => $response->body->toString()
         ), JSON_PRETTY_PRINT);
       return;
     }
     $_SESSION['paid'] = true;
     return $response->body;

Do not be confused by the isset test for the session state.  In our simple example, it will be set to ``false'' by the fulfillment URL which the browser actually always visits first. (This is for technical reasons; the natural logical progression would of course be to pay before accessing the fulfillment URL.)  We describe how the fulfillment URL works in the next section.

The fulfillment page
====================

The fulfillment page can be called by users that have already paid for the item, as well as by users that have not yet paid at all.  The fulfillment page must use the HTTP session state to detect if the payment has been performed already, and if not request payment from the wallet.

For our example, we include in the URI of the fulfillment page the data which is needed to allow the page to determine which contract the user is trying to access. Thus, the fulfillment URL for our example looks like the following:

     https://charity-shop.example.com/fulfillment? \
     transaction_id=<TRANSACTION_ID>&timestamp=<CONTRACTTIMESTAMP>

The /fulfillment handler will then perform the following actions:

     <html>
      <head>
       <title>Donation Fulfillment</titile>
      </head>
      <body>
       <?php
        # At first, check if the user has already paid for the product.
        # If so, deliver the product.
        session_start();
        if (! isset($_SESSION['paid'])){
         # set as pending
         $_SESSION['paid'] = false;
        }
        else{
         if($_SESSION['paid']){
          echo "<p>Thanks for your donation!</p>";
          return;
        }
         else{
          echo '<form action="/cc-payment">
           First name<br> <input type="text"></input><br>
           Family name<br> <input type="text"></input><br>
           Age<br> <input type="text"></input><br>
           Nationality<br> <input type="text"></input><br>
           CC number<br> <input type="text"></input><br>
           Cvv2 code<br> <input type="text"></input><br>
           <input type="radio" name="gender">Female</input><br>
           <input type="submit"></input>
           </form>';
           return;
        }
       }

       # Reconstruct the contract
       $rec_proposal = make_contract($_GET['transaction_id'], $_GET['timestamp']);
       # $response obeys to the specification at:
       # https://api.taler.net/api-merchant.html#offer
       $response = post_to_backend("/contract", $rec_proposal);

       http_response_code (402);
       header ('X-Taler-Contract-Hash: json_decode($response)["H_contract"]');
       header ('X-Taler-Offer-Url: /donate');
       header ('X-Taler-Pay-Url: /pay'); ?>
      </body>
     </html>

Advanced topics
***************

This chapter includes draft texts for advanced topics which have not yet been properly integrated with the main text.

Using the SEPA wire transfer method
===================================

Let's say that all the donations go to the following recipient, expressed in SEPA format (As said, supporting SEPA is still work in progress).

{
  "type": "SEPA",
  "IBAN": "XY00 1111 2222 3333 4444 5555 6666",
  "name": "Taler charity program",
  "BIC": "XXXXAB99",
  "salt": "RANDOMSALT"
}

Assume this information is stored in file $DATADIR/sepa.json.

Payments using JavaScript
=========================

The function executePayment exported by taler-wallet-lib.js will basically hand its three parameters to the wallet which implements the following semantics:

check in the internal DB if $response['H_contract'] has an entry, and:

  * if that is the case, then the user accepted the contract previously and the wallet sends a deposit permission  (Roughly speaking, a deposit permission is a JSON containing the coins to pay for a contract. Its full specification is available at: https://api.taler.net/api-merchant.html#depositpermission) to /frontend-pay. If this operation succeeds, then visit again the fulfillment URL, and finally enjoy the product.

  * if not, redirect the browser to /donate (which will then reinitiate the whole contract negotiation). This happens when the user visits a shared fulfillment URL. The idea is to let that user buy the same products as the user who shared the fulfillment URL. Nonetheless, the shop is not forced to follow this semantics when provides the third parameter to executePayment.

Design considerations for the fulfillment page
==============================================

The fulfillment page mechanism is designed to provide the following two properties:

 1. Taler payments can be implemented in DB-less frontends.

 2. Taler payments are replayable, meaning that each purchase is associated with a URL (the fulfillment URL) that shows the product each time it gets visited (and of course, only the first time takes the user's money).

In order to implement property (1), the frontend needs a way to recall what a contract is about (e.g. which product, which price, the timestamp, etc.) before proceeding with the actual payment and eventually deliver the final product.  That is achieved by reconstructing the contract using the fulfillment page's URL parameters (the fulfillment URL equipped with all the parameters is included in the contract).

In order to implement property (2), the frontend will firstly check the state to see if the product claimed among the fulfillment URL parameter has been paid; if so, the product is given to the customer. Otherwise, the frontend sets the payment as "pending" in the state and executes it in the wallet. The payment execution is performed by returning JavaScript code from taler-wallet-lib.js that triggers the wallet to send the payment to the pay page.  Once the pay page receives the payment, it sets the state for the payment as "payed".