major edits of pay process

This commit is contained in:
Christian Grothoff 2016-08-26 15:32:27 +02:00
parent 1a6f39f407
commit f0b08e6b4c

View File

@ -825,9 +825,12 @@ X-Taler-Contract-Url: https://shop/generate-contract/42
\label{listing:http-contract}
\end{figure*}
\subsubsection{Offer}
The offer URL of the Web shop can then initiate payments by sending a
\emph{contract proposal} (Figure~\ref{listing:json-contract}) to the wallet, either via the HTTP status
code {\tt 402 Payment Required} (Figure~\ref{listing:http-contract}), or via Taler's JavaScript API
\emph{contract proposal} (Figure~\ref{listing:json-contract}) to the
wallet, either via the HTTP status code {\tt 402 Payment Required}
(Figure~\ref{listing:http-contract}), or via Taler's JavaScript API
(Figure~\ref{listing:contract}). The wallet then presents the
contract to the user. The format of the contract is in an extensible
JSON-based format defined by Taler and not HTML, as the rendering of
@ -836,16 +839,6 @@ representation of the terms and prices. In case that transaction fees
need to be covered by the customer, these are shown together with the
rest of the proposed contract.
If the customer approves the contract by clicking the ``Confirm
Payment'' button (Figure~\ref{subfig:payment}), their wallet signs the
contract with enough coins to cover the contract's cost, stores all of
the information in its local database, and transmits the payment to
the {\em payment} URI of the Web shop. Once the Web shop confirms the
payment, the wallet redirects the browser to the {\em fulfillment} URL
provided by the merchant (Figure~\ref{subfig:fulfillment}).
\subsection{Browser security}
The Taler wallet operates from a securely isolated {\em background}
context on the client side. The user interface that displays the
contract and allows the user to confirm the payment is displayed by
@ -857,44 +850,62 @@ wallet's payment page (Figure~\ref{subfig:payment}), as such a page
would still not have access to the private keys of the coins that are
exclusive to the background context.
%The current Taler specification is written to accommodate for
%the rather restrictive set of APIs that WebExtension, a
%cross-browser extension API, provides.
If the customer approves the contract by clicking the ``Confirm
Payment'' button (Figure~\ref{subfig:payment}), their wallet signs the
contract with enough coins to cover the contract's cost, stores all of
the information in its local database, and redirects the browser to
the {\em fulfillment} URL provided by the merchant in the contract
(Figure~\ref{subfig:fulfillment}).
\subsection{Managing browser session state}
\subsubsection{Fulfillment}
% FIXME: this is where we probably want to revise quite a bit,
% including improving the description AND addressing the JS-less
% implementation.
The fulfillment URL uniquely identifies a purchase by some customer,
while the offer URL identifies a generic offer that is not specific to
a customer. The purchase identified by a fulfillment URL may have
been completed or still be in progress. The information contained in
the fulfillment URL must allow the merchant to restore the full
contract (including a unique transaction identifier) that was
associated with the purchase, either directly from the URL or
indirectly from an identifier in a database. Efficiently
reconstructing the contract entirely from the URL instead of using
costly database transactions can be important, as costly disk
operations for incomplete purchases make merchants more susceptible to
denial-of-service attacks from adversaries pretending to be customers.
% Say that this doesn't require accounts!
% explain that HTTP session state can be restored
% from the wallet state (replay!)
When a customer has completed a purchase, navigating to the
fulfillment URL in a browser will show the resource associated with
the purchase. This resource can be a digital good such as a news
article, or simply a confirmation for products that are delivered by
other means.
% explain repurchase correlation ID
When a customer has not yet completed a purchase (this is always the
case when a customer visits the fulfillment URL for the first time),
or when the Web shop cannot confirm that this visitor has paid for the
contract, for example because the session state was
lost,\footnote{This can happen when when privacy conscious users
delete their cookies. Also, some user agents (such as the TOR
browser) do not support persistent (non-session) cookies.} the Web
store responds by (again) triggering a payment process (either via
JavaScript or using {\tt 402 Payment Required}, see
Figure~\ref{listing:http-execute}). However, unlike the response from
the offer URL, the 402 response from the fulfillment page includes the
headers {\tt X-Taler-Contract-Hash}, {\tt X-Taler-Pay-Url} and {\tt
X-Taler-Offer-Url}.
% contract vs complete fulfillment URL
If the contract hash matches a payment which the user already
previously approved, the wallet reacts to this by injecting the logic
to transmit the payment to the {\em pay} URL of the Web shop into
the page. Then the wallet inspects the response as it may contain
error reports about a failed payment which the wallet has to handle.
By submitting the payment this way, we also ensure that this
intermediate request does not require JavaScript and still does not
interfer with navigation. Once the Web shop confirms the payment, the
wallet causes the fulfillment URL to be reloaded.
% design that allows merchant to not store any information
A purchase by a customer, completed or in progress, is uniquely
identified by a URL, called the \emph{fulfillment URL}. The
information contained in the fulfillment URL must allow the merchant
to restore the full contract that was associated with the purchase,
either directly from the URL or indirectly from an identifier in a
database. Efficiently reconstructing the contract entirely from the
URL instead of using costly database transactions can be important, as
costly disk operations for incomplete purchases make merchants
more susceptible to denial-of-service attacks from adversaries
pretending to be customers.
When a customer completed a purchase, navigating to the fulfillment
URL in a browser will show the resource associated with the purchase.
This resource can be a digital good such as a news article, or simply
a confirmation for products that are delivered by other means.
% FIXME: maybe we should have the URL that we are requesting
% in the example, and not just the response?
If the contract hash does not match a payment which the user
already approved, for example because the user obtained the link
from another user, the wallet navigates to the offer URL included
in the header.
\begin{figure*}[t!]
\lstset{language={}}
@ -922,41 +933,7 @@ X-Taler-Offer-Url: https://shop/generate-contract/42
\label{listing:http-execute}
\end{figure*}
In order to ensure that only the paying customer has access to the Web
resources behind the fulfillment URL, the Web store's server must
check the browser's session state. If the merchant can confirm that
the visitor has paid, the respective Web resource is returned. If the
merchant cannot confirm that the visitor has paid for the contract,
for example because the session state was lost,\footnote{This can
happen when when privacy conscious users delete their cookies.
Also, some user agents (such as the TOR browser) do not support
persistent (non-session) cookies.} it {\em again} triggers a payment
process (either via JavaScript or using {\tt 402 Payment Required}, see Figure~\ref{listing:http-execute}).
Since the fulfillment URL refers to a contract that typically is already known
to the user's wallet, it suffices to pass the contract hash (instead of
full contract) to the wallet.
If the user previously approved paying for the contract with this hash, the
wallet will (re-)transmit the signed coins that are associated
with the contract to the merchant.
When a user visits a fulfillment URL without having the associated
contract in their wallet, the wallet redirects the browser to the {\em
offer} URL for that purchase, if applicable. This behavior is
useful when a user wishes to share a fulfillment link with another
user to point him to the same resource.
Note that due to the limited WebExtensions API, the session state can
only be acquired when the wallet causes the browser to navigate to the
fulfillment URL (first without session state), since the session state
must be set from the same origin as the fulfillment URL. As a result,
the shop cannot simply return the fulfillment information in response
to the wallet performing the payment. However, this extra round trip
is also justified as the wallet needs to inspect the response anyway
as it may contain error reports about a failed payment which the wallet
has to handle. Finally, it ensures that the fulfillment page is fetched
via an HTTP GET request instead of an HTTP POST request, which is
important to nicely support the use of navigation (``back'', ``forward''
buttons) and bookmarks.
\subsubsection{Discussion}
Various failure modes are considered in this design: