merchant

Merchant backend to process payments, run by merchants
Log | Files | Refs | Submodules | README | LICENSE

commit 7b76f21accd51cea246b26ccb378a9f26114ec27
parent 733659b83b5e66ce07195a955ab6f1c38489545d
Author: Christian Grothoff <christian@grothoff.org>
Date:   Tue, 23 Sep 2025 17:09:25 +0200

fix #10444

Diffstat:
Msrc/backend/taler-merchant-donaukeyupdate.c | 90++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Msrc/backenddb/pg_select_donau_instances.c | 108++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
Msrc/backenddb/pg_select_donau_instances.h | 4++--
Msrc/include/taler_merchant_donau.h | 4++--
Msrc/include/taler_merchantdb_plugin.h | 1+
5 files changed, 188 insertions(+), 19 deletions(-)

diff --git a/src/backend/taler-merchant-donaukeyupdate.c b/src/backend/taler-merchant-donaukeyupdate.c @@ -17,6 +17,7 @@ * @file taler-merchant-donaukeyupdate.c * @brief Process that ensures our /keys data for all Donau instances is current * @author Bohdan Potuzhnyi + * @author Christian Grothoff */ #include "platform.h" #include "microhttpd.h" @@ -728,7 +729,6 @@ force_donau_charity_id (void *cls, extra, sizeof(uint64_t)); di_serial = GNUNET_ntohll (di_serial); - qs = db_plugin->select_donau_instance_by_serial (db_plugin->cls, di_serial, &donau_url, @@ -809,7 +809,8 @@ force_donau_keys (void *cls, if (NULL == d) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Donau instance `%s' not found. Creating new instance.\n", url); + "Donau instance `%s' not found. Creating new instance.\n", + url); d = GNUNET_new (struct Donau); d->donau_url = GNUNET_strdup (url); @@ -910,6 +911,75 @@ shutdown_task (void *cls) /** + * Callback function typically used by `select_donau_instances` to handle + * the details of each Donau instance retrieved from the database. + * + * @param cls Closure to pass additional context or data to the callback function. + * @param donau_instance_serial Serial number of the Donau instance in the merchant database. + * @param donau_url The URL of the Donau instance. + * @param charity_name The name of the charity associated with the Donau instance. + * @param charity_pub_key Pointer to the charity's public key used for cryptographic operations. + * @param charity_id The unique identifier for the charity within the Donau instance. + * @param charity_max_per_year Maximum allowed donations to the charity for the current year. + * @param charity_receipts_to_date Total donations received by the charity so far in the current year. + * @param current_year The year for which the donation data is being tracked. + * @param donau_keys_json JSON object containing additional key-related information for the Donau instance. + */ +static void +accept_donau ( + void *cls, + uint64_t donau_instance_serial, + const char *donau_url, + const char *charity_name, + const struct DONAU_CharityPublicKeyP *charity_pub_key, + uint64_t charity_id, + const struct TALER_Amount *charity_max_per_year, + const struct TALER_Amount *charity_receipts_to_date, + int64_t current_year, + const json_t *donau_keys_json + ) +{ + struct Donau *d; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Donau instance `%s' not found. Creating new instance.\n", + donau_url); + d = GNUNET_new (struct Donau); + d->donau_url = GNUNET_strdup (donau_url); + d->retry_delay = DONAU_MAXFREQ; + d->first_retry = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_ZERO); + GNUNET_CONTAINER_DLL_insert (d_head, + d_tail, + d); + if (NULL == donau_keys_json) + { + download_keys (d); + return; + } + d->keys = DONAU_keys_from_json (donau_keys_json); + if (NULL == d->keys) + { + GNUNET_break (0); + download_keys (d); + return; + } + d->retry_delay = DONAU_MAXFREQ; + d->first_retry = GNUNET_TIME_relative_to_absolute (DONAU_MAXFREQ); + + { + struct GNUNET_TIME_Absolute n; + + n = GNUNET_TIME_absolute_min ( + d->first_retry, + d->keys->sign_keys[0].expire_sign.abs_time); + d->retry_task = GNUNET_SCHEDULER_add_at (n, + &download_keys, + d); + } +} + + +/** * First task. * * @param cls closure, NULL @@ -990,11 +1060,25 @@ run (void *cls, NULL); } + { + enum GNUNET_DB_QueryStatus qs; + + qs = db_plugin->select_donau_instances (db_plugin->cls, + NULL, + &accept_donau, + NULL); + if (qs < 0) + { + GNUNET_break (0); + GNUNET_SCHEDULER_shutdown (); + return; + } + } if ( (0 == active_inquiries) && (test_mode) ) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "No donaukeys inquiries to start, exiting.\n"); + "No donau keys inquiries to start, exiting.\n"); GNUNET_SCHEDULER_shutdown (); return; } diff --git a/src/backenddb/pg_select_donau_instances.c b/src/backenddb/pg_select_donau_instances.c @@ -122,11 +122,18 @@ select_donau_instance_cb (void *cls, } -enum GNUNET_DB_QueryStatus -TMH_PG_select_donau_instances (void *cls, - const char *id, - TALER_MERCHANTDB_DonauInstanceCallback cb, - void *cb_cls) +/** + * Select all Donau instances (independent of instance) from the database. + * + * @param cls the closure for the database context + * @param cb callback function to call with each result + * @param cb_cls closure for the callback + * @return status of the PG + */ +static enum GNUNET_DB_QueryStatus +select_all_donau_instances (void *cls, + TALER_MERCHANTDB_DonauInstanceCallback cb, + void *cb_cls) { struct PostgresClosure *pg = cls; struct SelectDonauInstanceContext sdc = { @@ -135,7 +142,63 @@ TMH_PG_select_donau_instances (void *cls, /* Can be overwritten by the select_donau_instance_cb */ .extract_failed = false, }; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_end + }; + enum GNUNET_DB_QueryStatus qs; + + check_connection (pg); + PREPARE (pg, + "select_all_donau_instances", + "SELECT" + " di.donau_instances_serial" + ",di.donau_url" + ",di.charity_name" + ",mi.merchant_pub AS charity_pub_key" + ",di.charity_id" + ",di.charity_max_per_year" + ",di.charity_receipts_to_date" + ",di.current_year" + ",dk.keys_json" + " FROM merchant_donau_instances di" + " JOIN merchant_donau_keys dk" + " ON di.donau_url = dk.donau_url"); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "select_all_donau_instances", + params, + &select_donau_instance_cb, + &sdc); + + /* If there was an error inside select_donau_instance_cb, return a hard error. */ + if (sdc.extract_failed) + return GNUNET_DB_STATUS_HARD_ERROR; + + return qs; +} + +/** + * Select Donau instances from an instance @a id from the database. + * + * @param cls the closure for the database context + * @param id the ID of the merchant instance + * @param cb callback function to call with each result + * @param cb_cls closure for the callback + * @return status of the PG + */ +static enum GNUNET_DB_QueryStatus +select_donau_instances (void *cls, + const char *id, + TALER_MERCHANTDB_DonauInstanceCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + struct SelectDonauInstanceContext sdc = { + .cb = cb, + .cb_cls = cb_cls, + /* Can be overwritten by the select_donau_instance_cb */ + .extract_failed = false, + }; struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_string (id), GNUNET_PQ_query_param_end @@ -156,20 +219,42 @@ TMH_PG_select_donau_instances (void *cls, ",di.current_year" ",dk.keys_json" " FROM merchant_donau_instances di" - " JOIN merchant_donau_keys dk ON di.donau_url = dk.donau_url" - " JOIN merchant_instances mi ON di.merchant_instance_serial = mi.merchant_serial" + " JOIN merchant_donau_keys dk" + " ON di.donau_url = dk.donau_url" + " JOIN merchant_instances mi" + " ON di.merchant_instance_serial = mi.merchant_serial" " WHERE mi.merchant_id = $1"); - - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, "select_donau_instances", params, &select_donau_instance_cb, &sdc); - /* If there was an error inside select_donau_instance_cb, return a hard error. */ +/* If there was an error inside select_donau_instance_cb, return a hard error. */ if (sdc.extract_failed) return GNUNET_DB_STATUS_HARD_ERROR; return qs; -} -\ No newline at end of file +} + + +enum GNUNET_DB_QueryStatus +TMH_PG_select_donau_instances (void *cls, + const char *id, + TALER_MERCHANTDB_DonauInstanceCallback cb, + void *cb_cls) +{ + if (NULL == id) + { + return select_all_donau_instances (cls, + cb, + cb_cls); + } + else + { + return select_donau_instances (cls, + id, + cb, + cb_cls); + } +} diff --git a/src/backenddb/pg_select_donau_instances.h b/src/backenddb/pg_select_donau_instances.h @@ -28,10 +28,10 @@ #include "taler_merchant_donau.h" /** - * Select multiple Donau instances from the database. + * Select Donau instances from the database. * * @param cls the closure for the database context - * @param id the ID of the merchant instance + * @param id the ID of the merchant instance, NULL for all instances * @param cb callback function to call with each result * @param cb_cls closure for the callback * @return status of the PG diff --git a/src/include/taler_merchant_donau.h b/src/include/taler_merchant_donau.h @@ -128,6 +128,7 @@ struct TALER_MERCHANTDB_DonauInstance json_t *donau_keys_json; }; + /** * Callback function typically used by `select_donau_instances` to handle * the details of each Donau instance retrieved from the database. @@ -393,4 +394,4 @@ void TALER_MERCHANT_donau_instance_delete_cancel ( struct TALER_MERCHANT_DonauInstanceDeleteHandle *ddh); -#endif -\ No newline at end of file +#endif diff --git a/src/include/taler_merchantdb_plugin.h b/src/include/taler_merchantdb_plugin.h @@ -4317,6 +4317,7 @@ struct TALER_MERCHANTDB_Plugin * Select all Donau instances. * * @param cls closure + * @param id instance to restrict to, NULL for all * @param cb function to call on all Donau instances found * @param cb_cls closure for @a cb */