diff options
author | Christian Grothoff <christian@grothoff.org> | 2017-10-15 17:13:58 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2017-10-15 17:13:58 +0200 |
commit | fbd4260ef9d26c017462de0c61a1148886e77c65 (patch) | |
tree | 7bca90b340fde36bea81520718e15ce779efe9e5 | |
parent | 39074ad2b66370599396fbb1e4a1835ec7c9d5fe (diff) | |
download | merchant-frontend-examples-fbd4260ef9d26c017462de0c61a1148886e77c65.tar.gz merchant-frontend-examples-fbd4260ef9d26c017462de0c61a1148886e77c65.tar.bz2 merchant-frontend-examples-fbd4260ef9d26c017462de0c61a1148886e77c65.zip |
clean up tutorials
-rw-r--r-- | .gitignore | 11 | ||||
-rw-r--r-- | common/html/js-wallet.html | 26 | ||||
-rw-r--r-- | common/texi/api-reference.texi | 88 | ||||
-rw-r--r-- | common/texi/fdl-1.3.texi (renamed from python/doc/fdl-1.3.texi) | 0 | ||||
-rw-r--r-- | common/texi/fulfillment-page.texi | 30 | ||||
-rw-r--r-- | common/texi/instances.texi | 24 | ||||
-rw-r--r-- | common/texi/js-payments.texi | 69 | ||||
-rw-r--r-- | common/texi/lgpl.texi (renamed from python/doc/lgpl.texi) | 0 | ||||
-rw-r--r-- | common/texi/normalized-base-url.texi | 22 | ||||
-rw-r--r-- | common/texi/proposals.texi | 186 | ||||
-rw-r--r-- | common/texi/syntax.texi (renamed from python/doc/syntax.texi) | 0 | ||||
-rw-r--r-- | common/texi/wallet-detection.texi | 62 | ||||
-rw-r--r-- | php/doc/inline-proposals.texi | 22 | ||||
-rw-r--r-- | php/doc/tutorial.texi | 545 | ||||
-rw-r--r-- | python/doc/tutorial.texi | 240 |
15 files changed, 709 insertions, 616 deletions
@@ -4,3 +4,14 @@ php/doc/arch.* common/graphics/*.png common/graphics/*.pdf common/graphics/*.jpg +*~ +python/doc/arch.png +python/doc/arch_nobo.jpg +python/doc/arch_nobo.pdf +python/doc/tutorial.aux +python/doc/tutorial.cp +python/doc/tutorial.cps +python/doc/tutorial.html +python/doc/tutorial.log +python/doc/tutorial.pdf +python/doc/tutorial.toc diff --git a/common/html/js-wallet.html b/common/html/js-wallet.html new file mode 100644 index 0000000..1154eba --- /dev/null +++ b/common/html/js-wallet.html @@ -0,0 +1,26 @@ +<html lang="en"> + <head> + <script src="/web-common/taler-wallet-lib.js" type="application/javascript"> + </script> + </head> + <body> + <div id="content"> + </div> + <script type="application/javascript"> + + content = document.getElementById("content"); + p = document.createElement("p"); + + function walletInstalled(){ + p.textContent = "Wallet installed!"; + content.appendChild(p); + } + function walletNotInstalled(){ + p.textContent = "Wallet not found."; + content.appendChild(p); + } + taler.onPresent(wallerInstalled); + taler.onAbsent(wallerNotInstalled); + </script> + </body> +</html> diff --git a/common/texi/api-reference.texi b/common/texi/api-reference.texi new file mode 100644 index 0000000..6e3cd52 --- /dev/null +++ b/common/texi/api-reference.texi @@ -0,0 +1,88 @@ +@node Reference +@chapter Reference + +@menu +* Headers for HTTP 402:: Headers for the 402 status code and their effect on the user agent's operation +* JavaScript API:: JavaScript API to communicate with the wallet +* Stylesheet-based presence detection:: Presence detection using CSS style sheets and no JavaScript +@end menu + +@node Headers for HTTP 402 +@section Headers for HTTP 402 +The HTTP status code @code{402 Payment Required} can be used by the merchant +frontend to trigger operations related to payments in the user agent. The user +agent associates at most one proposal with every URL via the proposal's +@code{fulfillment_url} field. The associated proposal is either missing (in +case it doesn't exist), paid (in case the payment for it was successfully sent +to the merchant) or unpaid. If the associated proposal is unpaid, @code{402 +Payment Required} will cause the user agent to pay for the associated proposal. + +The following headers for @code{402 Payment Required} are recognized by Taler and further influence the processing: +@table @code +@item X-Taler-Refund-Url +If this header present, the value of this header must be a URL that the user agent can use to request and process refunds. + +@item X-Taler-Contract-Url +If there is no associated proposal, the user agent will fetch a proposal from +this URL and process it. This typically prompts the user to agree to pay. + +@item X-Taler-Offer-Url +If there is no associated proposal and @code{X-Taler-Contract-Url} is not +specified, the browser will navigate to this URL. + +@item X-Taler-User-Tipping-Url +If this header present, the value of this header must be a URL that the user agent can use to obtain tips (small, non-binding +financial rewards) payed from the merchant to the user's wallet. If this field is present, @code{X-Taler-User-Tipping-Exchange} +and @code{X-Taler-User-Tipping-Amount} must also be present. + +@item X-Taler-User-Tipping-Exchange +Exchange base URL for the exchange that the merchant helps withdrawing the tip from. + +@item X-Taler-User-Tipping-Amount +Amount of tip that the user is receiving, in the standard amount format (CURR:X.Y). + +@end table + +@node JavaScript API +@section JavaScript API + +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) +Add a callback to be called when support for Taler payments is detected. + +@item onAbsent(callback: () => void) +Add a callback to be called when support for Taler payments is disabled. + +@item pay(@{contract_url: string, offer_url: string@}) +Results in the same action as a @code{402 Payment Required} with @code{contract_url} in +the @code{X-Taler-Contract-Url} header and @code{offer_url} in the @code{X-Taler-Payment-Url} header. + +@item refund(refund_url: string) +Results in the same action as a @code{402 Payment Required} with @code{refund_url} in +the @code{X-Taler-Refund-Url} header. + +@end table + +@node Stylesheet-based presence detection +@section Stylesheet-based presence detection + +Stylesheet-based presence detection will be applied on all pages that have the +@code{data-taler-nojs} attribute of the @code{html} element set @code{true}. +The default/fallback stylesheet, that will be taken over by the wallet once +installed, must be included with the id @code{taler-presence-stylesheet}, like +this: + +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 diff --git a/python/doc/fdl-1.3.texi b/common/texi/fdl-1.3.texi index 8805f1a..8805f1a 100644 --- a/python/doc/fdl-1.3.texi +++ b/common/texi/fdl-1.3.texi diff --git a/common/texi/fulfillment-page.texi b/common/texi/fulfillment-page.texi new file mode 100644 index 0000000..5ae9628 --- /dev/null +++ b/common/texi/fulfillment-page.texi @@ -0,0 +1,30 @@ +@c Section of advanced topics discussing the fulfillment page in more depth. + +@node The fulfillment page +@section The fulfillment page +@cindex fulfillment page + +This section describes some of the design considerations for the fulfillment page. +They are primarily relevant for high-performance setups. + +The fulfillment page mechanism is designed to provide the following two properties: + +@enumerate +@item Taler payments @emph{can} be implemented in DB-less frontends. + +@item 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). +@end enumerate + +Both properties are gotten "for free" by the way replayable payments are +implemented. Since @code{pay.php} simply relays payments to the backend, +if the latter returns "200 OK", then the frontend delivers what is mentioned +in the backend's response. Note that along with the "200 OK" response, +the backend returns the whole proposal associated with the fulfillment +URL that triggered the payment, so the frontend has all the information +useful to pick the right product to deliver. +The "payment" relayed to the backend contains the @emph{order id}, +that allows the backend to perform all the integrity checks on the +payment. +This way, the frontend does not need any database to replay payments. diff --git a/common/texi/instances.texi b/common/texi/instances.texi new file mode 100644 index 0000000..42f0099 --- /dev/null +++ b/common/texi/instances.texi @@ -0,0 +1,24 @@ +@c Section from ``advanced topics'' introducing the concept of instances + +@node Instances +@section Instances +@cindex instances + +Taler's design allows a single backend to manage multiple frontends. +In other words, we might have multiple shops relying on the same backend. +As of terminology, we call @emph{instance} any of the frontends accounted +by the same backend. + +The backend's RESTful API allows frontends to specify which instance they are. +However, this specification is optional, and a ``default'' instance will be +used whenever the frontend does not specify one. + +Please note that in this stage of development, the backend's REST call @code{/history} +returns records for @emph{any} instance. The rationale behind is to allow grouping +``public'' business entities under the same backend. + +This way, a single frontend can expose multiple donation buttons for multiple +receivers, and still operate against one backend. So in this scenario, there is no +harm if the operator of instance `a' sees history entries related to instance `b'. + +See @code{https://donations.demo.taler.net/}, which uses this functionality. diff --git a/common/texi/js-payments.texi b/common/texi/js-payments.texi new file mode 100644 index 0000000..6c88069 --- /dev/null +++ b/common/texi/js-payments.texi @@ -0,0 +1,69 @@ +@c Section about triggering payments via JavaScript, currently not used! + +@node Payments using JavaScript +@section Triggering payments using JavaScript +@c +Please note that the following examples are purely instructional and NOT TESTED +along with the tutorial code. +@c +@cindex JavaScript +@c +@subsection Offering contracts +@c +Offering contracts the JavaScript way doesn't require us to set HTTP +headers, and so -- in a minimalistic implementation -- the donation button +should just hit a HTML page that invokes the @code{offerContractFrom} function, +from the @code{taler-wallet-lib.js} library. +@c +Thus our homepage can now look as follows +@c +@smallexample +// ../index-js.html +@verbatiminclude ../index-js.html +@end smallexample +@c +@code{donate-js.html} is now in charge of calling @code{offerContractFrom} +passing the contract URL to it, which is @code{"/generate-order.php"} in +our example. See below. + +@c +@smallexample +// ../donate-js.html +@verbatiminclude ../donate-js.html +@end smallexample +@c +Please make sure that @code{taler-wallet-lib.js} location is valid. +@c +@subsection Receiving payments +@cindex payment +@c +In the example in section @ref{Initiating the payment process}, the fulfillment +handler @code{/fulfillment.php} triggers the payment in the wallet by returing +the three needed values (contract hashcode, pay URL, offer URL) via HTTP headers. +@c +The same action can be accomplished @emph{with} JavaScript, thanks to +@code{taler-wallet-lib.js} of @emph{web-common} repository. +The fulfillment handler needs just to call the function @code{executePayment}, feeding it +with the three needed parameters. The wallet will then get triggered and proceed with the +payment. See below a full example: +@c +@smallexample +// ../fulfillment-js.php +@verbatiminclude ../fulfillment-js.php +@end smallexample +@c +Note that, in order to use this fulfillment handler for the tutorial, you need to +specify it in the contract's ``fulfillment_url'' field: +@c +@smallexample +@{ +... contract fields .. +@c +"fulfillment_url": "/fulfillment-js.php?transaction_id=<TRANSACTION_ID>& \ + timestamp=<CONTRACTTIMESTAMP>" +... +@} +@end smallexample +@c +Additionally, you should also make sure that @code{taler-wallet-lib.js} location +is valid. diff --git a/python/doc/lgpl.texi b/common/texi/lgpl.texi index ab03d6c..ab03d6c 100644 --- a/python/doc/lgpl.texi +++ b/common/texi/lgpl.texi diff --git a/common/texi/normalized-base-url.texi b/common/texi/normalized-base-url.texi new file mode 100644 index 0000000..b06d468 --- /dev/null +++ b/common/texi/normalized-base-url.texi @@ -0,0 +1,22 @@ +@c Section from ``advanced topics'' about how to normalize base URLs + +@node Normalized base URLs +@section Normalized base URLs + +Exchanges and merchants have a base URL for their service. This URL @b{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). + +@itemize +@item The URL must be absolute. This implies that the URL has a schema. +@item The path component of the URL must end with a slash. +@item The URL must not contain a fragment or query. +@end itemize + +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/common/texi/proposals.texi b/common/texi/proposals.texi new file mode 100644 index 0000000..f234c49 --- /dev/null +++ b/common/texi/proposals.texi @@ -0,0 +1,186 @@ +@c Section describing the format of Taler contracts/proposals in detail + +@node The Taler proposal format +@section The Taler proposal format +@cindex contract + +A Taler proposal can specify many details about the transaction. +This section describes each of the fields in depth. + +@table @var +@item amount +@cindex amount +Specifies the total amount to be paid to the merchant by the customer. +The amount is broken up into a @var{value}, a @var{fraction} +(100.000.000 @var{fraction} units correspond to one @var{value}) and +the @var{currency}. For example, @code{EUR 1.50} would be represented +as the tuple @code{value = 1, fraction = 50000000, currency = "EUR"}. + +@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 it 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 diff --git a/python/doc/syntax.texi b/common/texi/syntax.texi index 8bb37b3..8bb37b3 100644 --- a/python/doc/syntax.texi +++ b/common/texi/syntax.texi diff --git a/common/texi/wallet-detection.texi b/common/texi/wallet-detection.texi new file mode 100644 index 0000000..a4b9a34 --- /dev/null +++ b/common/texi/wallet-detection.texi @@ -0,0 +1,62 @@ +@c Section on how to detect the Taler wallet + +@node Detecting the presence of the Taler wallet +@section Detecting the presence of the Taler wallet +@cindex wallet + +Taler offers the way to the frontend developer to detect whether +a user has the wallet installed in their browser, and take actions +accordingly. + +@subsection The no-JavaScript way +The follwing example shows all that is needed to perform the detection +without using JavaScript: + +@smallexample +<!DOCTYPE html> +<html lang="en" 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 @code{https://git.taler.net/web-common.git}. Please adjust the @code{href} +attribute in order to make it work with your Web site. + +The detection works by @code{taler-fallback.css} hiding any tag from the +@code{taler-installed-show} class, in case no wallet is installed. If otherwise +the wallet is installed, the wallet takes action by hiding any tag from the +@code{taler-installed-hide} class and overriding @code{taler-fallback.css} logic +by showing any tag from the @code{taler-installed-show} class. + +@subsection The JavaScript way + +@code{taler-wallet-lib.js} helps the frontend, by providing the way to register two +callbacks: one to be executed if a wallet is present, the other if it is not. +See the example below: + +@smallexample +// js-wallet.html +@verbatiminclude ../../common/html/js-wallet.html +@end smallexample + +@code{taler-wallet-lib.js} exports the @code{taler} object that +exposes the @code{onPresent} and the @code{onAbsent} functions needed +to register the frontend's callbacks. Thus the function @code{walletInstalled} +will be executed whenever a wallet is installed, and @code{walletNotInstalled} +if not. Note that since now we can use JavaScript we can register +callbacks that do more than just showing and hiding elements. diff --git a/php/doc/inline-proposals.texi b/php/doc/inline-proposals.texi new file mode 100644 index 0000000..3613e9a --- /dev/null +++ b/php/doc/inline-proposals.texi @@ -0,0 +1,22 @@ +@node Inlining proposals in HTTP headers +@section Inlining proposals in HTTP headers +@cindex optimization +@cindex contract + +In the example in @ref{Prompting for payment}, we told the wallet the URL +from where it should fetch the proposal. Instead of specifying the proposal +via an URL, it is also possible to inline short proposals directly. + +That may be accomplished by the frontend including the @code{X-Taler-Proposal} +HTTP header, whenever the requested page is meant to trigger a payment. +The example shown below may be an alternative version of @code{/donate.php}, +which implements inline contracts. + +@smallexample +// ../inline.php +@verbatiminclude ../inline.php +@end smallexample + +The wallet will then look for the @code{X-Taler-Proposal} header, and fetch the +inlined contract if this header is found. Please note that this feature is not +yet implemented in the wallet. diff --git a/php/doc/tutorial.texi b/php/doc/tutorial.texi index 7b8d31b..27ef83a 100644 --- a/php/doc/tutorial.texi +++ b/php/doc/tutorial.texi @@ -2,6 +2,7 @@ @c %**start of header @setfilename tutorial.info @include version.texi +@include ../../common/texi/syntax.texi @settitle The GNU Taler tutorial for PHP Web shop developers @value{VERSION} @c Define a new index for options. @@ -15,7 +16,7 @@ This tutorial is about implementing a merchant frontend to run against a GNU Taler merchant backend (version @value{VERSION}, @value{UPDATED}), -Copyright @copyright{} 2016 INRIA +Copyright @copyright{} 2016, 2017 Taler Systems SA @quotation Permission is granted to copy, distribute and/or modify this document @@ -37,7 +38,8 @@ Texts. A copy of the license is included in the section entitled @subtitle Version @value{VERSION} @subtitle @value{UPDATED} @author Marcello Stanisci (@email{marcello.stanisci@@inria.fr}) -@author Christian Grothoff (@email{christian.grothoff@@inria.fr}) +@author Christian Grothoff (@email{christian.grothoff@@inria.fr} +@author Florian Dold (@email{florian.dold@@inria.fr}) @page @vskip 0pt plus 1filll @insertcopying @@ -432,7 +434,7 @@ transfer. The Taler exchange may aggregate multiple payments from transactions into one larger wire transfer. The @var{refund_deadline} and the @var{pay_deadline} values in the contract specify the timeframes within which the exchange is permitted to perform such -aggregations, see @ref{Taler contracts}. +aggregations, see @ref{The Taler proposal format}. In this chapter, we will see how a merchant can obtain the mapping from transactions to wire transfers and vice versa. @@ -562,529 +564,24 @@ See below both parts: @chapter Advanced topics @menu -* Presence detection:: Reacting to the presence of a Taler wallet -* Taler contracts:: Building Taler contracts -* Inline proposals:: Snding proposals with the HTTP header -* The Fulfillment page:: The rationale behind the fulfillment page design -* Normalized base URLs:: Format URLs are expected to be in Taler +* Detecting the presence of the Taler wallet:: Detecting the presence of the Taler wallet +* The Taler proposal format:: The Taler proposal format +* Inlining proposals in HTTP headers:: Inlining proposals in HTTP headers +* Instances:: Instances +* The fulfillment page:: The fulfillment page +* Normalized base URLs:: Normalized base URLs @end menu -@c FIXME. Add section about including images (or extra files in general) -@c along with payed content. +@include ../../common/texi/wallet-detection.texi +@include ../../common/texi/proposals.texi +@include inline-proposals.texi +@include ../../common/texi/instances.texi +@include ../../common/texi/fulfillment-page.texi +@include ../../common/texi/normalized-base-url.texi -@node Presence detection -@section Reacting to the presence of a Taler wallet -@cindex wallet - -Taler offers the way to the frontend developer to detect whether -a user has the wallet installed in their browser, and take actions -accordingly. - -@subsection The no-JavaScript way -The follwing example shows all that is needed to perform the detection -without using JavaScript: - -@smallexample -<!DOCTYPE html> -<html lang="en" 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 @code{https://git.taler.net/web-common.git}. Please adjust the @code{href} -attribute in order to make it work with your Web site. - -The detection works by @code{taler-fallback.css} hiding any tag from the -@code{taler-installed-show} class, in case no wallet is installed. If otherwise -the wallet is installed, the wallet takes action by hiding any tag from the -@code{taler-installed-hide} class and overriding @code{taler-fallback.css} logic -by showing any tag from the @code{taler-installed-show} class. - -@subsection The JavaScript way - -@code{taler-wallet-lib.js} helps the frontend, by providing the way to register two -callbacks: one to be executed if a wallet is present, the other if it is not. -See the example below: - -@smallexample -<html lang="en"> - <head> - <script src="/web-common/taler-wallet-lib.js" type="application/javascript"> - </script> - </head> - <body> - <div id="content"> - </div> - <script type="application/javascript"> - - content = document.getElementById("content"); - p = document.createElement("p"); - - function walletInstalled(){ - p.textContent = "Wallet installed!"; - content.appendChild(p); - } - function walletNotInstalled(){ - p.textContent = "Wallet not found."; - content.appendChild(p); - } - taler.onPresent(wallerInstalled); - taler.onAbsent(wallerNotInstalled); - </script> - </body> -</html> -@end smallexample - -@code{taler-wallet-lib.js} exports the @code{taler} object that -exposes the @code{onPresent} and the @code{onAbsent} functions needed -to register the frontend's callbacks. Thus the function @code{walletInstalled} -will be executed whenever a wallet is installed, and @code{walletNotInstalled} -if not. Note that since now we can use JavaScript we can register -callbacks that do more than just showing and hiding elements. - - -@node Taler proposals -@section Building Taler proposals -@cindex contract - -A Taler proposal can specify many details about the transaction. -This section describes each of the fields in depth. - -@table @var -@item amount -@cindex amount -Specifies the total amount to be paid to the merchant by the customer. -The amount is broken up into a @var{value}, a @var{fraction} -(100.000.000 @var{fraction} units correspond to one @var{value}) and -the @var{currency}. For example, @code{EUR 1.50} would be represented -as the tuple @code{value = 1, fraction = 50000000, currency = "EUR"}. - -@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 it 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 - -@node Inline proposals -@section Inlining proposals in HTTP headers -@cindex optimization -@cindex contract - -In the example in @ref{Prompting for payment}, we told the wallet the URL -from where it should fetch the proposal. Instead of specifying the proposal -via an URL, it is also possible to inline short proposals directly. - -That may be accomplished by the frontend including the @code{X-Taler-Proposal} -HTTP header, whenever the requested page is meant to trigger a payment. -The example shown below may be an alternative version of @code{/donate.php}, -which implements inline contracts. - -@smallexample -// ../inline.php -@verbatiminclude ../inline.php -@end smallexample - -The wallet will then look for the @code{X-Taler-Proposal} header, and fetch the -inlined contract if this header is found. Please note that this feature is not -yet implemented in the wallet. - -@c @node Payments using JavaScript -@c @section Triggering payments using JavaScript -@c -@c Please note that the following examples are purely instructional and NOT TESTED -@c along with the tutorial code. -@c -@c @cindex JavaScript -@c -@c @subsection Offering contracts -@c -@c Offering contracts the JavaScript way doesn't require us to set HTTP -@c headers, and so -- in a minimalistic implementation -- the donation button -@c should just hit a HTML page that invokes the @code{offerContractFrom} function, -@c from the @code{taler-wallet-lib.js} library. -@c -@c Thus our homepage can now look as follows -@c -@c @smallexample -@c // ../index-js.html -@c @verbatiminclude ../index-js.html -@c @end smallexample -@c -@c @code{donate-js.html} is now in charge of calling @code{offerContractFrom} -@c passing the contract URL to it, which is @code{"/generate-order.php"} in -@c our example. See below. -@c -@c @smallexample -@c // ../donate-js.html -@c @verbatiminclude ../donate-js.html -@c @end smallexample -@c -@c Please make sure that @code{taler-wallet-lib.js} location is valid. -@c -@c @subsection Receiving payments -@c @cindex payment -@c -@c In the example in section @ref{Initiating the payment process}, the fulfillment -@c handler @code{/fulfillment.php} triggers the payment in the wallet by returing -@c the three needed values (contract hashcode, pay URL, offer URL) via HTTP headers. -@c -@c The same action can be accomplished @emph{with} JavaScript, thanks to -@c @code{taler-wallet-lib.js} of @emph{web-common} repository. -@c The fulfillment handler needs just to call the function @code{executePayment}, feeding it -@c with the three needed parameters. The wallet will then get triggered and proceed with the -@c payment. See below a full example: -@c -@c @smallexample -@c // ../fulfillment-js.php -@c @verbatiminclude ../fulfillment-js.php -@c @end smallexample -@c -@c Note that, in order to use this fulfillment handler for the tutorial, you need to -@c specify it in the contract's ``fulfillment_url'' field: -@c -@c @smallexample -@c @{ -@c ... contract fields .. -@c -@c "fulfillment_url": "/fulfillment-js.php?transaction_id=<TRANSACTION_ID>& \ -@c timestamp=<CONTRACTTIMESTAMP>" -@c ... -@c @} -@c @end smallexample -@c -@c Additionally, you should also make sure that @code{taler-wallet-lib.js} location -@c is valid. - -@node The fulfillment page -@section Design considerations for the fulfillment page -@cindex fulfillment page - -The fulfillment page mechanism is designed to provide the following two properties: - -@enumerate -@item Taler payments @emph{can} be implemented in DB-less frontends. - -@item 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). -@end enumerate - -Both properties are gotten "for free" by the way replayable payments are -implemented. Since @code{pay.php} simply relays payments to the backend, -if the latter returns "200 OK", then the frontend delivers what is mentioned -in the backend's response. Note that along with the "200 OK" response, -the backend returns the whole proposal associated with the fulfillment -URL that triggered the payment, so the frontend has all the information -useful to pick the right product to deliver. -The "payment" relayed to the backend contains the @emph{order id}, -that allows the backend to perform all the integrity checks on the -payment. -This way, the frontend doesn't need any database to replay payments. - -@node Instances -@section Instances -@cindex instances - -Taler's design allows a single backend to manage multiple frontends. -In other words, we might have multiple shops relying on the same backend. -As of terminology, we call @emph{instance} any of the frontends accounted -by the same backend. - -The backend's RESTful API allows frontends to specify which instance they are. -However, this specification is optional, and a ``default'' instance will be -used whenever the frontend does not specify one. - -Please note that in this stage of development, the backend's REST call @code{/history} -returns records for @emph{any} instance. The rationale behind is to allow grouping -``public'' business entities under the same backend. - -This way, a single frontend can expose multiple donation buttons for multiple -receivers, and still operate against one backend. So in this scenario, there is no -harm if the operator of instance `a' sees history entries related to instance `b'. - -See @code{https://donations.demo.taler.net/}, which uses this functionality. - -@node Normalized base URLs -@section Normalized base URLs - -Exchanges and merchants have a base URL for their service. This URL @b{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). - -@itemize -@item The URL must be absolute. This implies that the URL has a schema. -@item The path component of the URL must end with a slash. -@item The URL must not contain a fragment or query. -@end itemize - -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. - - -@c The following section is copied from the Python manual, -@c changes should be done there and then copied back here. -@node Reference -@chapter Reference - -@menu -* Headers for HTTP 402:: Headers for the 402 status code and their effect on the user agent's operation -* JavaScript API:: JavaScript API to communicate with the wallet -* Stylesheet-based presence detection:: Presence detection using CSS style sheets and no JavaScript -@end menu - -@node Headers for HTTP 402 -@section Headers for HTTP 402 -The HTTP status code @code{402 Payment Required} can be used by the merchant -frontend to trigger operations related to payments in the user agent. The user -agent associates at most one proposal with every URL via the proposal's -@code{fulfillment_url} field. The associated proposal is either missing (in -case it doesn't exist), paid (in case the payment for it was successfully sent -to the merchant) or unpaid. If the associated proposal is unpaid, @code{402 -Payment Required} will cause the user agent to pay for the associated proposal. - -The following headers for @code{402 Payment Required} are recognized by Taler and further influence the processing: -@table @code -@item X-Taler-Refund-Url -If this header present, the value of this header must be a URL that the user agent can use to request and process refunds. - -@item X-Taler-Contract-Url -If there is no associated proposal, the user agent will fetch a proposal from -this URL and process it. This typically prompts the user to agree to pay. - -@item X-Taler-Offer-Url -If there is no associated proposal and @code{X-Taler-Contract-Url} is not -specified, the browser will navigate to this URL. - -@end table - -@node JavaScript API -@section JavaScript API - -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) -Add a callback to be called when support for Taler payments is detected. - -@item onAbsent(callback: () => void) -Add a callback to be called when support for Taler payments is disabled. - -@item pay(@{contract_url: string, offer_url: string@}) -Results in the same action as a @code{402 Payment Required} with @code{contract_url} in -the @code{X-Taler-Contract-Url} header and @code{offer_url} in the @code{X-Taler-Payment-Url} header. - -@item refund(refund_url: string) -Results in the same action as a @code{402 Payment Required} with @code{refund_url} in -the @code{X-Taler-Refund-Url} header. - -@end table - -@node Stylesheet-based presence detection -@section Stylesheet-based presence detection - -Stylesheet-based presence detection will be applied on all pages that have the -@code{data-taler-nojs} attribute of the @code{html} element set @code{true}. -The default/fallback stylesheet, that will be taken over by the wallet once -installed, must be included with the id @code{taler-presence-stylesheet}, like -this: - -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 - +@c ************ Reference chapter *********** +@include ../../common/texi/api-reference.texi @c ********************************************************** @c ******************* Appendices ************************* @@ -1094,13 +591,13 @@ If the wallet is not installed, @code{display} will be @code{none}. @unnumbered GNU-LGPL @cindex license @cindex LGPL -@include lgpl.texi +@include ../../common/texi/lgpl.texi @node GNU-FDL @unnumbered GNU-FDL @cindex license @cindex GNU Free Documentation License -@include fdl-1.3.texi +@include ../../common/texi/fdl-1.3.texi @node Concept Index @unnumbered Concept Index diff --git a/python/doc/tutorial.texi b/python/doc/tutorial.texi index 3d11468..d4b66dc 100644 --- a/python/doc/tutorial.texi +++ b/python/doc/tutorial.texi @@ -2,7 +2,7 @@ @c %**start of header @setfilename tutorial.info @include version.texi -@include syntax.texi +@include ../../common/texi/syntax.texi @settitle The GNU Taler tutorial for Python Web shop developers @value{VERSION} @c Define a new index for options. @@ -16,7 +16,7 @@ This tutorial is about implementing a merchant frontend to run against a GNU Taler merchant backend (version @value{VERSION}, @value{UPDATED}), -Copyright @copyright{} 2016, 2017 INRIA +Copyright @copyright{} 2016, 2017 Taler Systems SA @quotation Permission is granted to copy, distribute and/or modify this document @@ -57,6 +57,7 @@ Texts. A copy of the license is included in the section entitled @menu * Introduction:: What this tutorial is about * Setting up a simple donation page:: How to set up a donation page +* Back-office-integration:: How to integrate with the back office * Advanced topics:: Detailed solutions to specific issues * Reference:: Merchant integration reference @@ -252,7 +253,7 @@ If the wallet is not present, the error message ``No wallet installed!'' will be shown and the Taler ``X-Taler-Contract-Url'' header and the 402 status code ought to be ignored by the browser. -@section A helper function to generate the order +@section A helper function to generate the order We make distinction between @emph{three} different stages of what it informally called "contract". @@ -369,7 +370,7 @@ def fulfillment(): # make the payment, assuming the user already accepted the # proposal. response = flask.Response(status=402) - + # At this URL, the wallet may request a regeneration of the proposal. response.headers["X-Taler-Contract-Url"] = make_url("/generate-proposal") # This URL will be visited in case the user has opened @@ -471,122 +472,177 @@ should be able to point your browser at @code{http://localhost:5000/} and make a donation. -@node Advanced topics -@chapter Advanced topics -@menu -* Normalized base URLs:: Format URLs are expected to be in Taler -@end menu -@node Normalized base URLs -@section Normalized base URLs -Exchanges and merchants have a base URL for their service. This URL @b{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). +@node Back-office-integration +@chapter Integration with the back office + +This chapter shows how to implement the back office Web interface. + +We will use the term @emph{transaction} to refer to the business +transaction that a merchant has with a customer (and the related +communication with the Taler exchange for payment), and the term +@emph{wire transfer} to refer to the exchange settling its accounts +with the merchant. + +However, from the frontend's perspective, any transaction is denoted +by the @emph{order id} contained in the proposal that led to the +transaction. + +Given that Taler deals with microtransactions, not every customer +payment processed with Taler will necessarily correspond to a wire +transfer. The Taler exchange may aggregate multiple payments from +transactions into one larger wire transfer. The @var{refund_deadline} +and the @var{pay_deadline} values in the contract specify the +timeframes within which the exchange is permitted to perform such +aggregations, see @ref{The Taler proposal format}. + +In this chapter, we will see how a merchant can obtain the +mapping from transactions to wire transfers and vice versa. +Additionally, we will describe how to obtain a list of all +transactions known to the backend. + +@section Entry page + +Given this charge, the back office's main tasks are: @itemize -@item The URL must be absolute. This implies that the URL has a schema. -@item The path component of the URL must end with a slash. -@item The URL must not contain a fragment or query. +@item +Allow the back office operator to specify a order id, and display the +corresponding wire transfer identifiers. +@item +Allow the back office operator to specify a wire transfer ID, and +display all of the corresponding order ids. +@item +Allow the back office operator to obtain a list of all transactions. @end itemize -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. +We implement these with a simple HTML form. For simplicity, we have +one single page for gathering input data for both tracking directions: -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. +@smallexample +TBD. +@end smallexample -@node Reference -@chapter Reference +The imported script @code{history.js} is responsible for dynamically +get the list of known transactions. See below. -@menu -* Headers for HTTP 402:: Headers for the 402 status code and their effect on the user agent's operation -* JavaScript API:: JavaScript API to communicate with the wallet -* Stylesheet-based presence detection:: Presence detection using CSS style sheets and no JavaScript -@end menu +@section Tracking a transaction -@node Headers for HTTP 402 -@section Headers for HTTP 402 -The HTTP status code @code{402 Payment Required} can be used by the merchant -frontend to trigger operations related to payments in the user agent. The user -agent associates at most one proposal with every URL via the proposal's -@code{fulfillment_url} field. The associated proposal is either missing (in -case it doesn't exist), paid (in case the payment for it was successfully sent -to the merchant) or unpaid. If the associated proposal is unpaid, @code{402 -Payment Required} will cause the user agent to pay for the associated proposal. +The TBD is now responsible for taking +all the URL query parameter and use them on the @code{/track/transaction} +request to the backend, see @url{http://api.taler.net/api-merchant.html#get--track-transaction}. +The parameters are the @emph{order_id} and the @emph{instance} (see @ref{Instances}) +of this merchant. +Note that the backend may then request this information from the +exchange, or retrieve it from its own cache if it has already obtained +it. The backend will also check signatures from the exchange, persist +the information obtained, and complain if the exchange ever changes +its facts in an inconsistent manner. -The following headers for @code{402 Payment Required} are recognized by Taler and further influence the processing: -@table @code -@item X-Taler-Refund-Url -If this header present, the value of this header must be a URL that the user agent can use to request and process refunds. +@smallexample +TBD. +@end smallexample + +If the backend returned an HTTP status code @code{202} (Accepted), +this means that the exchange simply did not yet perform the wire +transfer. This is usually the case before @var{pay_deadline}, as the +exchange is waiting for additional opportunities to aggregate transactions. +In this case, we tell the user when to retry this operation later. + +In the @code{foreach} loop, we construct the list of all the +wire transfers which paid back transaction @emph{order_id}. For +simplicity, the list will report only two values: the wire transfer +identifier and the date when the transfer occurred. Nonetheless, +the data returned by the backend contains more information that +can be shown to the user. + +@section Tracking a wire transfer + +To track a wire transfer, the frontend just needs to forward the request +it got from the Web form, to the backend. +Again, the backend may request missing information from the exchange, +verify signatures, persist the result and complain if there are +inconsistencies. + +In the case that the backend detects inconsistencies, an HTTP status +code of @code{402} is returned. In this case, we report this +situation to the user, who should now report this situation to the +exchange's auditors as the exchange is misbehaving. + +In the usual case where everything went fine, we first output the +amount that was supposed to have been transfered under the given +@code{wtid}, and when it was performed (according to the exchange). +Finally, in the @code{foreach} loop, we construct the list of the +order ids paid by the wire transfer: + +@smallexample +TBD. +@end smallexample -@item X-Taler-Contract-Url -If there is no associated proposal, the user agent will fetch a proposal from -this URL and process it. This typically prompts the user to agree to pay. -@item X-Taler-Offer-Url -If there is no associated proposal and @code{X-Taler-Contract-Url} is not -specified, the browser will navigate to this URL. +@node History +@section Listing all transactions -@item X-Taler-User-Tipping-Url -If this header present, the value of this header must be a URL that the user agent can use to obtain tips (small, non-binding -financial rewards) payed from the merchant to the user's wallet. If this field is present, @code{X-Taler-User-Tipping-Exchange} -and @code{X-Taler-User-Tipping-Amount} must also be present. +In order to track transactions, order ids are needed as input. +To that purpose, the frontend needs to make a HTTP GET request to +@code{/history}, which is offered by the backend. -@item X-Taler-User-Tipping-Exchange -Exchange base URL for the exchange that the merchant helps withdrawing the tip from. +The returned data lists the transactions from the youngest back to +the oldest. -@item X-Taler-User-Tipping-Amount -Amount of tip that the user is receiving, in the standard amount format (CURR:X.Y). +The @code{/history} API is actually more rich, as it offers the way +to skim results based on time or on index, but that goes beyond the +scope of this tutorial. -@end table +Our example frontend implements this feature by orchestrating two +parts: -@node JavaScript API -@section JavaScript API +@itemize +@item A JavaScript function, imported within @code{backoffice.html}, + that issues the HTTP GET to TBD + and modifies the current page by adding a table showing the result. +@item The TBD, which is in charge of serving the request + coming from the JavaScript. Its task is to relay that request to the + backend, and echo the result back. +@end itemize -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}. +See below both parts: -@table @code -@item onPresent(callback: () => void) -Add a callback to be called when support for Taler payments is detected. +@smallexample +TBD +@end smallexample -@item onAbsent(callback: () => void) -Add a callback to be called when support for Taler payments is disabled. +@smallexample +TBD +@end smallexample -@item pay(@{contract_url: string, offer_url: string@}) -Results in the same action as a @code{402 Payment Required} with @code{contract_url} in -the @code{X-Taler-Contract-Url} header and @code{offer_url} in the @code{X-Taler-Payment-Url} header. -@item refund(refund_url: string) -Results in the same action as a @code{402 Payment Required} with @code{refund_url} in -the @code{X-Taler-Refund-Url} header. -@end table +@node Advanced topics +@chapter Advanced topics -@node Stylesheet-based presence detection -@section Stylesheet-based presence detection +@menu +* Detecting the presence of the Taler wallet:: Detecting the presence of the Taler wallet +* The Taler proposal format:: The Taler proposal format +@c * Inline proposals:: Sending proposals with the HTTP header +* Instances:: Instances +* The fulfillment page:: The fulfillment page +* Normalized base URLs:: Normalized base URLs +@end menu -Stylesheet-based presence detection will be applied on all pages that have the -@code{data-taler-nojs} attribute of the @code{html} element set @code{true}. -The default/fallback stylesheet, that will be taken over by the wallet once -installed, must be included with the id @code{taler-presence-stylesheet}, like -this: +@include ../../common/texi/wallet-detection.texi +@include ../../common/texi/proposals.texi +@c @include inline-proposals.texi -- not yet written for Python! +@include ../../common/texi/instances.texi +@include ../../common/texi/fulfillment-page.texi +@include ../../common/texi/normalized-base-url.texi -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 +@c ************ Reference chapter *********** +@include ../../common/texi/api-reference.texi @@ -598,13 +654,13 @@ If the wallet is not installed, @code{display} will be @code{none}. @unnumbered GNU-LGPL @cindex license @cindex LGPL -@include lgpl.texi +@include ../../common/texi/lgpl.texi @node GNU-FDL @unnumbered GNU-FDL @cindex license @cindex GNU Free Documentation License -@include fdl-1.3.texi +@include ../../common/texi/fdl-1.3.texi @node Concept Index @unnumbered Concept Index |