summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2020-04-07 18:47:45 +0200
committerChristian Grothoff <christian@grothoff.org>2020-04-07 18:47:45 +0200
commite781a77a66d292ba28b4e7a11b460f07daca9232 (patch)
tree9159ea415de8579580db850a4ddeecb49add118c
parent7cfd98c849c6eb21a1d3b0909e18c51649894ac4 (diff)
downloadmerchant-e781a77a66d292ba28b4e7a11b460f07daca9232.tar.gz
merchant-e781a77a66d292ba28b4e7a11b460f07daca9232.tar.bz2
merchant-e781a77a66d292ba28b4e7a11b460f07daca9232.zip
fix #6129 (/refund idempotency)
-rw-r--r--src/backend/taler-merchant-httpd_refund_increase.c242
-rw-r--r--src/backend/taler-merchant-httpd_refund_lookup.c6
-rw-r--r--src/backenddb/plugin_merchantdb_postgres.c56
-rw-r--r--src/backenddb/test_merchantdb.c15
-rw-r--r--src/include/taler_merchantdb_plugin.h232
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 33cf4d99..99a5bcbc 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 36a6b88f..d54a87c3 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 0f547e3d..7ee776ba 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 ff1e2b0a..87b8c734 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 38c18863..cc2e6bd9 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