[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-docs] 03/03: points for discussion
From: |
gnunet |
Subject: |
[taler-docs] 03/03: points for discussion |
Date: |
Sun, 09 Aug 2020 12:17:01 +0200 |
This is an automated email from the git hooks/post-receive script.
grothoff pushed a commit to branch master
in repository docs.
commit 551739c033f29fd21d6110def4f8ad87615b1b93
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Sun Aug 9 12:16:56 2020 +0200
points for discussion
---
design-documents/007-payment.rst | 100 +++++++++++++++++++++++++++------------
1 file changed, 70 insertions(+), 30 deletions(-)
diff --git a/design-documents/007-payment.rst b/design-documents/007-payment.rst
index 5294103..aacd163 100644
--- a/design-documents/007-payment.rst
+++ b/design-documents/007-payment.rst
@@ -23,6 +23,8 @@ Requirements
Proposed Solution
=================
+
+
Session-bound payment flow for Web resources
--------------------------------------------
@@ -35,103 +37,133 @@ Storefront
When *resource-URL* is requested, the storefront runs the following steps:
1. Extract the the *order-ID* (or null) and *resource name* from the
*resource-URL*.
-2. Extract the *session-ID* (or null) from the request's signed cookie
+2. Extract the *session-ID* (or null) from the request's signed cookie.
+ -------- DISCUSS: 'signed'? Since when are cookies signed???
3. If *session-ID* and *order-ID* is non-null and the storefront's
*session-payment-cache* contains the tuple (*order-ID*, *resource-name*,
*session-ID*),
- return to the client the information for *resource name*. **Terminate.**
-4. If the *session-ID* is null, assign a fresh session ID and set it in a
cookie to be sent with the response
+ return to the client the resource associated with *resource name*.
**Terminate.**
+4. If the *session-ID* is null, assign a fresh session ID and set it in a
cookie to be sent with the response.
5. If *order-ID* is null, create a new order for *resource-name* by doing a
``POST /private/orders`` to
the merchant backend. Store the new order ID as *order-ID*.
6. 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*.
7. If the *order-status* is paid and *refund-amount* is non-zero,
return to the client the refund info page for *resource name*.
**Terminate.**
+ ---------- DISCUSS: what is a 'refund info page'? What should be on it?
Explain better!
8. 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 information for *resource name*.
**Terminate.**
+ and 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::
- When a refund is given, the corresponding tuple must be removed from the
*session-page-cache*.
+ 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*.
Backend Private Order Status
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The merchant backend runs the following steps to generate the
*client-order-status-URL* when processing a request for ``GET
-/private/orders/{order-ID}?session_id={session-ID}``:
+/private/orders/{order-ID}?session_id={session-ID}&timeout_ms={timeout}``:
-1. Let *session-ID* be the session ID of the request (note: **not** the last
paid session ID)
-2. If *order-ID* does not identify an existing order, return an error.
**Terminate**.
+1. Let *session-ID* be the session ID of the request or null if not given
(note: **not** the last paid session ID)
+2. If *order-ID* does not identify an existing order, return a 40 Not Found
response. **Terminate**.
3. If *order-ID* identifies an order that is *unclaimed* and has claim token
*claim-token*, return the URL
::
{backendBaseUrl}/orders/{order-ID}?token={claim-token}&session_id={session-ID}
- **Terminate.**
-4. If *order-ID* identifies an order that is either *claimed* or *paid* and
has contract terms hash *contract-hash*, return the URL
+ (if no claim-token was generated, omit that parameter from the above URI).
**Terminate.**
+
+4. Here *order-ID* identifies an order that is *claimed*. If the order is
*unpaid*, wait until timeout or payment.
+
+5. If the order remains unpaid or was paid for a different *session-ID*,
obtain the contract terms hash *contract-hash* and return the URL
::
{backendBaseUrl}/orders/{order-ID}?h_contract={contract-hash}&session_id={session-ID}
+ together with the status *unpaid*. (If *session-ID* is null, it does not
matter for which session the contract was paid.) **Terminate.**
+
+6. Here *order-ID* must now identify an order that is *paid* or *refunded*.
Obtain the contract terms hash *contract-hash* and return the URL
+
+ ::
+
+
{backendBaseUrl}/orders/{order-ID}?h_contract={contract-hash}&session_id={session-ID}
+
+ together with the status *paid* or *refunded* (and if applicable, with
details about the applied refunds). **Terminate.**
+
+
+
Backend Client Order Status Page
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The merchant backend runs the following steps to generate the HTML page for
``GET
/orders/{order-ID}?session_id={session-ID}&claim_token={claim-token}&h_contract={contract-hash}``:
+------- NOTE: currently the argument is just 'token', not 'claim_token'!
----------
-1. If *order-ID* does not identify an existing order, render an error page.
**Terminate.**
-2. If *order-ID* identifies a paid order *ord*, run these steps:
+1. If *order-ID* does not identify an existing order, render a 404 Not Found
response. **Terminate.**
+2. If *order-ID* identifies a paid order (where the *session-id* matches the
one from the payment), run these steps:
- 1. If the *contract-hash* request parameter does not match the contract
terms hash of *ord*,
+ 1. If the *contract-hash* request parameter does not match the contract
terms hash of the order,
return a 403 Forbidden response. **Terminate.**
- 2. If *ord* has refunds that are not picked up, prompt the URI
+
+ 2. If the order has granted refunds that have not been obtained by the
wallet yet, prompt the URI
::
taler{proto_suffix}://refund/{/merchant_prefix*}/{order-id}/{session-id}
- Redirect to the *fulfillment-URL* of *ord* once the refund is picked up
and
- payment has been proven under *session-ID*.
-
- **Terminate.**
+ The generated Web site should long-poll until all refunds have been
obtained,
+ then redirect to the *fulfillment-URL* of the order once the refunds
have been
+ obtained. **Terminate.**
+ ----- FIXME: IIRC our long-polling API does only allow waiting for the
granted refund amount, not for the *obtained* refund amount. => API change?
- 3. Prompt the URI
+ 3. Here the order has been paid. -------- what about refunded???
+ Prompt the URI ------ ???why? don't we redirect to fulfillment URL???????
::
taler{proto_suffix}://pay/{/merchant_prefix*}/{order-id}/{session-id}
- Redirect to the *fulfillment-URL* of *ord* once
+ Redirect to the *fulfillment-URL* of the order once
payment has been proven under *session-ID*.
**Terminate.**
-3. If *order-ID* identifies an unpaid order *ord*, run these steps:
+3. If *order-ID* identifies an *unpaid* order, run these steps:
- 1. If the the *claim-token* request parameter does not matches the claim
token of
- *ord*, return a 403 Forbidden response. **Terminate**.
- 2. Prompt the URI
+ 1. If the the *claim-token* request parameter does not match the claim
token of
+ the order, return a 403 Forbidden response. **Terminate**.
+ ----- DISCUSS: unpaid vs. unclaimed: do we check token or h_contract?
------
- ::
+ 2. If there is a non-null *already-paid-order-ID* for *session-ID* stored
under the current order,
+ redirect to the *fulfillment-URL* of *already-paid-order-ID*.
**Terminate**.
-
taler{proto_suffix}://pay/{/merchant_prefix*}/{order-id}/{session-ID}?c={claim-token}
+ 3. Prompt the URI
- Redirect to the *fulfillment-URL* of *ord* once
- payment has been proven under *session-ID*.
+ ::
- If there is a non-null *already-paid-order-ID* for *session-ID*, redirect
- to the *fulfillment-URL* of *already-paid-order-ID*
+
taler{proto_suffix}://pay/{/merchant_prefix*}/{order-id}/{session-ID}?c={claim-token}
+ The generated Web site should long-poll to check for the payment
happening.
+ It should then redirect to the *fulfillment-URL* of the order once
+ payment has been proven under *session-ID*, or possibly redirect to the
+ *already-paid-order-ID*. Which of these happens depends on the
(long-polled) JSON replies.
**Terminate.**
Discussion / Q&A
================
+Notes
+-----
+
+* The *timeout_ms* argument is expected to be ignored when generating HTML.
+ Long-polling simply makes no sense if a browser accesses the site directly.
+
+
Covered Scenarios
-----------------
@@ -144,6 +176,14 @@ Covered Scenarios
Problematic Scenarios
---------------------
+Link sharing
+^^^^^^^^^^^^
+
+Right now, sharing the /orders/{order-ID} link with the session ID will
+allow someone who did not purchase the order to still get a 'paid' response
+from the backend. (Will fulfillment then work? => Check!)
+
+
Bookmarks of Lost Purchases / Social Sharing of Fulfillment URLs
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.