From e75db5acf7db8bf51d5e5e0ea7c6c19652432b89 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Thu, 20 Aug 2020 17:33:08 +0530 Subject: add example --- design-documents/007-payment.rst | 76 +++++++++++++++++++++++++++++++++------- 1 file changed, 64 insertions(+), 12 deletions(-) (limited to 'design-documents/007-payment.rst') diff --git a/design-documents/007-payment.rst b/design-documents/007-payment.rst index 83cf01e2..d57fbed9 100644 --- a/design-documents/007-payment.rst +++ b/design-documents/007-payment.rst @@ -38,25 +38,25 @@ Storefront When *resource-URL* is requested, the storefront runs the following steps: 1. Extract the *resource name* from the *resource-URL*. -2. Extract the *order-ID* and *session-ID* (or null) from the request's validated cookie (for example, by using signed cookies). -3. If *session-ID* and *order-ID* are valid and the storefront's - *session-payment-cache* contains the tuple (*order-ID*, *resource-name*, *session-ID*), - return to the client the resource associated with *resource name*. **Terminate.** -4. If *session-ID* and *order-ID* are invalid, assign a fresh session ID and create a new order for *resource name* by doing a ``POST /private/orders`` to - the merchant backend. Set both in the cookie to be sent with the response. +2. Extract the *session-ID* (or null) from the request's validated cookie (for example, by using signed cookies). +3. Extract the *order-ID* (or null) from the request's ``order_id`` cookie. This cookie may optionally be validated. +4. If *session-ID* or *order-ID* is invalid, assign a fresh session ID and + create a new order for *resource name* by doing a ``POST /private/orders`` + to the merchant backend. Set both in the cookie to be sent with the response. 5. Check the status of the payment for *order-ID* under *session-ID* by doing a ``GET /private/orders/{order-ID}?session_id={session-ID}``. This results in the *order-status*, *refund-amount* and the *client-order-status-URL*. 6. If the *order-status* is paid and *refund-amount* is non-zero, - return to the client a page with an explanation that the payment has been refunded. - If the client has not (fully) obtained the granted refunds yet, show a link to the public order page + return to the client a page with an explanation that the payment has been refunded. **Terminate.** +7. If the client has not (fully) obtained the granted refunds yet, show a link to the public order page of the backend to allow the client to obtain the refund. **Terminate.** -7. If the *order-status* is paid, store the tuple (*order-ID*, *resource-name*, *session-ID*) in *session-payment-cache* - and return to the client the resource associated with *resource name*. **Terminate.** -8. Otherwise, the *order-status* is unpaid. Redirect the client to *client-order-status-URL*. **Terminate.** +8. If the *order-status* is paid, return to the client the resource associated with *resource name*. **Terminate.** +9. Otherwise, the *order-status* is unpaid. Redirect the client to *client-order-status-URL*. **Terminate.** .. note:: - The use of a *session-page-cache* is optional, but recommended for performance. When a refund is given, the corresponding tuple must be removed from the *session-page-cache*. + Instead of making a request to the merchant backend on every request to *resource-URL*, the storefront + may use a *session-page-cache* that stores (*session-ID*, *order-ID*, *resource-name*) tuples. + When a refund is given, the corresponding tuple must be removed from the *session-page-cache*. Backend Private Order Status ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -167,6 +167,58 @@ The merchant backend runs the following steps to generate the HTML page for *already-paid-order-ID*. Which of these happens depends on the (long-polled) JSON replies. **Terminate.** +Examples +======== + +The examples use the prefix ``S:`` for the storefront, ``B:`` for the customer's browser +and ``W:`` for the wallet. + +The following example uses a detached wallet: + +.. code:: none + + B: [user nagivates to the book "Moby Dick" in the demo storefront] + B: -> GET https://shop.demo.taler.net/books/moby-dick + (content-type: application/html) + + S: [Assigns session sess01 to browser] + S: -> POST https://merchant-backend.demo.taler.net/orders + S: -> GET https://merchant-backend.demo.taler.net/orders/ord01?session_id-sess01 + + B: <- HTTP 307, redirect to https://merchant-backend.demo.taler.net/orders/ord01?token=ct01&session=sess01 + + B: -> GET https://merchant-backend.demo.taler.net/orders/ord01?token=ct01 + (content-type: application/html) + B: <- HTTP status 402 Payment Required, QR code / link to + taler://pay/shop.demo.taler.net/ord01/sess01?c=ct01 + + B: [via JavaScript on page] + B: -> GET https://merchant-backend.demo.taler.net/orders/ord01?token=ct01&session=sess01 + (content-type: application/json) + B: <- HTTP status 402 Payment Required + + W: [user scans QR taler://pay code] + W: POST https://shop.demo.taler.net/orders/ord01/claim + + B: [via JavaScript on page] + B: -> GET https://merchant-backend.demo.taler.net/orders/ord01?token=ct01&session=sess01 + (content-type: application/json) + B: <- HTTP status 402 Payment Required + + W: POST https://shop.demo.taler.net/orders/ord01/pay + + B: [via JavaScript on page] + B: -> GET https://merchant-backend.demo.taler.net/orders/ord01?token=ct01&session=sess01 + (content-type: application/json) + B: <- HTTP status 202 Accepted + B: [redirects to fulfillment URL of ord01 baked into the JavaScript code] + + B: -> GET https://shop.demo.taler.net/books/moby-dick + (content-type: application/html) + S: -> GET https://merchant-backend.demo.taler.net/orders/ord01?session_id-sess01 + S: <- HTTP 200, order status "paid" + B: <- HTTP 200, content of "moby-dick" is rendered + Discussion / Q&A ================ -- cgit v1.2.3