gnunet-svn
[Top][All Lists]
Advanced

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

[taler-merchant] branch master updated (5bc607b1 -> 42490d30)


From: gnunet
Subject: [taler-merchant] branch master updated (5bc607b1 -> 42490d30)
Date: Mon, 18 Mar 2024 23:09:19 +0100

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

grothoff pushed a change to branch master
in repository merchant.

    from 5bc607b1 simplify kyc logic in payment logic as we now have 
taler-merchant-depositcheck doing it better
     new 63c171f4 move lookup order for idempotency check into transaction 
scope where it belongs
     new 42490d30 implement protocol v12, fixes #7948

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 configure.ac                                       |   4 +-
 src/backend/taler-merchant-httpd_config.c          |   2 +-
 .../taler-merchant-httpd_private-get-orders.c      | 107 +++++----------
 .../taler-merchant-httpd_private-get-products.c    |  20 ++-
 .../taler-merchant-httpd_private-get-transfers.c   |  63 ++-------
 .../taler-merchant-httpd_private-post-orders.c     | 152 ++++++++++++---------
 src/backenddb/pg_lookup_products.c                 |  44 ++++--
 src/backenddb/pg_lookup_products.h                 |   5 +
 src/backenddb/test_merchantdb.c                    |   6 +
 src/include/taler_merchant_service.h               |   4 +
 src/include/taler_merchantdb_plugin.h              |   7 +
 src/lib/merchant_api_get_config.c                  |   4 +-
 src/lib/merchant_api_get_products.c                |   4 +-
 13 files changed, 217 insertions(+), 205 deletions(-)

diff --git a/configure.ac b/configure.ac
index 659d7349..8fd422fc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -268,12 +268,12 @@ AS_CASE([$with_exchange],
          CPPFLAGS="-I$with_exchange/include $CPPFLAGS $POSTGRESQL_CPPFLAGS"])
 
 AC_CHECK_HEADERS([taler/taler_mhd_lib.h],
- [AC_CHECK_LIB([talermhd], [TALER_MHD_parse_request_arg_amount], 
libtalermhd=1)])
+ [AC_CHECK_LIB([talermhd], [TALER_MHD_parse_request_arg_snumber], 
libtalermhd=1)])
 AM_CONDITIONAL(HAVE_TALERMHD, test x$libtalermhd = x1)
 AS_IF([test $libtalermhd != 1],
   [AC_MSG_ERROR([[
 ***
-*** You need libtalermhd >= 0.9.4a to build this program.
+*** You need libtalermhd >= 0.10.1 (API v2) to build this program.
 *** This library is part of the GNU Taler exchange, available at
 ***   https://taler.net
 *** ]])])
diff --git a/src/backend/taler-merchant-httpd_config.c 
b/src/backend/taler-merchant-httpd_config.c
index d020985b..969cf1ca 100644
--- a/src/backend/taler-merchant-httpd_config.c
+++ b/src/backend/taler-merchant-httpd_config.c
@@ -42,7 +42,7 @@
  * #MERCHANT_PROTOCOL_CURRENT and #MERCHANT_PROTOCOL_AGE in
  * merchant_api_config.c!
  */
