summaryrefslogtreecommitdiff
path: root/php
diff options
context:
space:
mode:
authorMarcello Stanisci <marcello.stanisci@inria.fr>2016-11-20 23:23:03 +0100
committerMarcello Stanisci <marcello.stanisci@inria.fr>2016-11-20 23:23:03 +0100
commit1774ca32f629649de8426cee487908ea2ee73e45 (patch)
tree03ffc925a65f23edc4f146356208dbf00be324b2 /php
parent739dacd350c3c0d7fa5943fea915b4c87b6a46c5 (diff)
parentfbda1603ef211357537584bc12c4625c6c96e620 (diff)
downloadmerchant-frontend-examples-1774ca32f629649de8426cee487908ea2ee73e45.tar.gz
merchant-frontend-examples-1774ca32f629649de8426cee487908ea2ee73e45.tar.bz2
merchant-frontend-examples-1774ca32f629649de8426cee487908ea2ee73e45.zip
Merge branch 'master' of taler.net:merchant-frontend-examples
Diffstat (limited to 'php')
-rw-r--r--php/contract.php100
-rw-r--r--php/doc/Makefile2
-rw-r--r--php/doc/tutorial.texi299
-rw-r--r--php/helpers.php4
4 files changed, 312 insertions, 93 deletions
diff --git a/php/contract.php b/php/contract.php
index 3af5ebf..49760d8 100644
--- a/php/contract.php
+++ b/php/contract.php
@@ -5,42 +5,58 @@
include_once 'helpers.php';
function make_contract($transaction_id, $now){
- $contract = array ('amount' =>
- array ('value' => 1,
- 'fraction' => 0,
- 'currency' => $GLOBALS['CURRENCY']),
- 'max_fee' =>
- array ('value' => 0,
- 'fraction' => 50000,
- 'currency' => $GLOBALS['CURRENCY']),
- 'transaction_id' => $transaction_id,
- 'products' => array (
- array ('description' => "Donation to charity program",
- 'quantity' => 1,
- 'price' =>
- array ('value' => 1,
- 'fraction' => 0,
- 'currency' => $GLOBALS['CURRENCY']),
- 'product_id' => 0,
- 'taxes' => array(),
- 'delivery_date' => "/Date(" . $now->getTimestamp() . ")/",
- 'delivery_location' => 'LNAME1')),
- 'summary' => "Personal donation to charity program",
- 'timestamp' => "/Date(" . $now->getTimestamp() . ")/",
- 'fulfillment_url' => url_rel("/fulfillment.php?"
- . "transaction_id=$transaction_id&timestamp="
- . $now->getTimestamp()),
- 'repurchase_correlation_id' => '',
- 'pay_deadline' =>
- "/Date(" . $now->add(new DateInterval('P2W'))->getTimestamp() . ")/",
- 'refund_deadline' =>
- "/Date(" . $now->add(new DateInterval('P3M'))->getTimestamp() . ")/",
- 'merchant' =>
- array ('address' => 'LNAME2',
- 'name' => "Charity donation shop",
- 'jurisdiction' => 'LNAME3'),
- 'locations' =>
- array ('LNAME1' =>
+ $contract
+ = array(
+ 'amount' =>
+ array('value' => 1,
+ 'fraction' => 0,
+ 'currency' => $GLOBALS['CURRENCY']),
+ 'max_fee' =>
+ array('value' => 0,
+ 'fraction' => 50000,
+ 'currency' => $GLOBALS['CURRENCY']),
+ 'transaction_id' =>
+ $transaction_id,
+ 'products' =>
+ array(array('description' =>
+ "Donation to charity program",
+ 'quantity' => 1,
+ 'price' =>
+ array ('value' => 1,
+ 'fraction' => 0,
+ 'currency' => $GLOBALS['CURRENCY']),
+ 'product_id' => 0,
+ 'taxes' =>
+ array(),
+ 'delivery_date' =>
+ "/Date(" . $now->getTimestamp() . ")/",
+ 'delivery_location' =>
+ 'LNAME1'
+ )
+ ),
+ 'summary' =>
+ "Personal donation to charity program",
+ 'timestamp' =>
+ "/Date(" . $now->getTimestamp() . ")/",
+ 'fulfillment_url' =>
+ url_rel("/fulfillment.php?"
+ . "transaction_id=$transaction_id&timestamp="
+ . $now->getTimestamp()),
+ 'repurchase_correlation_id' =>
+ '',
+ 'pay_deadline' =>
+ "/Date(" . $now->add(new DateInterval('P2W'))->getTimestamp() . ")/",
+ 'refund_deadline' =>
+ "/Date(" . $now->add(new DateInterval('P3M'))->getTimestamp() . ")/",
+ 'merchant' =>
+ array('address' =>
+ 'LNAME2',
+ 'name' =>
+ "Charity donation shop",
+ 'jurisdiction' =>
+ 'LNAME2'),
+ 'locations' =>
+ array ('LNAME1' =>
array ('country' => 'Test Country 1',
'city' => 'Test City 1',
'state' => 'Test State 1',
@@ -49,7 +65,7 @@
'ZIP code' => 49081,
'street' => 'test street 1',
'street number' => 201),
- 'LNAME2' =>
+ 'LNAME2' =>
array ('country' => 'Test Country 2',
'city' => 'Test City 2',
'state' => 'Test State 2',
@@ -57,14 +73,8 @@
'province' => 'Test Province 2',
'ZIP code' => 49082,
'street' => 'test street 2',
- 'street number' => 202),
- 'LNAME3' =>
- array ('country' => 'Test Country 3',
- 'city' => 'Test City 3',
- 'state' => 'Test State 3',
- 'region' => 'Test Region 3',
- 'province' => 'Test Province 3',
- 'ZIP code' => 49083)));
+ 'street number' => 202)
+ ));
return array ('contract' => $contract);
}
?>
diff --git a/php/doc/Makefile b/php/doc/Makefile
index f5573f2..56e08cd 100644
--- a/php/doc/Makefile
+++ b/php/doc/Makefile
@@ -13,5 +13,5 @@ clean:
rm -f arch.jpg arch.pdf tutorial.html tutorial.pdf
-info_TEXINFOS = manual.texi
+info_TEXINFOS = tutorial.texi
manual_TEXINFOS = version.texi
diff --git a/php/doc/tutorial.texi b/php/doc/tutorial.texi
index 948667b..b201261 100644
--- a/php/doc/tutorial.texi
+++ b/php/doc/tutorial.texi
@@ -211,7 +211,6 @@ while @code{post_to_backend} will send HTTP POST requests.
The given backend code uses a few helper functions from
@code{php/helpers.php}, which should be self-explanatory.
-@c But are not yet! Need to comment the code better!
@section Prompting for payment
@@ -401,91 +400,298 @@ anything goes wrong, the wallet will handle the respective error.
@chapter Integration with the back office
This chapter shows how to implement the back office Web interface.
-Namely, we want to verify if we received a wire transfer in
-relation to a given Taler transaction. We are also interested in the
-opposite direction: which Taler transactions are related to a
-given wire transfer.
-@c FIXME: does the reader know so far that a Taler transaction
-@c is meant to trigger a wire transfer?
-To that regard, the frontend's main task are:
+
+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.
+
+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.
+
+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 gather the input from the user and forward it to the backend
-@item transform the backend response in HTML and return it to the user
+@item
+Allow the back office operator to specify a transaction 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 transaction IDs
+@item
+Allow the back office operator to obtain a list of all transactions.
@end itemize
-We implement the first point with a simple HTML form. For simplicity, we
-have one single page for gathering input data for both tracking directions.
-See below the simple HTML entry page for the back office:
+We implement these with a simple HTML form. For simplicity, we have
+one single page for gathering input data for both tracking directions:
@smallexample
// php/track-input.html
@verbatiminclude ../track-input.html
@end smallexample
-The @code{track-transaction.php} script is now responsible for taking the
-Taler transaction ID given by the user in the @code{tid} field, and using it
-to issue a @code{/track/transaction} REST call to the backend,
-see @code{http://api.taler.net/api-merchant.html#get--track-transaction}. Note that the backend will then request this information
-from the exchange. The reason why we do this extra step through
-the backend is that the frontend is not supposed to perform any
-cryptographic work, and so it relies on the backend for that.
+@c TODO: expand with button to obtain list of all transactions.
+
+
+@section Tracking a transaction
+
+The @code{track-transaction.php} script is now responsible for taking
+the Taler transaction ID given by the user in the @code{tid} field,
+and using it to issue a @code{/track/transaction} request to the
+backend, see
+@url{http://api.taler.net/api-merchant.html#get--track-transaction}.
+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.
@smallexample
// php/track-transaction.php
@verbatiminclude ../track-transaction.php
@end smallexample
-If the backend returned an HTTP status code @code{202}, then the
-exchange did not perform the wire transfer for timing reasons,
-but no errors occurred. We tell the user when to retry this
-operation.
+If the backend returned an HTTP status code @code{202} (Accepted),
+this means that the exchange simply did yet not perform the wire
+transfer. This is usually the case before the @var{refund_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 @code{tid}. 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. Note that the function @code{get_to_backend}
-is shown in the previous chapter.
-
-As of @code{track-transfer.php}, see below the code sample, we
-first check if the user
-submitted all the parameters, and then we forward the request to
-the backend, that in turn will request this information from the
-exchange.
-Note the case when HTTP status code @code{402} is returned: due to
-extra checks that the backend does against the data returned by the
-exchange, the backend detected some inconsistency in the exchange's
-response. Accordingly, we report this situation to the user, who
-should now report this situation to the backend and exchange administrators.
-If instead everything went fine, we first output how much @code{wtid} was
-worth and when it has been performed, and finally in the @code{foreach}
-loop we construct the list of the transaction IDs paid back by @code{wtid}.
+can be shown to the user.
+
+@section Tracking a wire transfer
+
+To track a wire transfer, we first check if the user submitted all the
+required parameters, and then we forward the request 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
+transaction IDs paid by the wire transfer:
@smallexample
@verbatiminclude ../track-transfer.php
@end smallexample
+@section Listing all transactions
+
+FIXME.
+
+
@node Advanced topics
@chapter Advanced topics
-@c FIXME: add menu!
+@menu
+* Presence detection:: Reacting to the presence of a Taler wallet
+* Taler contracts:: Building Taler contracts
+* Inline contracts:: Snding contracts with the HTTP header
+* Payments using JavaScript:: Triggering payments using JavaScript
+* The Fulfillment page:: The rationale behind the fulfillment page design
+@end menu
+
+@node Presence detection
@section Reacting to the presence of a Taler wallet
+@cindex wallet
FIXME.
@c with and without JavaScript!
+@node Taler contracts
@section Building Taler contracts
+@cindex contract
-FIXME.
-@c this should discuss all of the different items in a Taler contract.
+A Taler contract 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 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 transaction_id
+@cindex transaction ID
+Numeric transaction ID, must be in the range @math{[0,2^{51})}.
+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. 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 repurchase_correlation_id
+@cindex repurchase correlation ID
+@c FIXME: explain!!!
+
+@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
+@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 contracts
@section Inlining contracts in HTTP headers
+@cindex optimization
+@cindex contract
In the example in section FIXME, we told the wallet the URL from where
it should fetch the contract. Instead of specifying the contract via
@@ -493,8 +699,10 @@ an URL, it is also possible to inline short contracts directly.
FIXME: explain how.
-
+@node Payments using JavaScript
@section Triggering payments using JavaScript
+@cindex JavaScript
+@cindex payment
In the example in section FIXME, we used a GET request to trigger the
payment. This section describes how we could have instead performed
@@ -519,8 +727,9 @@ parameter to @code{executePayment}.
@end itemize
-
+@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:
diff --git a/php/helpers.php b/php/helpers.php
index 4e7362e..b86b424 100644
--- a/php/helpers.php
+++ b/php/helpers.php
@@ -14,7 +14,7 @@
}
/**
- * Concatenates '$base' and '$path'. Tipically used
+ * Concatenates '$base' and '$path'. Typically used
* to add the path (represented by '$path') to a base URL
* (represented by '$base').
*/
@@ -49,7 +49,7 @@
}
/**
- * Take amount object in Taler format, and converts it
+ * Takes amount object in Taler format, and converts it
* in a human-readable string. NOTE: Taler amounts objects
* come from JSON of the form:
* '{"value" x, "fraction": y, "currency": "CUR"}'