gnunet-svn
[Top][All Lists]
Advanced

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

[taler-merchant] branch master updated: properly parse and return out-of


From: gnunet
Subject: [taler-merchant] branch master updated: properly parse and return out-of-stock reply, fix 2 FIXMEs
Date: Fri, 30 Oct 2020 17:13:12 +0100

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

grothoff pushed a commit to branch master
in repository merchant.

The following commit(s) were added to refs/heads/master by this push:
     new 09c40af  properly parse and return out-of-stock reply, fix 2 FIXMEs
09c40af is described below

commit 09c40af96fa338f6ba57a24df7d43b65384420f9
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Fri Oct 30 17:13:09 2020 +0100

    properly parse and return out-of-stock reply, fix 2 FIXMEs
---
 src/include/taler_merchant_service.h      |  92 +++++++++++++++++---
 src/lib/merchant_api_post_orders.c        | 136 ++++++++++++++++++------------
 src/testing/testing_api_cmd_post_orders.c |  40 ++++-----
 3 files changed, 180 insertions(+), 88 deletions(-)

diff --git a/src/include/taler_merchant_service.h 
b/src/include/taler_merchant_service.h
index 656ae76..88a33ba 100644
--- a/src/include/taler_merchant_service.h
+++ b/src/include/taler_merchant_service.h
@@ -1223,27 +1223,93 @@ TALER_MERCHANT_product_delete_cancel (
 
 
 /**
- * Handle to a POST /orders operation
+ * Handle to a POST /private/orders operation
  */
-// FIXME: rename: Operation => Handle!
-struct TALER_MERCHANT_PostOrdersOperation;
+struct TALER_MERCHANT_PostOrdersHandle;
+
+
+/**
+ * Possible details from a reply to POST /private/orders.
+ */
+struct TALER_MERCHANT_PostOrdersReply
+{
+
+  /**
+   * HTTP response details. HTTP status code
+   * determines what parts of @e details are valid.
+   */
+  struct TALER_MERCHANT_HttpResponse hr;
+
+  /**
+   * Details of the reply, depending on the HTTP
+   * status code.
+   */
+  union {
+
+    /**
+     * Details provided if the @e hr.http_status is
+     * #MHD_HTTP_OK and the order was created.
+     */
+    struct {
+      
+      /**
+       * order id of the newly created order
+       */
+      const char *order_id;
+
+      /**
+       * the claim token generated by the merchant,
+       * (NULL if it was NOT generated).
+       */
+      const struct TALER_ClaimTokenP *token;
+      
+    } ok;
+
+    /**
+     * Details provided if the @e hr.http_status is
+     * #MHD_HTTP_GONE because a product was out of stock.
+     */    
+    struct {
+      /**
+       * ID of the product of the order that is out of
+       * stock.
+       */
+      const char *product_id;
+
+      /**
+       * How many units were requested by the order.
+       */
+      uint64_t requested_quantity;
+
+      /**
+       * How many units are actually still in stock.
+       */
+      uint64_t available_quantity;
+
+      /**
+       * When does the backend expect the stock to be
+       * restocked? 0 for unknown.
+       */
+      struct GNUNET_TIME_Absolute restock_expected;
+      
+    } gone;
+    
+  } details;
+  
+};
+
 
 /**
  * Callbacks of this type are used to serve the result of submitting a
  * POST /orders request to a merchant.
  *
  * @param cls closure
- * @param hr HTTP response details
- * @param order_id order id of the newly created order
- * @param token the claim token generated by the merchant (NULL if
- *        it wasn't generated).
+ * @param por response details
  */
 typedef void
 (*TALER_MERCHANT_PostOrdersCallback) (
   void *cls,
-  const struct TALER_MERCHANT_HttpResponse *hr,
-  const char *order_id,
-  const struct TALER_ClaimTokenP *token);
+  const struct TALER_MERCHANT_PostOrdersReply *por);
 
 
 /**
@@ -1259,7 +1325,7 @@ typedef void
  * @param cb_cls closure for @a cb
  * @return a handle for this request, NULL on error
  */