-#define MERCHANT_PROTOCOL_VERSION "11:0:7"
+#define MERCHANT_PROTOCOL_VERSION "12:0:8"
 
 
 /**
diff --git a/src/backend/taler-merchant-httpd_private-get-orders.c 
b/src/backend/taler-merchant-httpd_private-get-orders.c
index 92a1f389..5fc91188 100644
--- a/src/backend/taler-merchant-httpd_private-get-orders.c
+++ b/src/backend/taler-merchant-httpd_private-get-orders.c
@@ -687,44 +687,23 @@ TMH_private_get_orders (const struct TMH_RequestHandler 
*rh,
                                        MHD_HTTP_BAD_REQUEST,
                                        TALER_EC_GENERIC_PARAMETER_MALFORMED,
                                        "wired");
+  po->of.delta = -20;
+  /* deprecated in protocol v12 */
+  TALER_MHD_parse_request_snumber (connection,
+                                   "delta",
+                                   &po->of.delta);
+  /* since protocol v12 */
+  TALER_MHD_parse_request_snumber (connection,
+                                   "limit",
+                                   &po->of.delta);
+  if ( (-MAX_DELTA > po->of.delta) ||
+       (po->of.delta > MAX_DELTA) )
   {
-    const char *delta_str;
-
-    delta_str = MHD_lookup_connection_value (connection,
-                                             MHD_GET_ARGUMENT_KIND,
-                                             "delta");
-    if (NULL == delta_str)
-    {
-      po->of.delta = -20;
-    }
-    else
-    {
-      char dummy;
-      long long ll;
-
-      if (1 !=
-          sscanf (delta_str,
-                  "%lld%c",
-                  &ll,
-                  &dummy))
-      {
-        GNUNET_break_op (0);
-        return TALER_MHD_reply_with_error (connection,
-                                           MHD_HTTP_BAD_REQUEST,
-                                           
TALER_EC_GENERIC_PARAMETER_MALFORMED,
-                                           "delta");
-      }
-      po->of.delta = (int64_t) ll;
-      if ( (-MAX_DELTA > po->of.delta) ||
-           (po->of.delta > MAX_DELTA) )
-      {
-        GNUNET_break_op (0);
-        return TALER_MHD_reply_with_error (connection,
-                                           MHD_HTTP_BAD_REQUEST,
-                                           
TALER_EC_GENERIC_PARAMETER_MALFORMED,
-                                           "delta");
-      }
-    }
+    GNUNET_break_op (0);
+    return TALER_MHD_reply_with_error (connection,
+                                       MHD_HTTP_BAD_REQUEST,
+                                       TALER_EC_GENERIC_PARAMETER_MALFORMED,
+                                       "delta");
   }
   {
     const char *date_s_str;
@@ -769,43 +748,25 @@ TMH_private_get_orders (const struct TMH_RequestHandler 
*rh,
       }
     }
   }
