gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-docs] branch master updated: complete public order spec, implemen


From: gnunet
Subject: [taler-docs] branch master updated: complete public order spec, implement Christian's suggestions
Date: Tue, 10 Aug 2021 15:11:21 +0200

This is an automated email from the git hooks/post-receive script.

dold pushed a commit to branch master
in repository docs.

The following commit(s) were added to refs/heads/master by this push:
     new a2cef95  complete public order spec, implement Christian's suggestions
a2cef95 is described below

commit a2cef959c0cf801e9f4136736dd8e8e8d98838af
Author: Florian Dold <florian@dold.me>
AuthorDate: Tue Aug 10 15:11:09 2021 +0200

    complete public order spec, implement Christian's suggestions
---
 merchant-spec/public-orders-get.ts | 183 ++++++++++++++++++++++++-------------
 1 file changed, 119 insertions(+), 64 deletions(-)

diff --git a/merchant-spec/public-orders-get.ts 
b/merchant-spec/public-orders-get.ts
index 916ba19..03c4f7a 100644
--- a/merchant-spec/public-orders-get.ts
+++ b/merchant-spec/public-orders-get.ts
@@ -28,8 +28,11 @@ interface Req {
 // (Abstract) response to /orders/{id}
 interface Resp {
   httpStatus: string;
+  contentType: "json" | "html";
   // Schema type of the response
   responseType: string;
+  // Redirect "Location: " if applicable to status code
+  redirectLocation?: string;
   // Additional details about response
   response?: any;
 }
@@ -41,56 +44,40 @@ type MerchantOrderStore = { [orderId: string]: 
MerchantOrderInfo };
 function handlePublicOrdersGet(mos: MerchantOrderStore, req: Req): Resp {
   const ord = mos[req.orderId];
   if (!ord) {
-    return {
-      httpStatus: "404 Not Found",
-      responseType: "TalerErrorResponse",
-    };
+    return respNotFound(req);
   }
   if (!ord.claimed) {
     if (ord.requireClaimToken && ord.claimToken !== req.claimToken) {
-      return {
-        httpStatus: "403 Forbidden",
-        responseType: "TalerErrorResponse",
-      };
+      return respForbidden(req);
     }
-    return {
-      httpStatus: "402 Payment Required",
-      responseType: "StatusUnpaidResponse",
-      response: {
-        fulfillmentUrl: ord.fulfillmentUrl,
-        // FIXME: do we include claim token here?
-        talerPayUri: "taler://pay/",
-      },
-    };
+    return respUnpaid(req, ord);
   }
 
   if (!ord.paid) {
     const hcOk = ord.contractHash === req.contractHash;
-    if (!hcOk && ord.requireClaimToken && ord.claimToken !== req.claimToken) {
+    const ctOk = ord.claimToken === req.claimToken;
+    if (req.contractHash && !hcOk) {
+      // Contract terms hash given but wrong
+      return respForbidden(req);
+    }
+    if (req.claimToken && ord.claimToken !== req.claimToken) {
+      // Claim token given but wrong
+      return respForbidden(req);
+    }
+    if (ord.requireClaimToken && !req.claimToken && !hcOk) {
       // Client is trying to get the order status of a claimed,
       // unpaid order.  However, the client is not showing authentication.
-      // 
+      //
       // This can happen when the fulfillment URL includes the order ID,
       // and the storefront redirects the user to the backend QR code
       // page, because the order is not paid under the current session.
       // This happens on bookmarking / link sharing.
-      return {
-        httpStatus: "202 Accepted",
-        responseType: "StatusGotoResponse",
-        response: {
-          public_reorder_url: ord.publicReorderUrl,
-        },
-      };
+      if (!ord.publicReorderUrl) {
+        return respForbidden(req);
+      }
+      return respGoto(req, ord.publicReorderUrl);
     }
-    return {
-      httpStatus: "402 Payment Required",
-      responseType: "StatusUnpaidResponse",
-      response: {
-        fulfillmentUrl: ord.fulfillmentUrl,
-        // FIXME: do we include claim token here?
-        talerPayUri: "taler://pay/",
-      },
-    };
+    return respUnpaid(req, ord);
   }
 
   // Here, we know that the order is paid for.
@@ -106,41 +93,109 @@ function handlePublicOrdersGet(mos: MerchantOrderStore, 
req: Req): Resp {
     ord.contractHash === req.contractHash ||
     (ord.requireClaimToken && ord.claimToken === req.claimToken);
 
-  if (authOk) {
-    if (!!req.sessionId && req.sessionId !== ord.lastPaidSessionId) {
-      const alreadyPaidOrd = findAlreadyPaid(mos, req.sessionId);
-      if (alreadyPaidOrd) {
-        return {
-          httpStatus: "202 Accepted",
-          responseType: "StatusGotoResponse",
-          response: {
-            public_reorder_url: ord.publicReorderUrl,
-            already_paid_order_id: alreadyPaidOrd.orderId,
-          },
-        };
-      }
-      return {
-        httpStatus: "402 Payment Required",
-        responseType: "StatusUnpaidResponse",
-        response: {
-          fulfillmentUrl: ord.fulfillmentUrl,
-          // TO DISCUSS: do we include claim token here?
-          talerPayUri: "taler://pay/",
-        },
-      };
+  if (!authOk) {
+    return respForbidden(req);
+  }
+
+  if (!!req.sessionId && req.sessionId !== ord.lastPaidSessionId) {
+    const alreadyPaidOrd = findAlreadyPaid(mos, req.sessionId);
+    if (!!alreadyPaidOrd) {
+      return respAlreadyPaid(req, alreadyPaidOrd);
     }
+    return respUnpaid(req, ord);
+  }
+  return respPaid(req, ord);
+}
+
+function respNotFound(req: Req): Resp {
+  return {
+    contentType: req.accept,
+    httpStatus: "404 Not Found",
+    responseType: "TalerError",
+  };
+}
+
+function respForbidden(req: Req): Resp {
+  return {
+    contentType: req.accept,
+    httpStatus: "403 Forbidden",
+    responseType: "TalerError",
+  };
+}
+
+function respAlreadyPaid(req: Req, alreadyPaidOrd: MerchantOrderInfo): Resp {
+  // This could be called with an empty fulfillment URL, but that doens't
+  // really make sense for the client's perspective.
+  if (req.accept === "html") {
     return {
-      httpStatus: "200 OK",
-      responseType: "StatusPaidResponse",
-      response: {
-        fulfillmentUrl: ord.fulfillmentUrl,
-      },
+      httpStatus: "302 Found",
+      contentType: "html",
+      redirectLocation: alreadyPaidOrd.fulfillmentUrl,
+      responseType: "empty",
     };
   }
+  return {
+    httpStatus: "202 Accepted",
+    contentType: "json",
+    responseType: "StatusGotoResponse",
+    response: {
+      fulfillment_url: alreadyPaidOrd.fulfillmentUrl,
+    },
+  };
+}
 
+function respGoto(req: Req, publicReorderUrl: string): Resp {
+  if (req.accept === "html") {
+    return {
+      httpStatus: "302 Found",
+      contentType: "html",
+      redirectLocation: publicReorderUrl,
+      responseType: "empty",
+    };
+  }
   return {
-    httpStatus: "403 Forbidden",
-    responseType: "TalerErrorResponse",
+    httpStatus: "202 Accepted",
+    contentType: "json",
+    responseType: "StatusGotoResponse",
+    response: {
+      public_reorder_url: publicReorderUrl,
+    },
+  };
+}
+
+function respUnpaid(req: Req, ord: MerchantOrderInfo): Resp {
+  if (req.accept === "html") {
+    return;
+  }
+  return {
+    httpStatus: "402 Payment Required",
+    contentType: "html",
+    responseType: "StatusUnpaidResponse",
+    response: {
+      // Required for repurchase detection
+      fulfillmentUrl: ord.fulfillmentUrl,
+    },
+  };
+}
+
+function respPaid(req: Req, ord: MerchantOrderInfo): Resp {
+  if (req.accept === "html") {
+    if (req.accept === "html") {
+      return {
+        httpStatus: "302 Found",
+        contentType: "html",
+        redirectLocation: ord.fulfillmentUrl || "<backend pay success page>",
+        responseType: "empty",
+      };
+    }
+  }
+  return {
+    httpStatus: "200 OK",
+    contentType: "json",
+    responseType: "StatusPaidResponse",
+    response: {
+      fulfillmentUrl: ord.fulfillmentUrl,
+    },
   };
 }
 

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]