gnunet-svn
[Top][All Lists]
Advanced

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

[taler-merchant] branch master updated: fix #6129 (/refund idempotency)


From: gnunet
Subject: [taler-merchant] branch master updated: fix #6129 (/refund idempotency)
Date: Tue, 07 Apr 2020 18:47:47 +0200

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 e781a77  fix #6129 (/refund idempotency)
e781a77 is described below

commit e781a77a66d292ba28b4e7a11b460f07daca9232
Author: Christian Grothoff <address@hidden>
AuthorDate: Tue Apr 7 18:47:45 2020 +0200

    fix #6129 (/refund idempotency)
---
 src/backend/taler-merchant-httpd_refund_increase.c | 242 ++++++++++-----------
 src/backend/taler-merchant-httpd_refund_lookup.c   |   6 -
 src/backenddb/plugin_merchantdb_postgres.c         |  56 ++---
 src/backenddb/test_merchantdb.c                    |  15 +-
 src/include/taler_merchantdb_plugin.h              | 232 ++++++++++----------
 5 files changed, 256 insertions(+), 295 deletions(-)

diff --git a/src/backend/taler-merchant-httpd_refund_increase.c 
b/src/backend/taler-merchant-httpd_refund_increase.c
index 33cf4d9..99a5bcb 100644
--- a/src/backend/taler-merchant-httpd_refund_increase.c
+++ b/src/backend/taler-merchant-httpd_refund_increase.c
@@ -129,82 +129,26 @@ json_parse_cleanup (struct TM_HandlerContext *hc)
 
 
 /**
- * Handle request for increasing the refund associated with
- * a contract.
+ * Process a refund request.
  *
- * @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
- * @param mi merchant backend instance, never NULL
+ * @param connection HTTP client connection
+ * @param mi merchant instance doing the processing
+ * @param refund amount to be refunded
+ * @param order_id for which order is the refund
+ * @param reason reason for the refund
  * @return MHD result code
  */