+  if (po->of.delta > 0)
+    po->of.start_row = 0;
+  else
+    po->of.start_row = INT64_MAX;
+  /* deprecated in protocol v12 */
+  TALER_MHD_parse_request_number (connection,
+                                  "start",
+                                  &po->of.start_row);
+  /* since protocol v12 */
+  TALER_MHD_parse_request_number (connection,
+                                  "offset",
+                                  &po->of.start_row);
+  if (INT64_MAX < po->of.start_row)
   {
-    const char *start_row_str;
-
-    start_row_str = MHD_lookup_connection_value (connection,
-                                                 MHD_GET_ARGUMENT_KIND,
-                                                 "start");
-    if (NULL == start_row_str)
-    {
-      if (po->of.delta > 0)
-        po->of.start_row = 0;
-      else
-        po->of.start_row = INT64_MAX;
-    }
-    else
-    {
-      char dummy;
-      unsigned long long ull;
-
-      if (1 !=
-          sscanf (start_row_str,
-                  "%llu%c",
-                  &ull,
-                  &dummy))
-        return TALER_MHD_reply_with_error (connection,
-                                           MHD_HTTP_BAD_REQUEST,
-                                           
TALER_EC_GENERIC_PARAMETER_MALFORMED,
-                                           "start");
-      po->of.start_row = (uint64_t) ull;
-      if (INT64_MAX < po->of.start_row)
-      {
-        GNUNET_break_op (0);
-        return TALER_MHD_reply_with_error (connection,
-                                           MHD_HTTP_BAD_REQUEST,
-                                           
TALER_EC_GENERIC_PARAMETER_MALFORMED,
-                                           "start");
-      }
-    }
+    GNUNET_break_op (0);
+    return TALER_MHD_reply_with_error (connection,
+                                       MHD_HTTP_BAD_REQUEST,
+                                       TALER_EC_GENERIC_PARAMETER_MALFORMED,
+                                       "start");
   }
   po->of.session_id
     = MHD_lookup_connection_value (connection,
diff --git a/src/backend/taler-merchant-httpd_private-get-products.c 
b/src/backend/taler-merchant-httpd_private-get-products.c
index bc90c94d..d9fa4e49 100644
--- a/src/backend/taler-merchant-httpd_private-get-products.c
+++ b/src/backend/taler-merchant-httpd_private-get-products.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  (C) 2019, 2020, 2021 Taler Systems SA
+  (C) 2019, 2020, 2021, 2024 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU Affero General Public License as published by the Free 
Software
@@ -30,6 +30,7 @@
  */
 static void
 add_product (void *cls,
+             uint64_t product_serial,
              const char *product_id)
 {
   json_t *pa = cls;
@@ -38,6 +39,8 @@ add_product (void *cls,
                  json_array_append_new (
                    pa,
                    GNUNET_JSON_PACK (
+                     GNUNET_JSON_pack_uint64 ("product_serial",
+                                              product_serial),
                      GNUNET_JSON_pack_string ("product_id",
                                               product_id))));
 }
@@ -50,11 +53,26 @@ TMH_private_get_products (const struct TMH_RequestHandler 
*rh,
 {
   json_t *pa;
   enum GNUNET_DB_QueryStatus qs;
+  int64_t limit;
+  uint64_t offset;
 
+  limit = 20; /* default */
+  TALER_MHD_parse_request_snumber (connection,
+                                   "limit",
+                                   &limit);
+  if (limit < 0)
+    offset = INT64_MAX;
+  else
+    offset = 0;
+  TALER_MHD_parse_request_number (connection,
+                                  "offset",
+                                  &offset);
   pa = json_array ();
   GNUNET_assert (NULL != pa);
   qs = TMH_db->lookup_products (TMH_db->cls,
                                 hc->instance->settings.id,
+                                offset,
+                                limit,
                                 &add_product,
                                 pa);
   if (0 > qs)
diff --git a/src/backend/taler-merchant-httpd_private-get-transfers.c 
b/src/backend/taler-merchant-httpd_private-get-transfers.c
index c43781dd..3e540297 100644
--- a/src/backend/taler-merchant-httpd_private-get-transfers.c
+++ b/src/backend/taler-merchant-httpd_private-get-transfers.c
@@ -137,59 +137,16 @@ TMH_private_get_transfers (const struct 
TMH_RequestHandler *rh,
                                          TALER_EC_GENERIC_PARAMETER_MALFORMED,
                                          "after");
   }
-  {
-    const char *limit_s;
-
-    limit_s = MHD_lookup_connection_value (connection,
-                                           MHD_GET_ARGUMENT_KIND,
-                                           "limit");
-    if (NULL != limit_s)
-    {
-      char dummy[2];
-      long long l;
-
-      if (1 !=
-          sscanf (limit_s,
-                  "%lld%1s",
-                  &l,
-                  dummy))
-        return TALER_MHD_reply_with_error (connection,
-                                           MHD_HTTP_BAD_REQUEST,
-                                           
TALER_EC_GENERIC_PARAMETER_MALFORMED,
-                                           "limit");
-      limit = (int64_t) l;
-    }
-  }
-  {
-    const char *offset_s;
-
-    offset_s = MHD_lookup_connection_value (connection,
-                                            MHD_GET_ARGUMENT_KIND,
-                                            "offset");
-    if (NULL != offset_s)
-    {
-      char dummy[2];
-      unsigned long long o;
-
-      if (1 !=
-          sscanf (offset_s,
-                  "%llu%1s",
-                  &o,
-                  dummy))
-        return TALER_MHD_reply_with_error (connection,
-                                           MHD_HTTP_BAD_REQUEST,
-                                           
TALER_EC_GENERIC_PARAMETER_MALFORMED,
-                                           "offset");
-      offset = (uint64_t) o;
-    }
-    else
-    {
-      if (limit < 0)
-        offset = INT64_MAX;
-      else
-        offset = 0;
-    }
-  }
+  TALER_MHD_parse_request_snumber (connection,
+                                   "limit",
+                                   &limit);
+  if (limit < 0)
+    offset = INT64_MAX;
+  else
+    offset = 0;
+  TALER_MHD_parse_request_number (connection,
+                                  "offset",
+                                  &offset);
   if (! (TALER_arg_to_yna (connection,
                            "verified",
                            TALER_EXCHANGE_YNA_ALL,
diff --git a/src/backend/taler-merchant-httpd_private-post-orders.c 
b/src/backend/taler-merchant-httpd_private-post-orders.c
index 736da1c2..92d35b78 100644
--- a/src/backend/taler-merchant-httpd_private-post-orders.c
+++ b/src/backend/taler-merchant-httpd_private-post-orders.c
@@ -423,6 +423,24 @@ struct OrderContext
      * Which product (by offset) is out of stock, UINT_MAX if all were 
in-stock.
      */
     unsigned int out_of_stock_index;
+
+    /**
+     * Set to a previous claim token *if* @e idempotent
+     * is also true.
+     */
+    struct TALER_ClaimTokenP token;
+
+    /**
+     * Set to true if the order was idempotent and there
+     * was an equivalent one before.
+     */
+    bool idempotent;
+
+    /**
+     * Set to true if the order is in conflict with a
+     * previous order with the same order ID.
+     */
+    bool conflict;
   } execute_order;
 
   struct
@@ -661,6 +679,45 @@ execute_transaction (struct OrderContext *oc)
     GNUNET_break (0);
     return GNUNET_DB_STATUS_HARD_ERROR;
   }
+
+  /* Test if we already have an order with this id */
+  {
+    json_t *contract_terms;
+    struct TALER_MerchantPostDataHashP orig_post;
+
+    qs = TMH_db->lookup_order (TMH_db->cls,
+                               oc->hc->instance->settings.id,
+                               oc->parse_order.order_id,
+                               &oc->execute_order.token,
+                               &orig_post,
+                               &contract_terms);
+    /* If yes, check for idempotency */
+    if (0 > qs)
+    {
+      GNUNET_break (0);
+      TMH_db->rollback (TMH_db->cls);
+      return qs;
+    }
+    if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
+    {
+      TMH_db->rollback (TMH_db->cls);
+      json_decref (contract_terms);
+      /* Comparing the contract terms is sufficient because all the other
+         params get added to it at some point. */
+      if (0 == GNUNET_memcmp (&orig_post,
+                              &oc->parse_request.h_post_data))
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                    "Order creation idempotent\n");
+        oc->execute_order.idempotent = true;
+        return qs;
+      }
+      GNUNET_break_op (0);
+      oc->execute_order.conflict = true;
+      return qs;
+    }
+  }
+
   /* Setup order */
   qs = TMH_db->insert_order (TMH_db->cls,
                              oc->hc->instance->settings.id,
@@ -757,70 +814,6 @@ execute_order (struct OrderContext *oc)
     &oc->hc->instance->settings;
   enum GNUNET_DB_QueryStatus qs;
 
-  /* Test if we already have an order with this id */
-  /* FIXME: this should be done within the main
-     transaction! */
-  {
-    struct TALER_ClaimTokenP token;
-    json_t *contract_terms;
-    struct TALER_MerchantPostDataHashP orig_post;
-
-    TMH_db->preflight (TMH_db->cls);
-    qs = TMH_db->lookup_order (TMH_db->cls,
-                               oc->hc->instance->settings.id,
-                               oc->parse_order.order_id,
-                               &token,
-                               &orig_post,
-                               &contract_terms);
-    /* If yes, check for idempotency */
-    if (0 > qs)
-    {
-      GNUNET_break (0);
-      TMH_db->rollback (TMH_db->cls);
-      reply_with_error (oc,
-                        MHD_HTTP_INTERNAL_SERVER_ERROR,
-                        TALER_EC_GENERIC_DB_FETCH_FAILED,
-                        "lookup_order");
-      return;
-    }
-    if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
-    {
-      MHD_RESULT ret;
-
-      json_decref (contract_terms);
-      /* Comparing the contract terms is sufficient because all the other
-         params get added to it at some point. */
-      if (0 == GNUNET_memcmp (&orig_post,
-                              &oc->parse_request.h_post_data))
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                    "Order creation idempotent\n");
-        ret = TALER_MHD_REPLY_JSON_PACK (
-          oc->connection,
-          MHD_HTTP_OK,
-          GNUNET_JSON_pack_string ("order_id",
-                                   oc->parse_order.order_id),
-          GNUNET_JSON_pack_allow_null (
-            GNUNET_JSON_pack_data_varsize (
-              "token",
-              GNUNET_is_zero (&token)
-              ? NULL
-              : &token,
-              sizeof (token))));
-        finalize_order (oc,
-                        ret);
-        return;
-      }
-      /* This request is not idempotent */
-      GNUNET_break_op (0);
-      reply_with_error (
-        oc,
-        MHD_HTTP_CONFLICT,
-        TALER_EC_MERCHANT_PRIVATE_POST_ORDERS_ALREADY_EXISTS,
-        oc->parse_order.order_id);
-      return;
-    }
-  }
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Executing database transaction to create order '%s' for 
instance '%s'\n",
               oc->parse_order.order_id,