-struct TALER_MERCHANT_PostOrdersOperation *
+struct TALER_MERCHANT_PostOrdersHandle *
 TALER_MERCHANT_orders_post (struct GNUNET_CURL_Context *ctx,
                             const char *backend_url,
                             const json_t *order,
@@ -1305,7 +1371,7 @@ struct TALER_MERCHANT_InventoryProduct
  * @param cb_cls closure for @a cb
  * @return a handle for this request, NULL on error
  */
-struct TALER_MERCHANT_PostOrdersOperation *
+struct TALER_MERCHANT_PostOrdersHandle *
 TALER_MERCHANT_orders_post2 (
   struct GNUNET_CURL_Context *ctx,
   const char *backend_url,
@@ -1329,7 +1395,7 @@ TALER_MERCHANT_orders_post2 (
  */
 void
 TALER_MERCHANT_orders_post_cancel (
-  struct TALER_MERCHANT_PostOrdersOperation *po);
+  struct TALER_MERCHANT_PostOrdersHandle *po);
 
 
 /**
diff --git a/src/lib/merchant_api_post_orders.c 
b/src/lib/merchant_api_post_orders.c
index a6f1ec7..9c45ad2 100644
--- a/src/lib/merchant_api_post_orders.c
+++ b/src/lib/merchant_api_post_orders.c
@@ -37,7 +37,7 @@
 /**
  * @brief A POST /orders Handle
  */
-struct TALER_MERCHANT_PostOrdersOperation
+struct TALER_MERCHANT_PostOrdersHandle
 {
 
   /**
@@ -76,7 +76,7 @@ struct TALER_MERCHANT_PostOrdersOperation
  * Function called when we're done processing the
  * HTTP POST /orders request.
  *
- * @param cls the `struct TALER_MERCHANT_PostOrdersOperation`
+ * @param cls the `struct TALER_MERCHANT_PostOrdersHandle`
  * @param response_code HTTP response code, 0 on error
  * @param response response body, NULL if not JSON
  */
@@ -85,48 +85,50 @@ handle_post_order_finished (void *cls,
                             long response_code,
                             const void *response)
 {
-  struct TALER_MERCHANT_PostOrdersOperation *po = cls;
-  const char *order_id = NULL;
-  struct TALER_ClaimTokenP token = {0};
+  struct TALER_MERCHANT_PostOrdersHandle *po = cls;
   const json_t *json = response;
-  struct TALER_MERCHANT_HttpResponse hr = {
-    .http_status = (unsigned int) response_code,
-    .reply = json
-  };
-  bool has_token = ((NULL != json_object_get (json,
-                                              "token")) &&
-                    (false == json_is_null (json_object_get (json,
-                                                             "token"))));
-  struct GNUNET_JSON_Specification spec[] = {
-    GNUNET_JSON_spec_string ("order_id",
-                             &order_id),
-    (! has_token) ?
-    GNUNET_JSON_spec_end () :
-    GNUNET_JSON_spec_fixed_auto ("token",
-                                 &token),
-    GNUNET_JSON_spec_end ()
+  struct TALER_MERCHANT_PostOrdersReply por = {
+    .hr.http_status = (unsigned int) response_code,
+    .hr.reply = json
   };
-
+  struct TALER_ClaimTokenP token = {0};
+  
   po->job = NULL;
   switch (response_code)
   {
   case 0:
-    hr.ec = TALER_EC_INVALID_RESPONSE;
+    por.hr.ec = TALER_EC_INVALID_RESPONSE;
     break;
   case MHD_HTTP_OK:
-    if (GNUNET_OK !=
-        GNUNET_JSON_parse (json,
-                           spec,
-                           NULL, NULL))
     {
-      GNUNET_break_op (0);
-      hr.http_status = 0;
-      hr.ec = TALER_EC_PROPOSAL_REPLY_MALFORMED;
+      struct GNUNET_JSON_Specification spec[] = {
+        GNUNET_JSON_spec_string ("order_id",
+                                 &por.details.ok.order_id),
+        GNUNET_JSON_spec_mark_optional (
+          GNUNET_JSON_spec_fixed_auto ("token",
+                                       &token)),
+        GNUNET_JSON_spec_end ()
+      };
+      
+      if (GNUNET_OK !=
+          GNUNET_JSON_parse (json,
+                             spec,
+                             NULL, NULL))
+      {
+        GNUNET_break_op (0);
+        por.hr.http_status = 0;
+        por.hr.ec = TALER_EC_PROPOSAL_REPLY_MALFORMED;
+      }
+      else
+      {
+        if (! GNUNET_is_zero (&token))
+          por.details.ok.token = &token;
+      }
     }
     break;
   case MHD_HTTP_BAD_REQUEST:
-    hr.ec = TALER_JSON_get_error_code (json);
-    hr.hint = TALER_JSON_get_error_hint (json);
+    por.hr.ec = TALER_JSON_get_error_code (json);
+    por.hr.hint = TALER_JSON_get_error_hint (json);
     /* This should never happen, either us or
        the merchant is buggy (or API version conflict);
        just pass JSON reply to the application */
@@ -136,51 +138,75 @@ handle_post_order_finished (void *cls,
        of the signatures is invalid; as we checked them,
        this should never happen, we should pass the JSON
        reply to the application */
-    hr.ec = TALER_JSON_get_error_code (json);
-    hr.hint = TALER_JSON_get_error_hint (json);
+    por.hr.ec = TALER_JSON_get_error_code (json);
+    por.hr.hint = TALER_JSON_get_error_hint (json);
     break;
   case MHD_HTTP_NOT_FOUND:
     /* Nothing really to verify, this should never
        happen, we should pass the JSON reply to the application */
-    hr.ec = TALER_JSON_get_error_code (json);
-    hr.hint = TALER_JSON_get_error_hint (json);
+    por.hr.ec = TALER_JSON_get_error_code (json);
+    por.hr.hint = TALER_JSON_get_error_hint (json);
     break;
   case MHD_HTTP_CONFLICT:
-    hr.ec = TALER_JSON_get_error_code (json);
-    hr.hint = TALER_JSON_get_error_hint (json);
+    por.hr.ec = TALER_JSON_get_error_code (json);
+    por.hr.hint = TALER_JSON_get_error_hint (json);
     break;
   case MHD_HTTP_GONE:
     /* The quantity of some product requested was not available. */
-    // FIXME: parse the OutOfStockResponse.
-    break;
+    {
+
+      struct GNUNET_JSON_Specification spec[] = {
+        GNUNET_JSON_spec_string (
+                                 "product_id",
+                                 &por.details.gone.product_id),
+        GNUNET_JSON_spec_uint64 (
+                                 "requested_quantity",
+                                 &por.details.gone.requested_quantity),
+        GNUNET_JSON_spec_uint64 (
+                                 "available_quantity",
+                                 &por.details.gone.available_quantity),
+        GNUNET_JSON_spec_mark_optional (
+          GNUNET_JSON_spec_absolute_time (
+                                          "restock_expected",
+                                          &por.details.gone.restock_expected)),
+        GNUNET_JSON_spec_end ()
+      };
+      
+      if (GNUNET_OK !=
+          GNUNET_JSON_parse (json,
+                             spec,
+                             NULL, NULL))
+      {
+        GNUNET_break_op (0);
+        por.hr.http_status = 0;
+        por.hr.ec = TALER_EC_PROPOSAL_REPLY_MALFORMED;
+      }
+      break;
+    }
   case MHD_HTTP_INTERNAL_SERVER_ERROR:
     /* Server had an internal issue; we should retry,
        but this API leaves this to the application */
-    hr.ec = TALER_JSON_get_error_code (json);
-    hr.hint = TALER_JSON_get_error_hint (json);
+    por.hr.ec = TALER_JSON_get_error_code (json);
+    por.hr.hint = TALER_JSON_get_error_hint (json);
     break;
   default:
     /* unexpected response code */
-    hr.ec = TALER_JSON_get_error_code (json);
-    hr.hint = TALER_JSON_get_error_hint (json);
+    por.hr.ec = TALER_JSON_get_error_code (json);
+    por.hr.hint = TALER_JSON_get_error_hint (json);
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "Unexpected response code %u/%d\n",
                 (unsigned int) response_code,
-                (int) hr.ec);
+                (int) por.hr.ec);
     GNUNET_break_op (0);
     break;
   }
   po->cb (po->cb_cls,
-          &hr,
-          order_id,
-          has_token ? &token : NULL);
-  if (MHD_HTTP_OK == response_code)
-    GNUNET_JSON_parse_free (spec);
+          &por);
   TALER_MERCHANT_orders_post_cancel (po);
 }
 
 
-struct TALER_MERCHANT_PostOrdersOperation *
+struct TALER_MERCHANT_PostOrdersHandle *
 TALER_MERCHANT_orders_post (struct GNUNET_CURL_Context *ctx,
                             const char *backend_url,
                             const json_t *order,
@@ -203,7 +229,7 @@ TALER_MERCHANT_orders_post (struct GNUNET_CURL_Context *ctx,
 }
 
 
-struct TALER_MERCHANT_PostOrdersOperation *
+struct TALER_MERCHANT_PostOrdersHandle *
 TALER_MERCHANT_orders_post2 (
   struct GNUNET_CURL_Context *ctx,
   const char *backend_url,
@@ -218,11 +244,11 @@ TALER_MERCHANT_orders_post2 (
   TALER_MERCHANT_PostOrdersCallback cb,
   void *cb_cls)
 {
-  struct TALER_MERCHANT_PostOrdersOperation *po;
+  struct TALER_MERCHANT_PostOrdersHandle *po;
   json_t *req;
   CURL *eh;
 
-  po = GNUNET_new (struct TALER_MERCHANT_PostOrdersOperation);
+  po = GNUNET_new (struct TALER_MERCHANT_PostOrdersHandle);
   po->ctx = ctx;
   po->cb = cb;
   po->cb_cls = cb_cls;
@@ -327,7 +353,7 @@ TALER_MERCHANT_orders_post2 (
 
 void
 TALER_MERCHANT_orders_post_cancel (
-  struct TALER_MERCHANT_PostOrdersOperation *po)
+  struct TALER_MERCHANT_PostOrdersHandle *po)
 {
   if (NULL != po->job)
   {
diff --git a/src/testing/testing_api_cmd_post_orders.c 
b/src/testing/testing_api_cmd_post_orders.c
index b9ea27e..b4a56ee 100644
--- a/src/testing/testing_api_cmd_post_orders.c
+++ b/src/testing/testing_api_cmd_post_orders.c
@@ -68,7 +68,7 @@ struct OrdersState
   /**
    * The /orders operation handle.
    */
-  struct TALER_MERCHANT_PostOrdersOperation *po;
+  struct TALER_MERCHANT_PostOrdersHandle *po;
 
   /**
    * The (initial) POST /orders/$ID/claim operation handle.
@@ -243,26 +243,20 @@ orders_claim_cb (void *cls,
  * method.
  *
  * @param cls closure.
- * @param hr HTTP response
- * @param order_id order id of the orders.
- * @param claim_token claim token
+ * @param por details about the response
  */
 static void
 order_cb (void *cls,
-          const struct TALER_MERCHANT_HttpResponse *hr,
-          const char *order_id,
-          const struct TALER_ClaimTokenP *claim_token)
+          const struct TALER_MERCHANT_PostOrdersReply *por)
 {
   struct OrdersState *ps = cls;
 
   ps->po = NULL;
-  if (NULL != claim_token)
-    ps->claim_token = *claim_token;
-  if (ps->http_status != hr->http_status)
+  if (ps->http_status != por->hr.http_status)
   {
     TALER_LOG_ERROR ("Given vs expected: %u(%d) vs %u\n",
-                     hr->http_status,
-                     (int) hr->ec,
+                     por->hr.http_status,
+                     (int) por->hr.ec,
                      ps->http_status);
     TALER_TESTING_FAIL (ps->is);
   }
@@ -272,12 +266,14 @@ order_cb (void *cls,
     TALER_TESTING_interpreter_next (ps->is);
     return;
   }
-  switch (hr->http_status)
+  switch (por->hr.http_status)
   {
   case MHD_HTTP_OK:
-    ps->order_id = GNUNET_strdup (order_id);
+    if (NULL != por->details.ok.token)
+      ps->claim_token = *por->details.ok.token;
+    ps->order_id = GNUNET_strdup (por->details.ok.order_id);
     if ((NULL != ps->expected_order_id) &&
-        (0 != strcmp (order_id,
+        (0 != strcmp (por->details.ok.order_id,
                       ps->expected_order_id)))
     {
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -290,6 +286,7 @@ order_cb (void *cls,
       const struct TALER_TESTING_Command *order_cmd;
       const struct TALER_ClaimTokenP *prev_token;
       struct TALER_ClaimTokenP zero_token = {0};
+      
       order_cmd = TALER_TESTING_interpreter_lookup_command (
         ps->is,
         ps->duplicate_of);
@@ -303,10 +300,10 @@ order_cb (void *cls,
         TALER_TESTING_interpreter_fail (ps->is);
         return;
       }
-      if (NULL == claim_token)
+      if (NULL == por->details.ok.token)
         prev_token = &zero_token;
       if (0 != GNUNET_memcmp (prev_token,
-                              claim_token))
+                              por->details.ok.token))
       {
         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                     "Claim tokens for identical requests do not match\n");
@@ -315,17 +312,20 @@ order_cb (void *cls,
       }
     }
     break;
+  case MHD_HTTP_GONE:
+    TALER_TESTING_interpreter_next (ps->is);
+    return;
   case MHD_HTTP_CONFLICT:
     TALER_TESTING_interpreter_next (ps->is);
     return;
   default:
     {
-      char *s = json_dumps (hr->reply,
+      char *s = json_dumps (por->hr.reply,
                             JSON_COMPACT);
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                   "Unexpected status code from /orders: %u (%d) at %s; JSON: 
%s\n",
-                  hr->http_status,
-                  hr->ec,
+                  por->hr.http_status,
+                  (int) por->hr.ec,
                   TALER_TESTING_interpreter_get_current_label (ps->is),
                   s);
       GNUNET_free (s);

-- 
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]