commit 8fc8be0d00a68091204d4fcc12430a297baf3df0
parent d989aa1389eef18d82639edf0a058e1a3a5ec5a1
Author: Christian Grothoff <christian@grothoff.org>
Date: Thu, 17 Jul 2025 14:27:32 +0200
fix #10185
Diffstat:
3 files changed, 140 insertions(+), 90 deletions(-)
diff --git a/src/backend/taler-merchant-httpd_config.c b/src/backend/taler-merchant-httpd_config.c
@@ -43,7 +43,7 @@
* #MERCHANT_PROTOCOL_CURRENT and #MERCHANT_PROTOCOL_AGE in
* merchant_api_config.c!
*/
-#define MERCHANT_PROTOCOL_VERSION "20:0:17"
+#define MERCHANT_PROTOCOL_VERSION "21:0:0"
/**
diff --git a/src/backend/taler-merchant-httpd_private-get-orders.c b/src/backend/taler-merchant-httpd_private-get-orders.c
@@ -20,6 +20,7 @@
*/
#include "platform.h"
#include "taler-merchant-httpd_private-get-orders.h"
+#include <taler/taler_merchant_util.h>
#include <taler/taler_json_lib.h>
#include <taler/taler_dbevents.h>
@@ -302,11 +303,12 @@ add_order (void *cls,
json_t *contract_terms = NULL;
struct TALER_PrivateContractHashP h_contract_terms;
enum GNUNET_DB_QueryStatus qs;
- const char *summary;
char *order_id = NULL;
bool refundable = false;
bool paid;
- struct TALER_Amount order_amount;
+ bool wired;
+ struct TALER_MERCHANT_Contract *contract = NULL;
+ int16_t choice_index = -1;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Adding order `%s' (%llu) to result set at instance `%s'\n",
@@ -341,13 +343,19 @@ add_order (void *cls,
{
/* First try to find the order in the contracts */
uint64_t os;
-
- qs = TMH_db->lookup_contract_terms (TMH_db->cls,
- po->instance_id,
- order_id,
- &contract_terms,
- &os,
- NULL);
+ bool session_matches;
+
+ qs = TMH_db->lookup_contract_terms3 (TMH_db->cls,
+ po->instance_id,
+ order_id,
+ NULL,
+ &contract_terms,
+ &os,
+ &paid,
+ &wired,
+ &session_matches,
+ NULL,
+ &choice_index);
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
GNUNET_break (os == order_serial);
}
@@ -356,6 +364,8 @@ add_order (void *cls,
/* Might still be unclaimed, so try order table */
struct TALER_MerchantPostDataHashP unused;
+ paid = false;
+ wired = false;
qs = TMH_db->lookup_order (TMH_db->cls,
po->instance_id,
order_id,
@@ -368,112 +378,152 @@ add_order (void *cls,
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Order %llu disappeared during iteration. Skipping.\n",
(unsigned long long) order_serial);
- json_decref (contract_terms); /* should still be NULL */
- GNUNET_free (order_id);
- return;
+ goto cleanup;
}
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
{
GNUNET_break (0);
po->result = TALER_EC_GENERIC_DB_FETCH_FAILED;
- json_decref (contract_terms);
- GNUNET_free (order_id);
- return;
+ goto cleanup;
}
+ contract = TALER_MERCHANT_contract_parse (contract_terms,
+ true);
+ if (NULL == contract)
{
- struct GNUNET_TIME_Timestamp rd;
- struct GNUNET_JSON_Specification spec[] = {
- TALER_JSON_spec_amount_any ("amount",
- &order_amount),
- GNUNET_JSON_spec_timestamp ("refund_deadline",
- &rd),
- GNUNET_JSON_spec_string ("summary",
- &summary),
- GNUNET_JSON_spec_end ()
+ GNUNET_break (0);
+ po->result = TALER_EC_MERCHANT_GENERIC_DB_CONTRACT_CONTENT_INVALID;
+ goto cleanup;
+ }
+
+ if (GNUNET_TIME_absolute_is_future (
+ contract->refund_deadline.abs_time) &&
+ paid)
+ {
+ struct ProcessRefundsClosure prc = {
+ .ec = TALER_EC_NONE
};
+ const struct TALER_Amount *brutto;
- if (GNUNET_OK !=
- GNUNET_JSON_parse (contract_terms,
- spec,
- NULL, NULL))
+ switch (contract->version)
{
+ case TALER_MERCHANT_CONTRACT_VERSION_0:
+ brutto = &contract->details.v0.brutto;
+ break;
+ case TALER_MERCHANT_CONTRACT_VERSION_1:
+ {
+ struct TALER_MERCHANT_ContractChoice *choice
+ = &contract->details.v1.choices[choice_index];
+
+ GNUNET_assert (choice_index < contract->details.v1.choices_len);
+ brutto = &choice->amount;
+ }
+ break;
+ default:
GNUNET_break (0);
- po->result = TALER_EC_MERCHANT_GENERIC_DB_CONTRACT_CONTENT_INVALID;
- json_decref (contract_terms);
- GNUNET_free (order_id);
- return;
+ goto cleanup;
+ }
+
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (brutto->currency,
+ &prc.total_refund_amount));
+ qs = TMH_db->lookup_refunds_detailed (TMH_db->cls,
+ po->instance_id,
+ &h_contract_terms,
+ &process_refunds_cb,
+ &prc);
+ if (0 > qs)
+ {
+ GNUNET_break (0);
+ po->result = TALER_EC_GENERIC_DB_FETCH_FAILED;
+ goto cleanup;
}
+ if (TALER_EC_NONE != prc.ec)
+ {
+ GNUNET_break (0);
+ po->result = prc.ec;
+ goto cleanup;
+ }
+ if (0 > TALER_amount_cmp (&prc.total_refund_amount,
+ brutto))
+ refundable = true;
+ }
- if (TALER_amount_is_zero (&order_amount) &&
+ switch (contract->version)
+ {
+ case TALER_MERCHANT_CONTRACT_VERSION_0:
+ if (TALER_amount_is_zero (&contract->details.v0.brutto) &&
(po->of.wired != TALER_EXCHANGE_YNA_ALL) )
{
/* If we are actually filtering by wire status,
and the order was over an amount of zero,
do not return it as wire status is not
exactly meaningful for orders over zero. */
- json_decref (contract_terms);
- GNUNET_free (order_id);
- return;
+ goto cleanup;
}
-
- if (GNUNET_TIME_absolute_is_future (rd.abs_time) &&
- paid)
+ GNUNET_assert (
+ 0 ==
+ json_array_append_new (
+ po->pa,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("order_id",
+ contract->order_id),
+ GNUNET_JSON_pack_uint64 ("row_id",
+ order_serial),
+ GNUNET_JSON_pack_timestamp ("timestamp",
+ creation_time),
+ TALER_JSON_pack_amount (
+ "amount",
+ &contract->details.v0.brutto),
+ GNUNET_JSON_pack_string ("summary",
+ contract->summary),
+ GNUNET_JSON_pack_bool ("refundable",
+ refundable),
+ GNUNET_JSON_pack_bool ("paid",
+ paid))));
+ break;
+ case TALER_MERCHANT_CONTRACT_VERSION_1:
+ if (-1 == choice_index)
+ choice_index = 0; /* default choice */
+ GNUNET_assert (choice_index < contract->details.v1.choices_len);
{
- struct ProcessRefundsClosure prc = {
- .ec = TALER_EC_NONE
- };
-
- GNUNET_assert (GNUNET_OK ==
- TALER_amount_set_zero (order_amount.currency,
- &prc.total_refund_amount));
- qs = TMH_db->lookup_refunds_detailed (TMH_db->cls,
- po->instance_id,
- &h_contract_terms,
- &process_refunds_cb,
- &prc);
- if (0 > qs)
- {
- GNUNET_break (0);
- po->result = TALER_EC_GENERIC_DB_FETCH_FAILED;
- json_decref (contract_terms);
- GNUNET_free (order_id);
- return;
- }
- if (TALER_EC_NONE != prc.ec)
- {
- GNUNET_break (0);
- po->result = prc.ec;
- json_decref (contract_terms);
- GNUNET_free (order_id);
- return;
- }
- if (0 > TALER_amount_cmp (&prc.total_refund_amount,
- &order_amount))
- refundable = true;
+ struct TALER_MERCHANT_ContractChoice *choice
+ = &contract->details.v1.choices[choice_index];
+
+ GNUNET_assert (
+ 0 ==
+ json_array_append_new (
+ po->pa,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("order_id",
+ contract->order_id),
+ GNUNET_JSON_pack_uint64 ("row_id",
+ order_serial),
+ GNUNET_JSON_pack_timestamp ("timestamp",
+ creation_time),
+ TALER_JSON_pack_amount ("amount",
+ &choice->amount),
+ GNUNET_JSON_pack_string ("summary",
+ contract->summary),
+ GNUNET_JSON_pack_bool ("refundable",
+ refundable),
+ GNUNET_JSON_pack_bool ("paid",
+ paid))));
}
+ break;
+ default:
+ GNUNET_break (0);
+ goto cleanup;
}
- GNUNET_assert (0 ==
- json_array_append_new (
- po->pa,
- GNUNET_JSON_PACK (
- GNUNET_JSON_pack_string ("order_id",
- order_id),
- GNUNET_JSON_pack_uint64 ("row_id",
- order_serial),
- GNUNET_JSON_pack_timestamp ("timestamp",
- creation_time),
- TALER_JSON_pack_amount ("amount",
- &order_amount),
- GNUNET_JSON_pack_string ("summary",
- summary),
- GNUNET_JSON_pack_bool ("refundable",
- refundable),
- GNUNET_JSON_pack_bool ("paid",
- paid))));
+cleanup:
json_decref (contract_terms);
GNUNET_free (order_id);
+ if (NULL != contract)
+ {
+ TALER_MERCHANT_contract_free (contract);
+ contract = NULL;
+ }
}
diff --git a/src/backenddb/pg_lookup_statistics_counter_by_interval.c b/src/backenddb/pg_lookup_statistics_counter_by_interval.c
@@ -155,7 +155,7 @@ TMH_PG_lookup_statistics_counter_by_interval (
struct LookupCounterStatisticsContext context = {
.cb = cb,
.cb_cls = cb_cls,
- /* Can be overwritten by the lookup_token_families_cb */
+ /* Can be overwritten by the lookup_statistics_counter_by_interval_cb */
.extract_failed = false,
.description = NULL
};