-int
-MH_handler_refund_increase (struct TMH_RequestHandler *rh,
-                            struct MHD_Connection *connection,
-                            void **connection_cls,
-                            const char *upload_data,
-                            size_t *upload_data_size,
-                            struct MerchantInstance *mi)
+static int
+process_refund (struct MHD_Connection *connection,
+                struct MerchantInstance *mi,
+                const struct TALER_Amount *refund,
+                const char *order_id,
+                const char *reason)
 {
-  int res;
-  struct TMH_JsonParseContext *ctx;
-  struct TALER_Amount refund;
-  json_t *root;
   json_t *contract_terms;
-  const char *order_id;
-  const char *reason;
-  struct GNUNET_HashCode h_contract_terms;
-  struct GNUNET_CRYPTO_EddsaSignature sig;
-  struct GNUNET_JSON_Specification spec[] = {
-    TALER_JSON_spec_amount ("refund", &refund),
-    GNUNET_JSON_spec_string ("order_id", &order_id),
-    GNUNET_JSON_spec_string ("reason", &reason),
-    GNUNET_JSON_spec_end ()
-  };
   enum GNUNET_DB_QueryStatus qs;
   enum GNUNET_DB_QueryStatus qsx;
-
-  if (NULL == *connection_cls)
-  {
-    ctx = GNUNET_new (struct TMH_JsonParseContext);
-    ctx->hc.cc = &json_parse_cleanup;
-    *connection_cls = ctx;
-  }
-  else
-  {
-    ctx = *connection_cls;
-  }
-  res = TALER_MHD_parse_post_json (connection,
-                                   &ctx->json_parse_context,
-                                   upload_data,
-                                   upload_data_size,
-                                   &root);
-  if (GNUNET_SYSERR == res)
-    return MHD_NO;
-  /* the POST's body has to be further fetched */
-  if ( (GNUNET_NO == res) ||
-       (NULL == root) )
-    return MHD_YES;
-
-  res = TALER_MHD_parse_json_data (connection,
-                                   root,
-                                   spec);
-  if (GNUNET_NO == res)
-  {
-    GNUNET_break_op (0);
-    json_decref (root);
-    return MHD_YES;
-  }
-  if (GNUNET_SYSERR == res)
-  {
-    GNUNET_break_op (0);
-    json_decref (root);
-    return TALER_MHD_reply_with_error (connection,
-                                       MHD_HTTP_BAD_REQUEST,
-                                       TALER_EC_JSON_INVALID,
-                                       "Request body does not match 
specification");
-  }
+  struct GNUNET_HashCode h_contract_terms;
 
   db->preflight (db->cls);
   /* Convert order id to h_contract_terms */
@@ -219,7 +163,6 @@ MH_handler_refund_increase (struct TMH_RequestHandler *rh,
     GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
     /* Always report on hard error as well to enable diagnostics */
     GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
-    json_decref (root);
     return TALER_MHD_reply_with_error (connection,
                                        MHD_HTTP_INTERNAL_SERVER_ERROR,
                                        TALER_EC_REFUND_LOOKUP_DB_ERROR,
@@ -230,7 +173,6 @@ MH_handler_refund_increase (struct TMH_RequestHandler *rh,
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                 "Unknown order id given: `%s'\n",
                 order_id);
-    json_decref (root);
     return TALER_MHD_reply_with_error (connection,
                                        MHD_HTTP_NOT_FOUND,
                                        TALER_EC_REFUND_ORDER_ID_UNKNOWN,
@@ -242,14 +184,13 @@ MH_handler_refund_increase (struct TMH_RequestHandler *rh,
                        &h_contract_terms))
   {
     GNUNET_break (0);
-    GNUNET_JSON_parse_free (spec);
     json_decref (contract_terms);
-    json_decref (root);
     return TALER_MHD_reply_with_error (connection,
                                        MHD_HTTP_INTERNAL_SERVER_ERROR,
                                        TALER_EC_INTERNAL_LOGIC_ERROR,
                                        "Could not hash contract terms");
   }
+  json_decref (contract_terms);
   for (unsigned int i = 0; i<MAX_RETRIES; i++)
   {
     if (GNUNET_OK !=
@@ -257,14 +198,12 @@ MH_handler_refund_increase (struct TMH_RequestHandler *rh,
                    "increase refund"))
     {
       GNUNET_break (0);
-      json_decref (contract_terms);
-      json_decref (root);
       return GNUNET_DB_STATUS_HARD_ERROR;
     }
     qs = db->increase_refund_for_contract_NT (db->cls,
                                               &h_contract_terms,
                                               &mi->pubkey,
-                                              &refund,
+                                              refund,
                                               reason);
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "increase refund returned %d\n",
@@ -302,9 +241,6 @@ MH_handler_refund_increase (struct TMH_RequestHandler *rh,
     GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
     /* Always report on hard error as well to enable diagnostics */
     GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
-    GNUNET_JSON_parse_free (spec);
-    json_decref (contract_terms);
-    json_decref (root);
     return TALER_MHD_reply_with_error (connection,
                                        MHD_HTTP_INTERNAL_SERVER_ERROR,
                                        
TALER_EC_REFUND_MERCHANT_DB_COMMIT_ERROR,
@@ -312,53 +248,13 @@ MH_handler_refund_increase (struct TMH_RequestHandler *rh,
   }
   if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                "Refunded amount lower or equal to previous refund: %s\n",
-                TALER_amount2s (&refund));
-    GNUNET_JSON_parse_free (spec);
-    json_decref (contract_terms);
-    json_decref (root);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Refusing refund amount %s that is larger than original 
payment\n",
+                TALER_amount2s (refund));
     return TALER_MHD_reply_with_error (connection,
                                        MHD_HTTP_CONFLICT,
                                        TALER_EC_REFUND_INCONSISTENT_AMOUNT,
-                                       "Amount incorrect: not larger than the 
previous one");
-  }
-
-  /**
-   * Return to the frontend at this point.  The frontend will then return
-   * a "402 Payment required" carrying a "X-Taler-Refund-Url: www"
-   * where 'www' is the URL where the wallet can automatically fetch
-   * the refund permission.
-   *
-   * Just a "200 OK" should be fine here, as the frontend has all
-   * the information needed to generate the right response.
-   *///
-  {
-    struct TALER_MerchantRefundConfirmationPS confirmation = {
-      .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_REFUND_OK),
-      .purpose.size = htonl (sizeof (confirmation))
-    };
-
-    GNUNET_CRYPTO_hash (order_id,
-                        strlen (order_id),
-                        &confirmation.h_order_id);
-
-    if (GNUNET_OK !=
-        GNUNET_CRYPTO_eddsa_sign (&mi->privkey.eddsa_priv,
-                                  &confirmation.purpose,
-                                  &sig))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Failed to sign successful refund confirmation\n");
-      json_decref (contract_terms);
-      GNUNET_JSON_parse_free (spec);
-      json_decref (root);
-      return TALER_MHD_reply_with_error (connection,
-                                         MHD_HTTP_INTERNAL_SERVER_ERROR,
-                                         
TALER_EC_REFUND_MERCHANT_SIGNING_FAILED,
-                                         "Refund done, but failed to sign 
confirmation");
-
-    }
+                                       "Amount above payment");
   }
 
   {
@@ -368,18 +264,102 @@ MH_handler_refund_increase (struct TMH_RequestHandler 
*rh,
     taler_refund_uri = make_taler_refund_uri (connection,
                                               mi->id,
                                               order_id);
-    ret = TALER_MHD_reply_json_pack (connection,
-                                     MHD_HTTP_OK,
-                                     "{s:o, s:o, s:s}",
-                                     "sig", GNUNET_JSON_from_data_auto (&sig),
-                                     "contract_terms", contract_terms,
-                                     "taler_refund_uri", taler_refund_uri);
+    ret = TALER_MHD_reply_json_pack (
+      connection,
+      MHD_HTTP_OK,
+      "{s:o, s:s}",
+      "h_contract_terms",
+      GNUNET_JSON_from_data_auto (&h_contract_terms),
+      "taler_refund_url",
+      taler_refund_uri);
     GNUNET_free (taler_refund_uri);
-    GNUNET_JSON_parse_free (spec);
-    json_decref (root);
     return ret;
   }
 }
 
 
+/**
+ * Handle request for increasing the refund associated with
+ * a contract.
+ *
+ * @param connection the MHD connection to handle
+ * @param[in,out] connection_cls the connection's closure (can be updated)
+ * @param upload_data upload data
+ * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @param mi merchant backend instance, never NULL
+ * @return MHD result code
+ */
+int
+MH_handler_refund_increase (struct TMH_RequestHandler *rh,
+                            struct MHD_Connection *connection,
+                            void **connection_cls,
+                            const char *upload_data,
+                            size_t *upload_data_size,
+                            struct MerchantInstance *mi)
+{
+  int res;
+  struct TMH_JsonParseContext *ctx;
+  struct TALER_Amount refund;
+  const char *order_id;
+  const char *reason;
+  struct GNUNET_JSON_Specification spec[] = {
+    TALER_JSON_spec_amount ("refund", &refund),
+    GNUNET_JSON_spec_string ("order_id", &order_id),
+    GNUNET_JSON_spec_string ("reason", &reason),
+    GNUNET_JSON_spec_end ()
+  };
+  json_t *root;
+
+  if (NULL == *connection_cls)
+  {
+    ctx = GNUNET_new (struct TMH_JsonParseContext);
+    ctx->hc.cc = &json_parse_cleanup;
+    *connection_cls = ctx;
+  }
+  else
+  {
+    ctx = *connection_cls;
+  }
+
+  res = TALER_MHD_parse_post_json (connection,
+                                   &ctx->json_parse_context,
+                                   upload_data,
+                                   upload_data_size,
+                                   &root);
+  if (GNUNET_SYSERR == res)
+    return MHD_NO;
+  /* the POST's body has to be further fetched */
+  if ( (GNUNET_NO == res) ||
+       (NULL == root) )
+    return MHD_YES;
+
+  res = TALER_MHD_parse_json_data (connection,
+                                   root,
+                                   spec);
+  if (GNUNET_NO == res)
+  {
+    GNUNET_break_op (0);
+    json_decref (root);
+    return MHD_YES;
+  }
+  if (GNUNET_SYSERR == res)
+  {
+    GNUNET_break_op (0);
+    json_decref (root);
+    return TALER_MHD_reply_with_error (connection,
+                                       MHD_HTTP_BAD_REQUEST,
+                                       TALER_EC_JSON_INVALID,
+                                       "Request body does not match 
specification");
+  }
+  res = process_refund (connection,
+                        mi,
+                        &refund,
+                        order_id,
+                        reason);
+  GNUNET_JSON_parse_free (spec);
+  json_decref (root);
+  return res;
+}
+
+
 /* end of taler-merchant-httpd_refund_increase.c */
diff --git a/src/backend/taler-merchant-httpd_refund_lookup.c 
b/src/backend/taler-merchant-httpd_refund_lookup.c
index 36a6b88..d54a87c 100644
--- a/src/backend/taler-merchant-httpd_refund_lookup.c
+++ b/src/backend/taler-merchant-httpd_refund_lookup.c
@@ -25,12 +25,6 @@
 #include "taler-merchant-httpd.h"
 #include "taler-merchant-httpd_refund.h"
 
-/**
- * How often do we retry the non-trivial refund INSERT database
- * transaction?
- */
-#define MAX_RETRIES 5
-
 
 /**
  * Return refund situation about a contract.
diff --git a/src/backenddb/plugin_merchantdb_postgres.c 
b/src/backenddb/plugin_merchantdb_postgres.c
index 0f547e3..7ee776b 100644
--- a/src/backenddb/plugin_merchantdb_postgres.c
+++ b/src/backenddb/plugin_merchantdb_postgres.c
@@ -2054,7 +2054,7 @@ process_refund_cb (void *cls,
 
 
 /**
- * Closure for #process_deposits_cb.
+ * Closure for #process_deposits_for_refund_cb.
  */
 struct InsertRefundContext
 {
@@ -2198,7 +2198,9 @@ process_deposits_for_refund_cb (void *cls,
   if (0 >= TALER_amount_cmp (ctx->refund,
                              &current_refund))
   {
-    ctx->qs = GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Existing refund of %s at or above requested refund. Finished 
early.\n",
+                TALER_amount2s (&current_refund));
     return;
   }
 
@@ -2301,11 +2303,11 @@ process_deposits_for_refund_cb (void *cls,
    * Although this should be checked as the business should never
    * issue a refund bigger than the contract's actual price, we cannot
    * rely upon the frontend being correct.
-   */GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+   *///
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
               "The refund of %s is bigger than the order's value\n",
               TALER_amount2s (ctx->refund));
-
-  ctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
+  ctx->qs = GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
 }
 
 
@@ -2322,39 +2324,40 @@ process_deposits_for_refund_cb (void *cls,
  * @param reason 0-terminated UTF-8 string giving the reason why the customer
  *               got a refund (free form, business-specific)
  * @return transaction status
- *         #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if the refund is accepted
- *         #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if the refund cannot be 
issued: this can happen for two
- *               reasons: the issued refund is not greater of the previous 
refund,
- *               or the coins don't have enough amount left to pay for this 
refund.
+ *        #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if @a refund is ABOVE the 
amount we
+ *        were originally paid and thus the transaction failed;
+ *        #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if the request is valid,
+ *        regardless of whether it actually increased the refund beyond
+ *        what was already refunded (idempotency!)
  */
 static enum GNUNET_DB_QueryStatus
-postgres_increase_refund_for_contract_NT (void *cls,
-                                          const struct
-                                          GNUNET_HashCode *h_contract_terms,
-                                          const struct
-                                          TALER_MerchantPublicKeyP 
*merchant_pub,
-                                          const struct TALER_Amount *refund,
-                                          const char *reason)
+postgres_increase_refund_for_contract_NT (
+  void *cls,
+  const struct GNUNET_HashCode *h_contract_terms,
+  const struct TALER_MerchantPublicKeyP *merchant_pub,
+  const struct TALER_Amount *refund,
+  const char *reason)
 {
   struct PostgresClosure *pg = cls;
-  struct InsertRefundContext ctx;
   enum GNUNET_DB_QueryStatus qs;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
     GNUNET_PQ_query_param_auto_from_type (merchant_pub),
     GNUNET_PQ_query_param_end
   };
+  struct InsertRefundContext ctx = {
+    .pg = pg,
+    .qs = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT,
+    .refund = refund,
+    .reason = reason,
+    .h_contract_terms = h_contract_terms,
+    .merchant_pub = merchant_pub
+  };
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Asked to refund %s on contract %s\n",
               TALER_amount2s (refund),
               GNUNET_h2s (h_contract_terms));
-  ctx.pg = pg;
-  ctx.qs = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
-  ctx.refund = refund;
-  ctx.reason = reason;
-  ctx.h_contract_terms = h_contract_terms;
-  ctx.merchant_pub = merchant_pub;
   qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
                                              "find_deposits",
                                              params,
@@ -2363,11 +2366,8 @@ postgres_increase_refund_for_contract_NT (void *cls,
   switch (qs)
   {
   case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Unknown contract: %s (merchant_pub: %s), no refund 
possible\n",
-                GNUNET_h2s (h_contract_terms),
-                TALER_B2S (merchant_pub));
-    return qs;
+    /* never paid, means we clearly cannot refund anything */
+    return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
   case GNUNET_DB_STATUS_SOFT_ERROR:
   case GNUNET_DB_STATUS_HARD_ERROR:
     return qs;
diff --git a/src/backenddb/test_merchantdb.c b/src/backenddb/test_merchantdb.c
index ff1e2b0..87b8c73 100644
--- a/src/backenddb/test_merchantdb.c
+++ b/src/backenddb/test_merchantdb.c
@@ -981,21 +981,19 @@ run (void *cls)
                                                    &refund_amount,
                                                    "refund testing"));
 
-  FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->increase_refund_for_contract_NT (plugin->cls,
                                                    &h_contract_terms,
                                                    &merchant_pub,
                                                    &refund_amount,
                                                    "same refund amount as "
-                                                   "the previous one, should 
succeed without changes (0)"));
-
-  /*Should fail as this refund a lesser amount respect to the previous one*/
-  FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
+                                                   "the previous one, should 
succeed without changes (1)"));
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->increase_refund_for_contract_NT (plugin->cls,
                                                    &h_contract_terms,
                                                    &merchant_pub,
                                                    &little_refund_amount,
-                                                   "lower refund amount as the 
previous one, should succeed without changes (0)"));
+                                                   "lower refund amount as the 
previous one, should succeed without changes (1)"));
   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->increase_refund_for_contract_NT (plugin->cls,
                                                    &h_contract_terms,
@@ -1003,13 +1001,12 @@ run (void *cls)
                                                    &right_second_refund_amount,
                                                    "right refund increase"));
 
-  FAILIF (GNUNET_DB_STATUS_HARD_ERROR !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
           plugin->increase_refund_for_contract_NT (plugin->cls,
                                                    &h_contract_terms,
                                                    &merchant_pub,
                                                    &too_big_refund_amount,
-                                                   "make refund testing fail 
due"
-                                                   " to too big refund 
amount"));
+                                                   "make refund testing fail 
due to too big refund amount"));
 
   FAILIF (GNUNET_OK !=
           test_wire_fee ());
diff --git a/src/include/taler_merchantdb_plugin.h 
b/src/include/taler_merchantdb_plugin.h
index 38c1886..cc2e6bd 100644
--- a/src/include/taler_merchantdb_plugin.h
+++ b/src/include/taler_merchantdb_plugin.h
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014-2017 INRIA
+  Copyright (C) 2014-2020 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
@@ -58,16 +58,14 @@ typedef void
  * @param total_amount total amount we receive for the contract after fees
  */
 typedef void
-(*TALER_MERCHANTDB_TransactionCallback)(void *cls,
-                                        const struct
-                                        TALER_MerchantPublicKeyP *merchant_pub,
-                                        const struct
-                                        GNUNET_HashCode *h_contract_terms,
-                                        const struct GNUNET_HashCode *h_wire,
-                                        struct GNUNET_TIME_Absolute timestamp,
-                                        struct GNUNET_TIME_Absolute refund,
-                                        const struct
-                                        TALER_Amount *total_amount);
+(*TALER_MERCHANTDB_TransactionCallback)(
+  void *cls,
+  const struct TALER_MerchantPublicKeyP *merchant_pub,
+  const struct GNUNET_HashCode *h_contract_terms,
+  const struct GNUNET_HashCode *h_wire,
+  struct GNUNET_TIME_Absolute timestamp,
+  struct GNUNET_TIME_Absolute refund,
+  const struct TALER_Amount *total_amount);
 
 
 /**
@@ -85,18 +83,16 @@ typedef void
  *        matches the `interface DepositSuccess` of the documentation.
  */
 typedef void
-(*TALER_MERCHANTDB_CoinDepositCallback)(void *cls,
-                                        const struct
-                                        GNUNET_HashCode *h_contract_terms,
-                                        const struct
-                                        TALER_CoinSpendPublicKeyP *coin_pub,
-                                        const char *exchange_url,
-                                        const struct
-                                        TALER_Amount *amount_with_fee,
-                                        const struct TALER_Amount *deposit_fee,
-                                        const struct TALER_Amount *refund_fee,
-                                        const struct TALER_Amount *wire_fee,
-                                        const json_t *exchange_proof);
+(*TALER_MERCHANTDB_CoinDepositCallback)(
+  void *cls,
+  const struct GNUNET_HashCode *h_contract_terms,
+  const struct TALER_CoinSpendPublicKeyP *coin_pub,
+  const char *exchange_url,
+  const struct TALER_Amount *amount_with_fee,
+  const struct TALER_Amount *deposit_fee,
+  const struct TALER_Amount *refund_fee,
+  const struct TALER_Amount *wire_fee,
+  const json_t *exchange_proof);
 
 
 /**
@@ -117,15 +113,13 @@ typedef void
  *             NULL if we have not asked for this signature
  */
 typedef void
-(*TALER_MERCHANTDB_TransferCallback)(void *cls,
-                                     const struct
-                                     GNUNET_HashCode *h_contract_terms,
-                                     const struct
-                                     TALER_CoinSpendPublicKeyP *coin_pub,
-                                     const struct
-                                     TALER_WireTransferIdentifierRawP *wtid,
-                                     struct GNUNET_TIME_Absolute 
execution_time,
-                                     const json_t *exchange_proof);
+(*TALER_MERCHANTDB_TransferCallback)(
+  void *cls,
+  const struct GNUNET_HashCode *h_contract_terms,
+  const struct TALER_CoinSpendPublicKeyP *coin_pub,
+  const struct TALER_WireTransferIdentifierRawP *wtid,
+  struct GNUNET_TIME_Absolute execution_time,
+  const json_t *exchange_proof);
 
 
 /**
@@ -150,13 +144,13 @@ typedef void
  * @param refund_fee cost of this refund operation
  */
 typedef void
-(*TALER_MERCHANTDB_RefundCallback)(void *cls,
-                                   const struct
-                                   TALER_CoinSpendPublicKeyP *coin_pub,
-                                   uint64_t rtransaction_id,
-                                   const char *reason,
-                                   const struct TALER_Amount *refund_amount,
-                                   const struct TALER_Amount *refund_fee);
+(*TALER_MERCHANTDB_RefundCallback)(
+  void *cls,
+  const struct TALER_CoinSpendPublicKeyP *coin_pub,
+  uint64_t rtransaction_id,
+  const char *reason,
+  const struct TALER_Amount *refund_amount,
+  const struct TALER_Amount *refund_fee);
 
 
 /**
@@ -325,12 +319,11 @@ struct TALER_MERCHANTDB_Plugin
    * @return transaction status
    */
   enum GNUNET_DB_QueryStatus
-  (*find_contract_terms_from_hash)(void *cls,
-                                   json_t **contract_terms,
-                                   const struct
-                                   GNUNET_HashCode *h_contract_terms,
-                                   const struct
-                                   TALER_MerchantPublicKeyP *merchant_pub);
+  (*find_contract_terms_from_hash)(
+    void *cls,
+    json_t **contract_terms,
+    const struct GNUNET_HashCode *h_contract_terms,
+    const struct TALER_MerchantPublicKeyP *merchant_pub);
 
 
   /**
@@ -343,12 +336,11 @@ struct TALER_MERCHANTDB_Plugin
    * @return transaction status
    */
   enum GNUNET_DB_QueryStatus
-  (*find_paid_contract_terms_from_hash)(void *cls,
-                                        json_t **contract_terms,
-                                        const struct
-                                        GNUNET_HashCode *h_contract_terms,
-                                        const struct
-                                        TALER_MerchantPublicKeyP 
*merchant_pub);
+  (*find_paid_contract_terms_from_hash)(
+    void *cls,
+    json_t **contract_terms,
+    const struct GNUNET_HashCode *h_contract_terms,
+    const struct TALER_MerchantPublicKeyP *merchant_pub);
 
 
   /**
@@ -371,18 +363,16 @@ struct TALER_MERCHANTDB_Plugin
    * @return transaction status
    */
   enum GNUNET_DB_QueryStatus
-  (*find_contract_terms_by_date_and_range)(void *cls,
-                                           struct GNUNET_TIME_Absolute date,
-                                           const struct
-                                           TALER_MerchantPublicKeyP *
-                                           merchant_pub,
-                                           uint64_t start,
-                                           uint64_t nrows,
-                                           int past,
-                                           unsigned int ascending,
-                                           
TALER_MERCHANTDB_ProposalDataCallback
-                                           cb,
-                                           void *cb_cls);
+  (*find_contract_terms_by_date_and_range)(
+    void *cls,
+    struct GNUNET_TIME_Absolute date,
+    const struct TALER_MerchantPublicKeyP *merchant_pub,
+    uint64_t start,
+    uint64_t nrows,
+    int past,
+    unsigned int ascending,
+    TALER_MERCHANTDB_ProposalDataCallback cb,
+    void *cb_cls);
 
   /**
    * Lookup for a proposal, respecting the signature used by the
@@ -396,12 +386,12 @@ struct TALER_MERCHANTDB_Plugin
    * @return transaction status
    */
   enum GNUNET_DB_QueryStatus
-  (*find_contract_terms_history)(void *cls,
-                                 const char *order_id,
-                                 const struct
-                                 TALER_MerchantPublicKeyP *merchant_pub,
-                                 TALER_MERCHANTDB_ProposalDataCallback cb,
-                                 void *cb_cls);
+  (*find_contract_terms_history)(
+    void *cls,
+    const char *order_id,
+    const struct TALER_MerchantPublicKeyP *merchant_pub,
+    TALER_MERCHANTDB_ProposalDataCallback cb,
+    void *cb_cls);
 
 
   /**
@@ -418,13 +408,13 @@ struct TALER_MERCHANTDB_Plugin
    * @return transaction status
    */
   enum GNUNET_DB_QueryStatus
-  (*find_contract_terms_by_date)(void *cls,
-                                 struct GNUNET_TIME_Absolute date,
-                                 const struct
-                                 TALER_MerchantPublicKeyP *merchant_pub,
-                                 uint64_t nrows,
-                                 TALER_MERCHANTDB_ProposalDataCallback cb,
-                                 void *cb_cls);
+  (*find_contract_terms_by_date)(
+    void *cls,
+    struct GNUNET_TIME_Absolute date,
+    const struct TALER_MerchantPublicKeyP *merchant_pub,
+    uint64_t nrows,
+    TALER_MERCHANTDB_ProposalDataCallback cb,
+    void *cb_cls);
 
 
   /**
@@ -468,11 +458,11 @@ struct TALER_MERCHANTDB_Plugin
    * @return transaction status
    */
   enum GNUNET_DB_QueryStatus
-  (*store_coin_to_transfer)(void *cls,
-                            const struct GNUNET_HashCode *h_contract_terms,
-                            const struct TALER_CoinSpendPublicKeyP *coin_pub,
-                            const struct
-                            TALER_WireTransferIdentifierRawP *wtid);
+  (*store_coin_to_transfer)(
+    void *cls,
+    const struct GNUNET_HashCode *h_contract_terms,
+    const struct TALER_CoinSpendPublicKeyP *coin_pub,
+    const struct TALER_WireTransferIdentifierRawP *wtid);
 
 
   /**
@@ -487,13 +477,13 @@ struct TALER_MERCHANTDB_Plugin
    * @return transaction status
    */
   enum GNUNET_DB_QueryStatus
-  (*store_transfer_to_proof)(void *cls,
-                             const char *exchange_url,
-                             const struct
-                             TALER_WireTransferIdentifierRawP *wtid,
-                             struct GNUNET_TIME_Absolute execution_time,
-                             const struct TALER_ExchangePublicKeyP 
*signkey_pub,
-                             const json_t *exchange_proof);
+  (*store_transfer_to_proof)(
+    void *cls,
+    const char *exchange_url,
+    const struct TALER_WireTransferIdentifierRawP *wtid,
+    struct GNUNET_TIME_Absolute execution_time,
+    const struct TALER_ExchangePublicKeyP *signkey_pub,
+    const json_t *exchange_proof);
 
 
   /**
@@ -512,16 +502,15 @@ struct TALER_MERCHANTDB_Plugin
    * @return transaction status code
    */
   enum GNUNET_DB_QueryStatus
-  (*store_wire_fee_by_exchange)(void *cls,
-                                const struct
-                                TALER_MasterPublicKeyP *exchange_pub,
-                                const struct GNUNET_HashCode *h_wire_method,
-                                const struct TALER_Amount *wire_fee,
-                                const struct TALER_Amount *closing_fee,
-                                struct GNUNET_TIME_Absolute start_date,
-                                struct GNUNET_TIME_Absolute end_date,
-                                const struct
-                                TALER_MasterSignatureP *exchange_sig);
+  (*store_wire_fee_by_exchange)(
+    void *cls,
+    const struct TALER_MasterPublicKeyP *exchange_pub,
+    const struct GNUNET_HashCode *h_wire_method,
+    const struct TALER_Amount *wire_fee,
+    const struct TALER_Amount *closing_fee,
+    struct GNUNET_TIME_Absolute start_date,
+    struct GNUNET_TIME_Absolute end_date,
+    const struct TALER_MasterSignatureP *exchange_sig);
 
 
   /**
@@ -556,15 +545,13 @@ struct TALER_MERCHANTDB_Plugin
    * @return transaction status
    */
   enum GNUNET_DB_QueryStatus
-  (*find_payments_by_hash_and_coin)(void *cls,
-                                    const struct
-                                    GNUNET_HashCode *h_contract_terms,
-                                    const struct
-                                    TALER_MerchantPublicKeyP *merchant_pub,
-                                    const struct
-                                    TALER_CoinSpendPublicKeyP *coin_pub,
-                                    TALER_MERCHANTDB_CoinDepositCallback cb,
-                                    void *cb_cls);
+  (*find_payments_by_hash_and_coin)(
+    void *cls,
+    const struct GNUNET_HashCode *h_contract_terms,
+    const struct TALER_MerchantPublicKeyP *merchant_pub,
+    const struct TALER_CoinSpendPublicKeyP *coin_pub,
+    TALER_MERCHANTDB_CoinDepositCallback cb,
+    void *cb_cls);
 
 
   /**
@@ -663,15 +650,19 @@ struct TALER_MERCHANTDB_Plugin
    * @param reason 0-terminated UTF-8 string giving the reason why the customer
    *               got a refund (free form, business-specific)
    * @return transaction status
+   *        #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if @a refund is ABOVE the 
amount we
+   *        were originally paid and thus the transaction failed;
+   *        #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if the request is valid,
+   *        regardless of whether it actually increased the refund beyond
+   *        what was already refunded (idempotency!)
    */
   enum GNUNET_DB_QueryStatus
-  (*increase_refund_for_contract_NT)(void *cls,
-                                     const struct
-                                     GNUNET_HashCode *h_contract_terms,
-                                     const struct
-                                     TALER_MerchantPublicKeyP *merchant_pub,
-                                     const struct TALER_Amount *refund,
-                                     const char *reason);
+  (*increase_refund_for_contract_NT)(
+    void *cls,
+    const struct GNUNET_HashCode *h_contract_terms,
+    const struct TALER_MerchantPublicKeyP *merchant_pub,
+    const struct TALER_Amount *refund,
+    const char *reason);
 
 
   /**
@@ -685,13 +676,12 @@ struct TALER_MERCHANTDB_Plugin
    * @return transaction status
    */
   enum GNUNET_DB_QueryStatus
-  (*get_refunds_from_contract_terms_hash)(void *cls,
-                                          const struct
-                                          TALER_MerchantPublicKeyP 
*merchant_pub,
-                                          const struct
-                                          GNUNET_HashCode *h_contract_terms,
-                                          TALER_MERCHANTDB_RefundCallback rc,
-                                          void *rc_cls);
+  (*get_refunds_from_contract_terms_hash)(
+    void *cls,
+    const struct TALER_MerchantPublicKeyP *merchant_pub,
+    const struct GNUNET_HashCode *h_contract_terms,
+    TALER_MERCHANTDB_RefundCallback rc,
+    void *rc_cls);
 
   /**
    * Add @a credit to a reserve to be used for tipping.  Note that

-- 
To stop receiving notification emails like this one, please contact
address@hidden.



reply via email to

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