@@ -865,6 +858,37 @@ execute_order (struct OrderContext *oc)
     return;
   }
 
+  /* DB transaction succeeded, check for idempotent */
+  if (oc->execute_order.idempotent)
+  {
+    MHD_RESULT ret;
+
+    ret = TALER_MHD_REPLY_JSON_PACK (
+      oc->connection,
+      MHD_HTTP_OK,
+      GNUNET_JSON_pack_string ("order_id",
+                               oc->parse_order.order_id),
+      GNUNET_JSON_pack_allow_null (
+        GNUNET_JSON_pack_data_varsize (
+          "token",
+          GNUNET_is_zero (&oc->execute_order.token)
+          ? NULL
+          : &oc->execute_order.token,
+          sizeof (oc->execute_order.token))));
+    finalize_order (oc,
+                    ret);
+    return;
+  }
+  if (oc->execute_order.conflict)
+  {
+    reply_with_error (
+      oc,
+      MHD_HTTP_CONFLICT,
+      TALER_EC_MERCHANT_PRIVATE_POST_ORDERS_ALREADY_EXISTS,
+      oc->parse_order.order_id);
+    return;
+  }
+
   /* DB transaction succeeded, check for out-of-stock */
   if (oc->execute_order.out_of_stock_index < UINT_MAX)
   {
diff --git a/src/backenddb/pg_lookup_products.c 
b/src/backenddb/pg_lookup_products.c
index d16aeb8d..fa2887a8 100644
--- a/src/backenddb/pg_lookup_products.c
+++ b/src/backenddb/pg_lookup_products.c
@@ -65,9 +65,12 @@ lookup_products_cb (void *cls,
   for (unsigned int i = 0; i < num_results; i++)
   {
     char *product_id;
+    uint64_t product_serial;
     struct GNUNET_PQ_ResultSpec rs[] = {
       GNUNET_PQ_result_spec_string ("product_id",
                                     &product_id),
+      GNUNET_PQ_result_spec_uint64 ("product_serial",
+                                    &product_serial),
       GNUNET_PQ_result_spec_end
     };
 
@@ -81,6 +84,7 @@ lookup_products_cb (void *cls,
       return;
     }
     plc->cb (plc->cb_cls,
+             product_serial,
              product_id);
     GNUNET_PQ_cleanup_result (rs);
   }
@@ -90,10 +94,13 @@ lookup_products_cb (void *cls,
 enum GNUNET_DB_QueryStatus
 TMH_PG_lookup_products (void *cls,
                         const char *instance_id,
+                        uint64_t offset,
+                        int64_t limit,
                         TALER_MERCHANTDB_ProductsCallback cb,
                         void *cb_cls)
 {
   struct PostgresClosure *pg = cls;
+  uint64_t plimit = (uint64_t) ((limit < 0) ? -limit : limit);
   struct LookupProductsContext plc = {
     .cb = cb,
     .cb_cls = cb_cls,
@@ -102,24 +109,45 @@ TMH_PG_lookup_products (void *cls,
   };
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_string (instance_id),
+    GNUNET_PQ_query_param_uint64 (&offset),
+    GNUNET_PQ_query_param_uint64 (&plimit),
     GNUNET_PQ_query_param_end
   };
   enum GNUNET_DB_QueryStatus qs;
 
   check_connection (pg);
   PREPARE (pg,
-           "lookup_products",
+           "lookup_products_asc",
            "SELECT"
-           " product_id"
+           "  product_id"
+           " ,product_serial"
            " FROM merchant_inventory"
            " JOIN merchant_instances"
            "   USING (merchant_serial)"
-           " WHERE merchant_instances.merchant_id=$1");
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "lookup_products",
-                                             params,
-                                             &lookup_products_cb,
-                                             &plc);
+           " WHERE merchant_instances.merchant_id=$1"
+           "   AND product_serial > $2"
+           " ORDER BY product_serial ASC"
+           " LIMIT $3");
+  PREPARE (pg,
+           "lookup_products_desc",
+           "SELECT"
+           "  product_id"
+           " ,product_serial"
+           " FROM merchant_inventory"
+           " JOIN merchant_instances"
+           "   USING (merchant_serial)"
+           " WHERE merchant_instances.merchant_id=$1"
+           "   AND product_serial < $2"
+           " ORDER BY product_serial DESC"
+           " LIMIT $3");
+  qs = GNUNET_PQ_eval_prepared_multi_select (
+    pg->conn,
+    (limit > 0)
+    ? "lookup_products_asc"
+    : "lookup_products_desc",
+    params,
+    &lookup_products_cb,
+    &plc);
   /* If there was an error inside lookup_products_cb, return a hard error. */
   if (plc.extract_failed)
     return GNUNET_DB_STATUS_HARD_ERROR;
diff --git a/src/backenddb/pg_lookup_products.h 
b/src/backenddb/pg_lookup_products.h
index 398b5eac..d96328c8 100644
--- a/src/backenddb/pg_lookup_products.h
+++ b/src/backenddb/pg_lookup_products.h
@@ -30,6 +30,9 @@
  *
  * @param cls closure
  * @param instance_id instance to lookup products for
+ * @param offset transfer_serial number of the transfer we want to offset from
+ * @param limit number of entries to return, negative for descending,
+ *                positive for ascending
  * @param cb function to call on all products found
  * @param cb_cls closure for @a cb
  * @return database result code
@@ -37,6 +40,8 @@
 enum GNUNET_DB_QueryStatus
 TMH_PG_lookup_products (void *cls,
                         const char *instance_id,
+                        uint64_t offset,
+                        int64_t limit,
                         TALER_MERCHANTDB_ProductsCallback cb,
                         void *cb_cls);
 
diff --git a/src/backenddb/test_merchantdb.c b/src/backenddb/test_merchantdb.c
index 53902b3d..60a0b08b 100644
--- a/src/backenddb/test_merchantdb.c
+++ b/src/backenddb/test_merchantdb.c
@@ -906,13 +906,17 @@ struct TestLookupProducts_Closure
  * Function called after calling @e test_lookup_products
  *
  * @param cls a pointer to the lookup closure.
+ * @param product_serial DB row ID
  * @param product_id the identifier of the product found.
  */
 static void
 lookup_products_cb (void *cls,
+                    uint64_t product_serial,
                     const char *product_id)
 {
   struct TestLookupProducts_Closure *cmp = cls;
+
+  GNUNET_assert (product_serial > 0);
   if (NULL == cmp)
     return;
   cmp->results_length += 1;
@@ -948,6 +952,8 @@ test_lookup_products (const struct InstanceData *instance,
   memset (results_matching, 0, sizeof (unsigned int) * products_length);
   if (0 > plugin->lookup_products (plugin->cls,
                                    instance->instance.id,
+                                   0,
+                                   20,
                                    &lookup_products_cb,
                                    &cls))
   {
diff --git a/src/include/taler_merchant_service.h 
b/src/include/taler_merchant_service.h
index 2ed51a29..6ddf3ee4 100644
--- a/src/include/taler_merchant_service.h
+++ b/src/include/taler_merchant_service.h
@@ -1386,6 +1386,10 @@ struct TALER_MERCHANT_InventoryEntry
    */
   const char *product_id;
 
+  /**
+   * Serial ID of the product.
+   */
+  uint64_t product_serial;
 };
 
 
diff --git a/src/include/taler_merchantdb_plugin.h 
b/src/include/taler_merchantdb_plugin.h
index 316b8678..404d0eb9 100644
--- a/src/include/taler_merchantdb_plugin.h
+++ b/src/include/taler_merchantdb_plugin.h
@@ -249,10 +249,12 @@ typedef void
  * Typically called by `lookup_products`.
  *
  * @param cls a `json_t *` JSON array to build
+ * @param product_serial row ID of the product
  * @param product_id ID of the product
  */
 typedef void
 (*TALER_MERCHANTDB_ProductsCallback)(void *cls,
+                                     uint64_t product_serial,
                                      const char *product_id);
 
 
@@ -1584,6 +1586,9 @@ struct TALER_MERCHANTDB_Plugin
    *
    * @param cls closure
    * @param instance_id instance to lookup products for
+   * @param offset transfer_serial number of the transfer we want to offset 
from
+   * @param limit number of entries to return, negative for descending,
+   *                positive for ascending
    * @param cb function to call on all products found
    * @param cb_cls closure for @a cb
    * @return database result code
@@ -1591,6 +1596,8 @@ struct TALER_MERCHANTDB_Plugin
   enum GNUNET_DB_QueryStatus
   (*lookup_products)(void *cls,
                      const char *instance_id,
+                     uint64_t offset,
+                     int64_t limit,
                      TALER_MERCHANTDB_ProductsCallback cb,
                      void *cb_cls);
 
diff --git a/src/lib/merchant_api_get_config.c 
b/src/lib/merchant_api_get_config.c
index 3f1471e3..3382c9f2 100644
--- a/src/lib/merchant_api_get_config.c
+++ b/src/lib/merchant_api_get_config.c
@@ -34,12 +34,12 @@
  * Which version of the Taler protocol is implemented
  * by this library?  Used to determine compatibility.
  */
-#define MERCHANT_PROTOCOL_CURRENT 11
+#define MERCHANT_PROTOCOL_CURRENT 12
 
 /**
  * How many configs are we backwards-compatible with?
  */
-#define MERCHANT_PROTOCOL_AGE 6
+#define MERCHANT_PROTOCOL_AGE 0
 
 
 /**
diff --git a/src/lib/merchant_api_get_products.c 
b/src/lib/merchant_api_get_products.c
index 01115094..21657cbd 100644
--- a/src/lib/merchant_api_get_products.c
+++ b/src/lib/merchant_api_get_products.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014-2023 Taler Systems SA
+  Copyright (C) 2014-2024 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU Lesser General Public License as published by the Free 
Software
@@ -89,6 +89,8 @@ parse_products (const json_t *json,
     struct GNUNET_JSON_Specification spec[] = {
       GNUNET_JSON_spec_string ("product_id",
                                &ie->product_id),
+      GNUNET_JSON_spec_uint64 ("product_serial",
+                               &ie->product_serial),
       GNUNET_JSON_spec_end ()
     };
 

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