diff options
author | Marcello Stanisci <marcello.stanisci@inria.fr> | 2016-11-20 23:23:03 +0100 |
---|---|---|
committer | Marcello Stanisci <marcello.stanisci@inria.fr> | 2016-11-20 23:23:03 +0100 |
commit | 1774ca32f629649de8426cee487908ea2ee73e45 (patch) | |
tree | 03ffc925a65f23edc4f146356208dbf00be324b2 /php | |
parent | 739dacd350c3c0d7fa5943fea915b4c87b6a46c5 (diff) | |
parent | fbda1603ef211357537584bc12c4625c6c96e620 (diff) | |
download | merchant-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.php | 100 | ||||
-rw-r--r-- | php/doc/Makefile | 2 | ||||
-rw-r--r-- | php/doc/tutorial.texi | 299 | ||||
-rw-r--r-- | php/helpers.php | 4 |
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×tamp=" - . $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×tamp=" + . $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"}' |