summaryrefslogtreecommitdiff
path: root/php/doc/tutorial.texi
blob: d5e9ba19249a698ab25364ddaa530ab154418c20 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
\input texinfo @c -*-texinfo-*-
@c %**start of header
@setfilename tutorial.info
@include ../../common/texi/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.
@defcodeindex op
@c Combine everything into one index (arbitrarily chosen to be the
@c concept index).
@syncodeindex op cp
@c %**end of header

@copying
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, 2018 Taler Systems SA

@quotation
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
any later version published by the Free Software Foundation; with no
Invariant Sections, with no Front-Cover Texts, and with no Back-Cover
Texts.  A copy of the license is included in the section entitled
``GNU Free Documentation License''.
@end quotation
@end copying
@c If your tutorial is published on paper by the FSF, it should include
@c The standard FSF Front-Cover and Back-Cover Texts, as given in
@c maintain.texi.
@c
@c Titlepage
@c
@titlepage
@title The GNU Taler tutorial for PHP Web shops
@subtitle Version @value{VERSION}
@subtitle @value{UPDATED}
@author Marcello Stanisci (@email{marcello.stanisci@@inria.fr})
@author Christian Grothoff (@email{christian.grothoff@@inria.fr}
@author Florian Dold (@email{florian.dold@@inria.fr})
@page
@vskip 0pt plus 1filll
@insertcopying
@end titlepage

@summarycontents
@contents

@ifnottex
@node Top
@top The GNU Taler tutorial for PHP Web shops
@insertcopying
@end ifnottex

@menu
* Introduction::                          Whom this tutorial is addressed to
* 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


Appendices

* GNU-LGPL::                     The GNU Lesser General Public License says how you
                                 can use the code of libtalermerchant.so in your own projects.
* GNU-FDL::                      The GNU Free Documentation License says how you
                                 can copy and share the documentation of GNU Taler.

Indices

* Concept Index::               Index of concepts and programs.
@end menu


@node Introduction
@chapter Introduction

@section About GNU Taler

GNU Taler is an open protocol for an electronic payment system with a
free software reference implementation.  GNU Taler offers secure, fast
and easy payment processing using well understood cryptographic
techniques.  GNU Taler allows customers to remain anonymous, while
ensuring that merchants can be held accountable by governments.
Hence, GNU Taler is compatible with anti-money-laundering (AML) and
know-your-customer (KYC) regulation, as well as data protection
regulation (such as GDPR).


@section About this tutorial

This tutorial is for Web developers and addresses how to integrate GNU
Taler with Web shops. It describes how to create a Web shop that
processes payments with the help of a GNU Taler merchant
@emph{backend}.  In the second chapter, you will learn how to trigger
the payment process from the Web site, how to communicate with the
backend, how to generate a order and process the payment.  The
third chapter covers the integration of a back office with the
backend, which includes tracking payments for orders, matching
payments to orders, and persisting and retrieving contracts.

@cindex examples
@cindex git
You can download all of the code examples given in this tutorial from
@url{https://git.taler.net/merchant-frontend-examples.git/tree/php/}.


@section Architecture overview

The Taler software stack for a merchant consists of the following
main components:

@itemize
@cindex frontend
@item A frontend which interacts with the customer's browser. The
  frontend enables the customer to build a shopping cart and place
  an order.  Upon payment, it triggers the respective business logic
  to satisfy the order.  This component is not included with Taler,
  but rather assumed to exist at the merchant. This tutorial
  describes how to develop a Taler frontend.
@cindex back office
@item A back office application that enables the shop operators to
  view customer orders, match them to financial transfers, and possibly
  approve refunds if an order cannot be satisfied.  This component is
  again not included with Taler, but rather assumed to exist at the
  merchant. This tutorial will describe how to integrate such a component
  to handle payments managed by Taler.  Such integration is shown by
  adding the back office functionality to the frontend implemented
  in the second part of this tutorial.
@cindex backend
@item A Taler-specific payment backend which makes it easy for the
  frontend to process financial transactions with Taler.  For this
  tutorial, you will use a public backend, but for a production
  deployment a merchant-specific backend will need to be setup
  by a system administrator.
@end itemize

The following image illustrates the various interactions of these
key components:

@image{arch, 3in, 4in}


The backend provides the cryptographic protocol support,
stores Taler-specific financial information and communicates
with the GNU Taler exchange over the Internet.  The frontend accesses
the backend via a RESTful API.  As a result, the frontend never has to
directly communicate with the exchange, and also does not deal with
sensitive data.  In particular, the merchant's signing keys and bank
account information are encapsulated within the Taler backend.

@node Setting up a simple donation page
@chapter Setting up a simple donation page

This section describes how to setup a simple shop, which exposes a
button to get donations via Taler. The expected behaviour is that once
the ``donate'' button is clicked, the customer will receive a Taler
*proposal* offering him the opportunity to make a fixed donation,
for example to donate 1 KUDOS to the charity operating the shop.

All the code samples shown below in the tutorial can be found at
@url{https://git.taler.net/merchant-frontend-examples.git/tree/php}.

@c NOTE: include explaining wallet installation to Web developer here!

@c Next sentence is inconsistent with Python version. Why?
Note that if the customer does not have the Taler wallet installed,
they should instead be prompted to proceed with a classic dialog for
credit card payments.


@section Specifying the backend

@cindex backend
@cindex configuration
@cindex currency
For many critical operations, the frontend needs to communicate
with a Taler backend.  Assuming that you do not yet have a backend
configured, you can use the public backend provided by the Taler
project for testing.  This public backend has been set-up at
@code{http://backend.demo.taler.net/} specifically for testing
frontends.  It uses the currency ``KUDOS'' and all payments will
go into the ``Tutorial'' account at the Taler ``bank'' running at
@code{https://bank.demo.taler.net/public-accounts}.

To point the frontend being developed in this tutorial to some
backend, it suffices to set the variable @code{$BACKEND} in
@code{php/config.php} to the desired backend's base URL.  You also
need to specify the currency used by the backend.  For example:

@smallexample
// php/config.php
@verbatiminclude ../config.php
@end smallexample


@section Talking to the backend

@cindex backend
Given the above configuration, we can now implement two simple
functions @code{get_to_backend} and @code{post_to_backend} to
send requests to the backend.  The function @code{get_to_backend}
is in charge of performing HTTP GET requests to the backend,
while @code{post_to_backend} will send HTTP POST requests.

@smallexample
// php/backend.php
@verbatiminclude ../backend.php
@end smallexample

The given @code{backend.php} code uses a few helper functions from
@code{php/helpers.php}, which should be self-explanatory.


@node Prompting for payment
@section Prompting for payment

@cindex button
Our goal is to trigger a Taler payment once the customer has clicked
on a donation button.  We will use a button that issues an HTTP GET
to the frontend @code{/donate.php} URL.  For this, the HTML would be as
follows:

@smallexample
// php/index.html
@verbatiminclude ../index.html
@end smallexample

When the server-side handler for @code{/donate.php} receives the form submission,
it will return a HTML page that will take care of:

@itemize
@item showing a credit card paywall to the user if no wallet is found, and
@item fetching a Taler proposal and passing it to the wallet if one is found
@end itemize

A minimalistic @code{donate.php} implementation is shown below (in PHP):

@cindex pay handler
@cindex 402
@cindex X-Taler-Contract-Url
@smallexample
// php/donate.php
@verbatiminclude ../donate.php
@end smallexample

Given this response, the Taler wallet will fetch the proposal from
@url{/generate-order.php} and display it to the user.

If the wallet is not present, the HTML body will be shown and the
Taler headers and the 402 status code ought to be ignored by the
browser.

@section A helper function to generate the order

We make distinction between @emph{three} different stages of what it
informally called "contract".

In a very first stage, we call it the @emph{order}: that occurs when
the frontend generates the first JSON that misses some information
that the backend is supposed to add.  When the backend completes the
order and signs it, we have a @emph{proposal}.  The proposal is what
the user is prompted with, and allows them to confirm the purchase.
Once the user confirms the purchase, the wallet makes a signature over
the proposal, turning it into a @emph{contract}.

We first define a helper function @code{make_order} that will
generate a complete Taler order as a nested PHP array.  The
function takes only the order ID and the timestamp as arguments;
all of the other details of the order are hardcoded in this simple
example.

The following code generate a order about donating 1 KUDOS to the
'Taler charity program':

@cindex contract
@smallexample
// php/order.php
@verbatiminclude ../order.php
@end smallexample


@section Signing and returning the proposal

The server-side handler for @code{/generate-order.php} has to call
@code{make_order} and then POST the result to the backend at
@code{/proposal}.  By POSTing the order to the backend we get a
cryptographic signature over its contents.  The result is then
returned to the wallet.

A simple @code{/generate-order.php} handler may thus look like this:

@cindex signature
@cindex backend
@cindex order
@smallexample
// php/generate-order.php
@verbatiminclude ../generate-order.php
@end smallexample

@c FIXME: improve example to do this right?
Note that in practice the frontend might want to generate a monotonically
increasing series of order IDs to avoid a chance of collisions.
Order IDs must be in the range of @math{[0:2^{51})}.

@section Handling errors

In the above example, the helper function @code{build_error} is
used to generate an error response in the case that the backend
somehow failed to respond properly to our request.

The function @code{build_error} is shown below, it returns JSON data
matching a particular format for reporting errors,
see @code{http://api.taler.net/api-common.html#errordetail}:

@smallexample
@c FIXME, build_error() doesn't respect error-reporting format yet!
// php/error.php
@verbatiminclude ../error.php
@end smallexample


@node Initiating the payment process
@section Initiating the payment process

@cindex fulfillment URL
After the browser has fetched the proposal, the user will be
given the opportunity to affirm the payment.  Assuming the user
affirms, the browser will navigate to the ``fulfillment_url'' that
was specified in the proposal.

The fulfillment page can be called by users that have already paid for
the item, as well as by users that have not yet paid at all.  The
fulfillment page must thus use the HTTP session state to detect if the
payment has been performed already, and if not request payment from
the wallet.

For our example, the fulfillment URL will contain the order id of
the donation, like in the following example:

@smallexample
https://shop.com/fulfillment.php?order_id=<ORDER_ID>
@end smallexample

The fulfillment handler at @code{/fulfillment.php} will use this information
to check if the user has already paid, and if so confirm the donation.
If the user has not yet paid, it will instead return another ``402 Payment
Required'' header, requesting the wallet to pay:

@smallexample
// php/fulfillment.php
@verbatiminclude ../fulfillment.php
@end smallexample

@cindex 402 payment required
Here, this second 402 response contains the following Taler-specific
headers:

@table @code
@item X-Taler-Contract-Url
@cindex X-Taler-Contract-Url
The URL that generated the proposal that led to this payment.
The wallet may need to reconstruct the proposal.
@item X-Taler-Contract-Query
@cindex X-Taler-Contract-Query
The way the wallet should lookup for replayable payments.
NOTE that for each payment done, the wallet stores the coins it
spent for it in an internal database. And each set of used coins
is associated to the fulfillment page where they have been spent.
So whenever an already known fulfillment page requests a payment,
the wallet will pick those coins it spent on that fulfillment
page and resend them (therefore @emph{replaying} the payment).
In other words, new coins are used only on unknown fulfillment
pages.
This header is supposed to be removed in future versions of the
wallet though, as it only works with the value @code{"fulfillment_url"}.
@item X-Taler-Offer-Url
@cindex X-Taler-Offer-Url
In case that the wallet does not know about this payment already,
i.e. because a user shared the URL with another user, this tells the
wallet where to go to retrieve a fresh offer.
@end table

@section Receiving payments via Taler

The final next step for the frontend is to accept the payment from the
wallet.  For this, the frontend must implement a payment handler at
the URI specified in the @code{pay_url} proposal field, as explained
above.

The role of the @code{/pay.php} handler is to receive the payment
from the wallet and forward it to the backend.  If the backend
reports that the payment was successful, the handler needs to update
the session state with the browser to remember that the user paid.

The following code implements this in PHP:

@smallexample
// php/pay.php
@verbatiminclude ../pay.php
@end smallexample

Do not be confused by the @code{isset} test for the session state.  In
our simple example, it will be set to ``false'' by the fulfillment URL
which the browser actually always visits first.

After the @code{pay.php} handler has affirmed that the payment was
successful, the wallet will refresh the fulfillment page, this
time receiving the message that the donation was successful.  If
anything goes wrong, the wallet will handle the respective error.

@node Back-office-integration
@chapter Integration with the back office

Taler ships the back-office feature as a stand-alone Web application.
See how to run it, on its own documentaion: @url{https://docs.taler.net/backoffice/html/manual.html}.


@node Advanced topics
@chapter Advanced topics

@menu
* Detecting the presence of the Taler wallet::  Detecting the presence of the Taler wallet
* The Taler proposal format::                   The Taler proposal format
* Instances::                                   Instances
* The fulfillment page::                        The fulfillment page
* Normalized base URLs::                        Normalized base URLs
@end menu

@include ../../common/texi/wallet-detection.texi
@include ../../common/texi/proposals.texi
@include ../../common/texi/instances.texi
@include ../../common/texi/fulfillment-page.texi
@include ../../common/texi/normalized-base-url.texi


@c ************ Reference chapter ***********
@include ../../common/texi/api-reference.texi

@c **********************************************************
@c *******************  Appendices  *************************
@c **********************************************************

@node GNU-LGPL
@unnumbered GNU-LGPL
@cindex license
@cindex LGPL
@include ../../common/texi/lgpl.texi

@node GNU-FDL
@unnumbered GNU-FDL
@cindex license
@cindex GNU Free Documentation License
@include ../../common/texi/fdl-1.3.texi

@node Concept Index
@unnumbered Concept Index

@printindex cp

@bye