From 3ee973fe5892dba1384dc4ca97e46148e479febd Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Mon, 26 Dec 2016 23:27:28 +0100 Subject: Moving payment protocol on 'docs' --- api/api-merchant.rst | 6 +- api/integration-bank.rst | 81 -------------- api/integration-general.rst | 82 -------------- api/integration-merchant.rst | 256 ------------------------------------------- 4 files changed, 3 insertions(+), 422 deletions(-) delete mode 100644 api/integration-bank.rst delete mode 100644 api/integration-general.rst delete mode 100644 api/integration-merchant.rst (limited to 'api') diff --git a/api/api-merchant.rst b/api/api-merchant.rst index b2f61233..11ed325e 100644 --- a/api/api-merchant.rst +++ b/api/api-merchant.rst @@ -25,7 +25,7 @@ Merchant API Before reading the API reference documentation, see the `merchant architecture `_ -and :ref:`payprot` +and the `payment protocol `_ --------------------- The Frontend HTTP API @@ -141,8 +141,8 @@ This frontend API is non-normative, and only gives an example of what a typical Returns a cooperative merchant page (called the execution page) that will send the ``taler-execute-payment`` to the wallet and react to failure or success of the actual payment. ``fulfillment_url`` is included in the `contract`_. - Furthermore, :ref:`payprot` documents the payment protocol between wallets and - merchants. + Furthermore, `https://docs.taler.net/integration-merchant.html#payprot`_ + documents the payment protocol between wallets and merchants. The wallet will inject an ``XMLHttpRequest`` request to the merchant's ``$pay_url`` in the context of the execution page. This mechanism is diff --git a/api/integration-bank.rst b/api/integration-bank.rst deleted file mode 100644 index 1dc2ec8d..00000000 --- a/api/integration-bank.rst +++ /dev/null @@ -1,81 +0,0 @@ -============================== -Interaction with bank websites -============================== - -This section describes how bank websites can interact with the -Taler wallet. - -Currently the following functionality is supported: - * Querying for the presence of a Taler wallet. - * Receiving change notifications from the Taler wallet. - * Creating a reserve. - - -For JavaScript code examples, see :ref:`communication`. - -------------------------- -Reserve Creation Request -------------------------- - -The bank website can request the creation of a :term:`reserve`. This operation -will require the user to specify the exchange where he wants to create the reserve -and the resolution of a CAPTCHA, before any action will be taken. - -As a result of the reserve creation request, the following steps will happen in sequence: - 1. The user chooses the desired amount from the bank's form - 2. Upon confirmation, the wallet fetches the desired amount from the user-filled form and - prompts the user for the *exchange base URL*. Then ask the user to confirm creating the - reserve. - 3. The wallet will create a key pair for the reserve. - 4. The wallet will request the CAPTCHA page to the bank. In that request's parameters it - communicates the desired amount, the reserve's public key and the exchange base URL to the - bank - 5. Upon successful resolution of the CAPTCHA by the user, the bank initiates the reserve - creation according to the gotten parameters. Together with `200 OK` status code sent back - to the wallet, it gets also a `ReserveCreated`_ object. - -Note that the reserve creation can be done by a SEPA wire transfer or some other means, -depending on the user's bank and chosen exchange. - -In response to the reserve creation request, the Taler wallet MAY cause the -current document location to be changed, in order to navigate to a -wallet-internal confirmation page. - -The bank requests reserve creation with the ``taler-create-reserve`` event. -The event data must be a `CreateReserveDetail`_: - - -.. _CreateReserveDetail: -.. code-block:: tsref - - interface CreateReserveDetail { - - // JSON 'amount' object. The amount the caller wants to transfer - // to the recipient's count - amount: Amount; - - // CAPTCHA's page URL which needs the following parameters - // query parameters: - // amount_value - // amount_fraction - // amount_currency - // reserve_pub - // exchange - // wire_details (URL encoding of /wire output from the exchange) - callback_url: string; - - // list of wire transfer types supported by the bank - // e.g. "SEPA", "TEST" - wt_types: Array - } - -.. _ReserveCreated: -.. code-block:: tsref - - interface ReserveCreated { - - // A URL informing the user about the succesfull outcome - // of his operation - redirect_url: string; - - } diff --git a/api/integration-general.rst b/api/integration-general.rst deleted file mode 100644 index 308ecf5a..00000000 --- a/api/integration-general.rst +++ /dev/null @@ -1,82 +0,0 @@ -.. _integration-general: - -================================ -Taler Wallet Website Integration -================================ - -.. note:: - The wallet-Websites communication is switching to a new policy which - is NOT based on DOM events, therefore obsoleting this page. To be soon - documented. - - -Websites (such as banks and online shops) can communicate with -the Taler wallet by a standardized protocol. - -From a technical perspective, the Taller wallet communicates with -the website by sending and receiving `DOM events `_ -on the bank website's ``HTMLDocument``. - -DOM events used by Taler have the prefix ``taler-``. - -------------------------- -Wallet Presence Awareness -------------------------- - -The bank website queries the wallet's presence by sending a ``taler-probe`` event. The -event data should be `null`. - -If the wallet is present and active, it will respond with a ``taler-wallet-present`` event. - -While the user agent is displaying a website, the user might deactivate or -re-activate the wallet. A Taler-aware *should* react to those events, and -indicate to the user that they should (re-)enable the wallet if necessary. - -When the wallet is activated, the ``taler-wallet-load`` event is sent -by the wallet. When the wallet is deactivated, the ``taler-wallet-unload`` event -is sent by the wallet. - -.. _communication: - ----------------------- -Communication Example ----------------------- - -The bank website can send the event ``taler-XYZ`` with the event data ``eventData`` -to the wallet with the following JavaScript code: - -.. sourcecode:: javascript - - const myEvent = new CustomEvent("taler-XYZ", eventData); - document.dispatchEvent(myEvent); - -Events can be received by installing a listener: - - -.. sourcecode:: javascript - - function myListener(talerEvent) { - // handle event here! - } - document.addEventListener("taler-XYZ", myListener); - - --------------------- -Normalized Base URLs --------------------- - -Exchanges and merchants have a base URL for their service. This URL *must* be in a -canonical form when it is stored (e.g. in the wallet's database) or transmitted -(e.g. to a bank page). - -1. The URL must be absolute. This implies that the URL has a schema. -2. The path component of the URL must end with a slash. -3. The URL must not contain a fragment or query. - -When a user enters a URL that is, technically, relative (such as "alice.example.com/exchange"), wallets -*may* transform it into a canonical base URL ("http://alice.example.com/exchange/"). Other components *should not* accept -URLs that are not canonical. - -Rationale: Joining non-canonical URLs with relative URLs (e.g. "exchange.example.com" with "reserve/status") -results in different and slightly unexpected behavior in some URL handling libraries. -Canonical URLs give more predictable results with standard URL joining. diff --git a/api/integration-merchant.rst b/api/integration-merchant.rst deleted file mode 100644 index 7cf93044..00000000 --- a/api/integration-merchant.rst +++ /dev/null @@ -1,256 +0,0 @@ -.. - This file is part of GNU TALER. - -.. - Note that this page is more a protocol-explaination than a guide that teaches - merchants how to work with Taler wallets - - Copyright (C) 2014, 2015, 2016 INRIA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License along with - TALER; see the file COPYING. If not, see - - @author Marcello Stanisci - @author Christian Grothoff - -================================== -Interaction with merchant websites -================================== - -.. _payprot: - -+++++++++++++++++++ -The payment process -+++++++++++++++++++ - -By design, the Taler payment process ensures the following properties: - -1. The user must see and accept a contract in a secure context before the payment happens. - That contract accounts for all the items which are supposed to be bought. - -2. The payment process must be idempotent, that is at any later time the customer must - be able to replay the payment and retrieve the resource he paid for. - In case where a physical item was bought, this online resource is the merchant's - order status page, which may contain tracking information for the customer. - Note that by `replaying the payment` we mean reusing the `same coins` used to pay for - the product the first time to get the `same product` the user got the first time. - So the replay does NOT subtract further credit from the user's total budget. - -3. Purchases are shareable: any purchase is given a URL that allows other users to - buy the same item(s). - -We call an *offer URL* any URL at the merchant's Web site that notifies the -wallet that the user needs to pay for something. The offer URL must take into -account that the user has no wallet installed, and manage the situation accordingly -(for example, by showing a credit card paywall). The notification can happen either -via JavaScript or via HTTP headers. - -The merchant needs to have a *contract URL* which generates the JSON -contract for Taler. Alternatively, the contract may be embedded -within the page returned by the offer URL and given to the wallet -via JavaScript or via an HTTP header. - -The merchant must also provide a *pay URL* to which the wallet can -transmit the payment. Again, how this URL is made known from the merchant -to the wallet, it is managed by the HTTP headers- or JavaScript-based protocol. - -The merchant must also have a *fulfillment URL*, that addresses points 2 and 3 above. -In particular, fulfillment URL is responsible for: - -* Deliver the final product to the user after the payment -* Instruct the wallet to send the payment to the pay URL -* Redirect the user to the offer URL in case they hit a shared fulfillment URL. - -Again, Taler provides two ways of doing that: JavaScript- and HTTP headers-based. - -Taler helps merchants on the JavaScript-based interaction by providing the -``taler-wallet-lib``. See https://git.taler.net/web-common.git/tree/taler-wallet-lib.ts - -------- -Example -------- - -For example, suppose Alice wants to pay for a movie. She will first -select the movie from the catalog, which directs her to the offer URL -*https://merchant/offer?x=8ru42*. This URL generates a "402 Payment -Required" response, and will instruct the wallet about the contract's -URL. Then the wallet downloads the contract that states that Alice is -about to buy a movie. The contract includes a fresh transaction ID, say 62. -Alice's browser detects the response code and displays the contract -for Alice. - -Alice then confirms that she wants to buy the movie. Her wallet -associates her confirmation with the details and a hash of the contract. -After Alice confirms, the wallet redirects her to the fulfillment URL, say -*https://merchant/fulfillment?x=8ru42&tid=62* that is specified in the -contract. - -The first time Alice visits this URL, the merchant will again -generate a "402 Payment Required" response, this time not including -the full contract but merely the hash of the contract (which includes -Alice's transaction ID 62), as well as the offer URL (which Alice -will ignore) and the pay URL. Alice's wallet will detect that -Alice already confirmed that she wants to execute this particular -contract. The wallet will then transmit the payment to the pay URL, -obtain a response from the merchant confirming that the payment was -successful, and then reload the fulfillment URL. - -This time (and every time in the future where Alice visits the -fulfillment URL), she receives the movie. If the browser has lost the -session state, the merchant will again ask her to pay (as it happened the -very first time she visited the fulfillment URL), and she will authenticate -by replaying the payment. - -If Alice decides to share the fulfillment URL with Bob and he visits -it, his browser will not have the right session state and furthermore -his wallet will not be able to replay the payment. Instead, his wallet -will automatically redirect Bob to the offer URL and allow him to -purchase the movie himself. - -.. _offer: - ---------------- -Making an offer ---------------- - -When a user visits a offer URL, the merchant returns a page that can interact -with the wallet either via JavaScript or by returning a "402 Payment Required". -This page's main objective is to inform the wallet on where it should get the -contract. In case of JavaScript interaction, the merchant should just return -a page whose javascript contains an invocation to ``offerContractFrom()`` -from ``taler-wallet-lib``. This function will download the contract from -`` and hand it to the wallet. - -In case of HTTP headers-based protocol, the merchant needs to set the header -`X-Taler-contract-url` to the contract URL. Once this information reaches the -browser, the wallet will takes action by reading that header and downloading -the contract. - -Either way, the contract gets to the wallet which then renders it to the user. - -.. _fulfillment: - -------------------------------- -Fulfillment interaction details -------------------------------- - -A payment process is triggered whenever the user visits a fulfillment -URL and he has no rights in the session state to get the items -accounted in the fulfillment URL. Note that after the user accepts a -contract, the wallet will automatically point the browser to the -fulfillment URL. - -Becasue fulfillment URLs implements replayable and shareable payments -(see points 2,3 above), fulfillment URL parameter must encompass all the -details necessary to reconstruct a contract. - -That saves the merchant from writing contracts to disk upon every contract -generation, and defer this operation until customers actually pay. - -.................. -HTTP headers based -.................. - -Once the fulfillment URL gets visited, deliver the final product if the user has -paid, otherwise: the merchant will reconstruct the contract and re-hash it, sending -back to the client a "402 Payment required" status code and some HTTP headers which -will help the wallet to manage the payment. Namely: - -* `X-taler-contract-hash` -* `X-taler-pay-URL` -* `X-taler-offer-URL` - -The wallet then looks at `X-taler-contract-hash`, and can face two situations: - -1. This hashcode is already present in the wallet's database (meaning that the user did accept the related contract), so the wallet can send the payment to `X-taler-pay-URL`. During this operation, the wallet associates the coins it sent to `X-taler-pay-URL` with this hashcode, so that it can replay payments whenever it gets this hashcode again. - -2. This hashcode is unknown to the wallet (meaning that the user visited a shared fulfillment URL). The wallet then points the browser to `X-taler-offer-URL`, which is in charge of generating a contract referring to the same items accounted in the fulfillment URL. Of course, the user is then able to accept or not the contract. - -................ -JavaScript based -................ - -Once the fulfillment URL gets visited, deliver the final product if the user has paid, otherwise: -the merchant will reconstruct the contract and re-hash it. Then it will return a page whose JavaScript -needs to include a call to ``taler.executeContract(..)``. See the following example: - -.. sourcecode:: html - - - - - - - .. - - - -The logic which will take place is the same as in the HTTP header based protocol. -Once ``executePayment(..)`` gets executed in the browser, it will hand its three -parameters to the wallet, which will: - -1. Send the payment to `` if `` is found in its database (meaning that the user accepted it). -2. Redirect the browser to ``, if `` is NOT found in its database, meaning that the user visited a shared fulfillment URL. - -.. - .................. - State and security - .................. - - The server-side state gets updated in two situations, (1) when an article is - "about" to be bought, which means when the user visits the fulfillment URL, - and (2) when the user actually pays. For (1), we use the contract hascode to - access the state, whereas in (2) we just define a list of payed articles. - For example: - - .. sourcecode:: python - - session[] = {'article_name': 'How_to_write_a_frontend'} # (1) - session['payed_articles'] = ['How_to_write_a_frontend', 'How_to_install_a_backend'] # (2) - - The list of payed articles is used by the frontend to deliver the article to the user: - if the article name is among ``session['payed_articles']``, then the user gets what they - paid for. - - The reason for using `` as the key is to prevent the wallet to send bogus - parameters along the fulfillment URL. `` is the contract hashcode that - the fulfillment handler gets from the backend using the fulfillment URL parameters. - - In fact, when the wallet sends the payment to the frontend pay handler, it has to provide - both coins and contract hashcode. That hascode is (1) verified by the backend when it - receives the coins, (2) used by the frontend to update the list of payed articles. - - See below an example of pay handler: - - .. sourcecode:: python - - ... - - # 'deposit_permission' is the JSON object sent by the wallet - # which contains coins and the contract hashcode. - response = send_payment_to_backend(deposit_permission) - - # The backend accepted the payment - if 200 == response.status_code: - # Here we pick the article name from the state defined at - # fulfillment time. - # deposit_permission['H_contract'] is the contract hashcode - payed_article = session[deposit_permission['H_contract']]['article_name'] - session['payed_articles'].append(payed_article) - - - So the wallet is forced to send a valid contract hashcode along the payment, - and since that hashcode is then used to update the list of payed articles, - the wallet is forced to send fulfillment URL parameters that match that hashcode, - therefore being valid parameters. -- cgit v1.2.3