tutorial.texi (16742B)
1 \input texinfo @c -*-texinfo-*- 2 @c %**start of header 3 @setfilename tutorial.info 4 @include ../../common/texi/version.texi 5 @include ../../common/texi/syntax.texi 6 @settitle The GNU Taler tutorial for PHP Web shop developers @value{VERSION} 7 8 @c Define a new index for options. 9 @defcodeindex op 10 @c Combine everything into one index (arbitrarily chosen to be the 11 @c concept index). 12 @syncodeindex op cp 13 @c %**end of header 14 15 @copying 16 This tutorial is about implementing a merchant frontend to run against a 17 GNU Taler merchant backend (version @value{VERSION}, @value{UPDATED}), 18 19 Copyright @copyright{} 2016, 2017, 2018 Taler Systems SA 20 21 @quotation 22 Permission is granted to copy, distribute and/or modify this document 23 under the terms of the GNU Free Documentation License, Version 1.3 or 24 any later version published by the Free Software Foundation; with no 25 Invariant Sections, with no Front-Cover Texts, and with no Back-Cover 26 Texts. A copy of the license is included in the section entitled 27 ``GNU Free Documentation License''. 28 @end quotation 29 @end copying 30 @c If your tutorial is published on paper by the FSF, it should include 31 @c The standard FSF Front-Cover and Back-Cover Texts, as given in 32 @c maintain.texi. 33 @c 34 @c Titlepage 35 @c 36 @titlepage 37 @title The GNU Taler tutorial for PHP Web shops 38 @subtitle Version @value{VERSION} 39 @subtitle @value{UPDATED} 40 @author Marcello Stanisci (@email{marcello.stanisci@@inria.fr}) 41 @author Christian Grothoff (@email{christian.grothoff@@inria.fr} 42 @author Florian Dold (@email{florian.dold@@inria.fr}) 43 @page 44 @vskip 0pt plus 1filll 45 @insertcopying 46 @end titlepage 47 48 @summarycontents 49 @contents 50 51 @ifnottex 52 @node Top 53 @top The GNU Taler tutorial for PHP Web shops 54 @insertcopying 55 @end ifnottex 56 57 @menu 58 * Introduction:: Whom this tutorial is addressed to 59 * Setting up a simple donation page:: How to set up a donation page 60 * Back-office-integration:: How to integrate with the back office 61 * Advanced topics:: Detailed solutions to specific issues 62 * Reference:: Merchant integration reference 63 64 65 Appendices 66 67 * GNU-LGPL:: The GNU Lesser General Public License says how you 68 can use the code of libtalermerchant.so in your own projects. 69 * GNU-FDL:: The GNU Free Documentation License says how you 70 can copy and share the documentation of GNU Taler. 71 72 Indices 73 74 * Concept Index:: Index of concepts and programs. 75 @end menu 76 77 78 @node Introduction 79 @chapter Introduction 80 81 @section About GNU Taler 82 83 GNU Taler is an open protocol for an electronic payment system with a 84 free software reference implementation. GNU Taler offers secure, fast 85 and easy payment processing using well understood cryptographic 86 techniques. GNU Taler allows customers to remain anonymous, while 87 ensuring that merchants can be held accountable by governments. 88 Hence, GNU Taler is compatible with anti-money-laundering (AML) and 89 know-your-customer (KYC) regulation, as well as data protection 90 regulation (such as GDPR). 91 92 93 @section About this tutorial 94 95 This tutorial is for Web developers and addresses how to integrate GNU 96 Taler with Web shops. It describes how to create a Web shop that 97 processes payments with the help of a GNU Taler merchant 98 @emph{backend}. In the second chapter, you will learn how to trigger 99 the payment process from the Web site, how to communicate with the 100 backend, how to generate a order and process the payment. The 101 third chapter covers the integration of a back office with the 102 backend, which includes tracking payments for orders, matching 103 payments to orders, and persisting and retrieving contracts. 104 105 @cindex examples 106 @cindex git 107 You can download all of the code examples given in this tutorial from 108 @url{https://git.taler.net/merchant-frontend-examples.git/tree/php/}. 109 110 111 @section Architecture overview 112 113 The Taler software stack for a merchant consists of the following 114 main components: 115 116 @itemize 117 @cindex frontend 118 @item A frontend which interacts with the customer's browser. The 119 frontend enables the customer to build a shopping cart and place 120 an order. Upon payment, it triggers the respective business logic 121 to satisfy the order. This component is not included with Taler, 122 but rather assumed to exist at the merchant. This tutorial 123 describes how to develop a Taler frontend. 124 @cindex back office 125 @item A back office application that enables the shop operators to 126 view customer orders, match them to financial transfers, and possibly 127 approve refunds if an order cannot be satisfied. This component is 128 again not included with Taler, but rather assumed to exist at the 129 merchant. This tutorial will describe how to integrate such a component 130 to handle payments managed by Taler. Such integration is shown by 131 adding the back office functionality to the frontend implemented 132 in the second part of this tutorial. 133 @cindex backend 134 @item A Taler-specific payment backend which makes it easy for the 135 frontend to process financial transactions with Taler. For this 136 tutorial, you will use a public backend, but for a production 137 deployment a merchant-specific backend will need to be setup 138 by a system administrator. 139 @end itemize 140 141 The following image illustrates the various interactions of these 142 key components: 143 144 @image{arch, 3in, 4in} 145 146 147 The backend provides the cryptographic protocol support, 148 stores Taler-specific financial information and communicates 149 with the GNU Taler exchange over the Internet. The frontend accesses 150 the backend via a RESTful API. As a result, the frontend never has to 151 directly communicate with the exchange, and also does not deal with 152 sensitive data. In particular, the merchant's signing keys and bank 153 account information are encapsulated within the Taler backend. 154 155 @node Setting up a simple donation page 156 @chapter Setting up a simple donation page 157 158 This section describes how to setup a simple shop, which exposes a 159 button to get donations via Taler. The expected behaviour is that once 160 the ``donate'' button is clicked, the customer will receive a Taler 161 *proposal* offering him the opportunity to make a fixed donation, 162 for example to donate 1 KUDOS to the charity operating the shop. 163 164 All the code samples shown below in the tutorial can be found at 165 @url{https://git.taler.net/merchant-frontend-examples.git/tree/php}. 166 167 @c NOTE: include explaining wallet installation to Web developer here! 168 169 @c Next sentence is inconsistent with Python version. Why? 170 Note that if the customer does not have the Taler wallet installed, 171 they should instead be prompted to proceed with a classic dialog for 172 credit card payments. 173 174 175 @section Specifying the backend 176 177 @cindex backend 178 @cindex configuration 179 @cindex currency 180 For many critical operations, the frontend needs to communicate 181 with a Taler backend. Assuming that you do not yet have a backend 182 configured, you can use the public backend provided by the Taler 183 project for testing. This public backend has been set-up at 184 @code{http://backend.demo.taler.net/} specifically for testing 185 frontends. It uses the currency ``KUDOS'' and all payments will 186 go into the ``Tutorial'' account at the Taler ``bank'' running at 187 @code{https://bank.demo.taler.net/public-accounts}. 188 189 To point the frontend being developed in this tutorial to some 190 backend, it suffices to set the variable @code{$BACKEND} in 191 @code{php/config.php} to the desired backend's base URL. You also 192 need to specify the currency used by the backend. For example: 193 194 @smallexample 195 // php/config.php 196 @verbatiminclude ../config.php 197 @end smallexample 198 199 200 @section Talking to the backend 201 202 @cindex backend 203 Given the above configuration, we can now implement two simple 204 functions @code{get_to_backend} and @code{post_to_backend} to 205 send requests to the backend. The function @code{get_to_backend} 206 is in charge of performing HTTP GET requests to the backend, 207 while @code{post_to_backend} will send HTTP POST requests. 208 209 @smallexample 210 // php/backend.php 211 @verbatiminclude ../backend.php 212 @end smallexample 213 214 The given @code{backend.php} code uses a few helper functions from 215 @code{php/helpers.php}, which should be self-explanatory. 216 217 218 @node Prompting for payment 219 @section Prompting for payment 220 221 @cindex button 222 Our goal is to trigger a Taler payment once the customer has clicked 223 on a donation button. We will use a button that issues an HTTP GET 224 to the frontend @code{/donate.php} URL. For this, the HTML would be as 225 follows: 226 227 @smallexample 228 // php/index.html 229 @verbatiminclude ../index.html 230 @end smallexample 231 232 When the server-side handler for @code{/donate.php} receives the form submission, 233 it will return a HTML page that will take care of: 234 235 @itemize 236 @item showing a credit card paywall to the user if no wallet is found, and 237 @item fetching a Taler proposal and passing it to the wallet if one is found 238 @end itemize 239 240 A minimalistic @code{donate.php} implementation is shown below (in PHP): 241 242 @cindex pay handler 243 @cindex 402 244 @cindex X-Taler-Contract-Url 245 @smallexample 246 // php/donate.php 247 @verbatiminclude ../donate.php 248 @end smallexample 249 250 Given this response, the Taler wallet will fetch the proposal from 251 @url{/generate-order.php} and display it to the user. 252 253 If the wallet is not present, the HTML body will be shown and the 254 Taler headers and the 402 status code ought to be ignored by the 255 browser. 256 257 @section A helper function to generate the order 258 259 We make distinction between @emph{three} different stages of what it 260 informally called "contract". 261 262 In a very first stage, we call it the @emph{order}: that occurs when 263 the frontend generates the first JSON that misses some information 264 that the backend is supposed to add. When the backend completes the 265 order and signs it, we have a @emph{proposal}. The proposal is what 266 the user is prompted with, and allows them to confirm the purchase. 267 Once the user confirms the purchase, the wallet makes a signature over 268 the proposal, turning it into a @emph{contract}. 269 270 We first define a helper function @code{make_order} that will 271 generate a complete Taler order as a nested PHP array. The 272 function takes only the order ID and the timestamp as arguments; 273 all of the other details of the order are hardcoded in this simple 274 example. 275 276 The following code generate a order about donating 1 KUDOS to the 277 'Taler charity program': 278 279 @cindex contract 280 @smallexample 281 // php/order.php 282 @verbatiminclude ../order.php 283 @end smallexample 284 285 286 @section Signing and returning the proposal 287 288 The server-side handler for @code{/generate-order.php} has to call 289 @code{make_order} and then POST the result to the backend at 290 @code{/proposal}. By POSTing the order to the backend we get a 291 cryptographic signature over its contents. The result is then 292 returned to the wallet. 293 294 A simple @code{/generate-order.php} handler may thus look like this: 295 296 @cindex signature 297 @cindex backend 298 @cindex order 299 @smallexample 300 // php/generate-order.php 301 @verbatiminclude ../generate-order.php 302 @end smallexample 303 304 @c FIXME: improve example to do this right? 305 Note that in practice the frontend might want to generate a monotonically 306 increasing series of order IDs to avoid a chance of collisions. 307 Order IDs must be in the range of @math{[0:2^{51})}. 308 309 @section Handling errors 310 311 In the above example, the helper function @code{build_error} is 312 used to generate an error response in the case that the backend 313 somehow failed to respond properly to our request. 314 315 The function @code{build_error} is shown below, it returns JSON data 316 matching a particular format for reporting errors, 317 see @code{http://api.taler.net/api-common.html#errordetail}: 318 319 @smallexample 320 @c FIXME, build_error() doesn't respect error-reporting format yet! 321 // php/error.php 322 @verbatiminclude ../error.php 323 @end smallexample 324 325 326 @node Initiating the payment process 327 @section Initiating the payment process 328 329 @cindex fulfillment URL 330 After the browser has fetched the proposal, the user will be 331 given the opportunity to affirm the payment. Assuming the user 332 affirms, the browser will navigate to the ``fulfillment_url'' that 333 was specified in the proposal. 334 335 The fulfillment page can be called by users that have already paid for 336 the item, as well as by users that have not yet paid at all. The 337 fulfillment page must thus use the HTTP session state to detect if the 338 payment has been performed already, and if not request payment from 339 the wallet. 340 341 For our example, the fulfillment URL will contain the order id of 342 the donation, like in the following example: 343 344 @smallexample 345 https://shop.com/fulfillment.php?order_id=<ORDER_ID> 346 @end smallexample 347 348 The fulfillment handler at @code{/fulfillment.php} will use this information 349 to check if the user has already paid, and if so confirm the donation. 350 If the user has not yet paid, it will instead return another ``402 Payment 351 Required'' header, requesting the wallet to pay: 352 353 @smallexample 354 // php/fulfillment.php 355 @verbatiminclude ../fulfillment.php 356 @end smallexample 357 358 @cindex 402 payment required 359 Here, this second 402 response contains the following Taler-specific 360 headers: 361 362 @table @code 363 @item X-Taler-Contract-Url 364 @cindex X-Taler-Contract-Url 365 The URL that generated the proposal that led to this payment. 366 The wallet may need to reconstruct the proposal. 367 @item X-Taler-Contract-Query 368 @cindex X-Taler-Contract-Query 369 The way the wallet should lookup for replayable payments. 370 NOTE that for each payment done, the wallet stores the coins it 371 spent for it in an internal database. And each set of used coins 372 is associated to the fulfillment page where they have been spent. 373 So whenever an already known fulfillment page requests a payment, 374 the wallet will pick those coins it spent on that fulfillment 375 page and resend them (therefore @emph{replaying} the payment). 376 In other words, new coins are used only on unknown fulfillment 377 pages. 378 This header is supposed to be removed in future versions of the 379 wallet though, as it only works with the value @code{"fulfillment_url"}. 380 @item X-Taler-Offer-Url 381 @cindex X-Taler-Offer-Url 382 In case that the wallet does not know about this payment already, 383 i.e. because a user shared the URL with another user, this tells the 384 wallet where to go to retrieve a fresh offer. 385 @end table 386 387 @section Receiving payments via Taler 388 389 The final next step for the frontend is to accept the payment from the 390 wallet. For this, the frontend must implement a payment handler at 391 the URI specified in the @code{pay_url} proposal field, as explained 392 above. 393 394 The role of the @code{/pay.php} handler is to receive the payment 395 from the wallet and forward it to the backend. If the backend 396 reports that the payment was successful, the handler needs to update 397 the session state with the browser to remember that the user paid. 398 399 The following code implements this in PHP: 400 401 @smallexample 402 // php/pay.php 403 @verbatiminclude ../pay.php 404 @end smallexample 405 406 Do not be confused by the @code{isset} test for the session state. In 407 our simple example, it will be set to ``false'' by the fulfillment URL 408 which the browser actually always visits first. 409 410 After the @code{pay.php} handler has affirmed that the payment was 411 successful, the wallet will refresh the fulfillment page, this 412 time receiving the message that the donation was successful. If 413 anything goes wrong, the wallet will handle the respective error. 414 415 @node Back-office-integration 416 @chapter Integration with the back office 417 418 Taler ships the back-office feature as a stand-alone Web application. 419 See how to run it, on its own documentaion: @url{https://docs.taler.net/backoffice/html/manual.html}. 420 421 422 @node Advanced topics 423 @chapter Advanced topics 424 425 @menu 426 * Detecting the presence of the Taler wallet:: Detecting the presence of the Taler wallet 427 * The Taler proposal format:: The Taler proposal format 428 * Instances:: Instances 429 * The fulfillment page:: The fulfillment page 430 * Normalized base URLs:: Normalized base URLs 431 @end menu 432 433 @include ../../common/texi/wallet-detection.texi 434 @include ../../common/texi/proposals.texi 435 @include ../../common/texi/instances.texi 436 @include ../../common/texi/fulfillment-page.texi 437 @include ../../common/texi/normalized-base-url.texi 438 439 440 @c ************ Reference chapter *********** 441 @include ../../common/texi/api-reference.texi 442 443 @c ********************************************************** 444 @c ******************* Appendices ************************* 445 @c ********************************************************** 446 447 @node GNU-LGPL 448 @unnumbered GNU-LGPL 449 @cindex license 450 @cindex LGPL 451 @include ../../common/texi/lgpl.texi 452 453 @node GNU-FDL 454 @unnumbered GNU-FDL 455 @cindex license 456 @cindex GNU Free Documentation License 457 @include ../../common/texi/fdl-1.3.texi 458 459 @node Concept Index 460 @unnumbered Concept Index 461 462 @printindex cp 463 464 @bye