merchant

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

commit ae71def791e592482b7b8078c45f3476633ab1cc
parent beac1c1695d8a74864eac9461b9d5d9b0e0e3ae2
Author: Christian Grothoff <christian@grothoff.org>
Date:   Fri, 26 Sep 2025 19:41:14 +0200

fixes wrt #10454

Diffstat:
Msrc/backend/taler-merchant-httpd_private-post-donau-instance.c | 35+++++++++++++++++++++++++++++++++--
Msrc/backenddb/Makefile.am | 1+
Msrc/backenddb/merchant-0023.sql | 3+++
Asrc/backenddb/pg_check_donau_instance.c | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/backenddb/pg_check_donau_instance.h | 45+++++++++++++++++++++++++++++++++++++++++++++
Msrc/backenddb/pg_insert_donau_instance.c | 33++++-----------------------------
Msrc/backenddb/pg_select_donau_instance_by_serial.c | 12+++++++-----
Msrc/backenddb/pg_select_donau_instances_filtered.c | 2+-
Msrc/backenddb/pg_update_donau_instance.c | 16++++++++--------
Msrc/backenddb/plugin_merchantdb_postgres.c | 3+++
Msrc/include/taler_merchantdb_plugin.h | 23++++++++++++++++++++---
11 files changed, 189 insertions(+), 48 deletions(-)

diff --git a/src/backend/taler-merchant-httpd_private-post-donau-instance.c b/src/backend/taler-merchant-httpd_private-post-donau-instance.c @@ -146,7 +146,8 @@ donau_charity_get_cb (void *cls, return; } - if (GNUNET_memcmp (&gcr->details.ok.charity.charity_pub.eddsa_pub, + if (0 != + GNUNET_memcmp (&gcr->details.ok.charity.charity_pub.eddsa_pub, &pdc->hc->instance->merchant_pub.eddsa_pub)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, @@ -251,6 +252,8 @@ TMH_private_post_donau_instance (const struct TMH_RequestHandler *rh, if (NULL == pdc) { + enum GNUNET_DB_QueryStatus qs; + pdc = GNUNET_new (struct PostDonauCtx); pdc->connection = connection; pdc->hc = hc; @@ -277,6 +280,34 @@ TMH_private_post_donau_instance (const struct TMH_RequestHandler *rh, return MHD_NO; } } + qs = TMH_db->check_donau_instance (TMH_db->cls, + &hc->instance->merchant_pub, + pdc->donau_url, + pdc->charity_id); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + case GNUNET_DB_STATUS_SOFT_ERROR: + GNUNET_break (0); + pdc->http_status = MHD_HTTP_INTERNAL_SERVER_ERROR; + return TALER_MHD_reply_with_error ( + connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_FETCH_FAILED, + "check_donau_instance"); + break; + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + pdc->http_status = MHD_HTTP_NO_CONTENT; + pdc->response = MHD_create_response_from_buffer_static (0, + NULL); + TALER_MHD_add_global_headers (pdc->response, + false); + goto respond; + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + /* normal case, continue below */ + break; + } + { struct DONAU_CharityPrivateKeyP cp; @@ -303,7 +334,7 @@ TMH_private_post_donau_instance (const struct TMH_RequestHandler *rh, MHD_suspend_connection (connection); return MHD_YES; } - +respond: if (NULL != pdc->response) { GNUNET_break (GNUNET_NO == pdc->suspended); diff --git a/src/backenddb/Makefile.am b/src/backenddb/Makefile.am @@ -227,6 +227,7 @@ libtaler_plugin_merchantdb_postgres_la_SOURCES = \ if HAVE_DONAU libtaler_plugin_merchantdb_postgres_la_SOURCES += \ pg_insert_donau_instance.h pg_insert_donau_instance.c \ + pg_check_donau_instance.h pg_check_donau_instance.c \ pg_select_donau_instances.h pg_select_donau_instances.c \ pg_select_all_donau_instances.h pg_select_all_donau_instances.c \ pg_select_donau_instances_filtered.h pg_select_donau_instances_filtered.c \ diff --git a/src/backenddb/merchant-0023.sql b/src/backenddb/merchant-0023.sql @@ -81,5 +81,8 @@ CREATE INDEX tan_challenges_expiration_index COMMENT ON INDEX tan_challenges_expiration_index IS 'for garbage collection'; +ALTER TABLE merchant_donau_instances + ADD CONSTRAINT merchant_donau_charity_unique + UNIQUE (donau_url, merchant_instance_serial, charity_id); COMMIT; diff --git a/src/backenddb/pg_check_donau_instance.c b/src/backenddb/pg_check_donau_instance.c @@ -0,0 +1,64 @@ +/* + This file is part of TALER + Copyright (C) 2025 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file backenddb/pg_check_donau_instance.c + * @brief Implementation of the check_donau_instance function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "pg_check_donau_instance.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TMH_PG_check_donau_instance ( + void *cls, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const char *donau_url, + uint64_t charity_id + ) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (donau_url), + GNUNET_PQ_query_param_uint64 (&charity_id), + GNUNET_PQ_query_param_auto_from_type (merchant_pub), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_end + }; + + check_connection (pg); + PREPARE (pg, + "check_donau_instance", + "SELECT 1" + " FROM merchant_donau_instances" + " WHERE donau_url=$1" + " AND charity_id=$2 " + " AND merchant_instance_serial =" + " (SELECT merchant_serial" + " FROM merchant_instances mi" + " WHERE mi.merchant_pub = $3)"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "check_donau_instance", + params, + rs); + +} diff --git a/src/backenddb/pg_check_donau_instance.h b/src/backenddb/pg_check_donau_instance.h @@ -0,0 +1,45 @@ +/* + This file is part of TALER + Copyright (C) 2025 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file backenddb/pg_check_donau_instance.h + * @brief implementation of the check_donau_instance function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_CHECK_DONAU_INSTANCE_H +#define PG_CHECK_DONAU_INSTANCE_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "taler_merchantdb_plugin.h" + + +/** + * Check if information about a Donau instance exists. + * + * @param cls closure + * @param merchant_pub public key of the instance + * @param donau_url URL of the Donau instance + * @param charity_id charity ID of the Donau instance + */ +enum GNUNET_DB_QueryStatus +TMH_PG_check_donau_instance ( + void *cls, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const char *donau_url, + uint64_t charity_id + ); + +#endif diff --git a/src/backenddb/pg_insert_donau_instance.c b/src/backenddb/pg_insert_donau_instance.c @@ -33,10 +33,9 @@ TMH_PG_insert_donau_instance ( void *cls, const char *donau_url, const struct DONAU_Charity *charity, - const uint64_t charity_id) + uint64_t charity_id) { struct PostgresClosure *pg = cls; - enum GNUNET_DB_QueryStatus qs; struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_string (donau_url), GNUNET_PQ_query_param_string (charity->name), @@ -51,8 +50,6 @@ TMH_PG_insert_donau_instance ( }; check_connection (pg); - - /* FIXME: combine into a single stored procedure */ PREPARE (pg, "insert_donau_instance", "INSERT INTO merchant_donau_instances" @@ -68,31 +65,9 @@ TMH_PG_insert_donau_instance ( " (SELECT merchant_serial" " FROM merchant_instances mi" " WHERE mi.merchant_pub = $3)," - " $4, $5, $6, $7);"); - PREPARE (pg, - "update_donau_instance", - "UPDATE merchant_donau_instances SET" - " charity_name = $2," - " charity_max_per_year = $5," - " charity_receipts_to_date = $6," - " current_year = $7" - " WHERE" - " charity_id=$4" - " AND merchant_instance_serial" - " = (SELECT merchant_serial" - " FROM merchant_instances mi" - " WHERE mi.merchant_pub = $3)" - " AND donau_url=$1;"); - - qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, - "update_donau_instance", - params); - if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) - { - qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, + " $4, $5, $6, $7)" + " ON CONFLICT DO NOTHING;"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, "insert_donau_instance", params); - } - - return qs; } diff --git a/src/backenddb/pg_select_donau_instance_by_serial.c b/src/backenddb/pg_select_donau_instance_by_serial.c @@ -40,15 +40,18 @@ TMH_PG_select_donau_instance_by_serial (void *cls, GNUNET_PQ_query_param_end }; struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_string ("donau_url", donau_url), - GNUNET_PQ_result_spec_uint64 ("charity_id", charity_id), + GNUNET_PQ_result_spec_string ("donau_url", + donau_url), + GNUNET_PQ_result_spec_uint64 ("charity_id", + charity_id), GNUNET_PQ_result_spec_end }; check_connection (pg); PREPARE (pg, "select_donau_instance_by_serial", - "SELECT donau_url, charity_id" + "SELECT donau_url" + " ,charity_id" " FROM merchant_donau_instances" " WHERE donau_instances_serial = $1"); @@ -57,4 +60,4 @@ TMH_PG_select_donau_instance_by_serial (void *cls, "select_donau_instance_by_serial", params, rs); -} -\ No newline at end of file +} diff --git a/src/backenddb/pg_select_donau_instances_filtered.c b/src/backenddb/pg_select_donau_instances_filtered.c @@ -15,7 +15,7 @@ */ /** * @file backenddb/pg_select_donau_instances_filtered.c - * @brief Implementation of the select_donau_instance function for Postgres + * @brief Implementation of the select_donau_instances_filtered function for Postgres * @author Bohdan Potuzhnyi * @author Vlada Svirsh */ diff --git a/src/backenddb/pg_update_donau_instance.c b/src/backenddb/pg_update_donau_instance.c @@ -27,12 +27,13 @@ #include "pg_update_donau_instance.h" #include "pg_helper.h" + enum GNUNET_DB_QueryStatus TMH_PG_update_donau_instance ( void *cls, const char *donau_url, const struct DONAU_Charity *charity, - const uint64_t charity_id) + uint64_t charity_id) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { @@ -54,17 +55,17 @@ TMH_PG_update_donau_instance ( "update_existing_donau_instance", "UPDATE merchant_donau_instances SET" " charity_name = $2," - " merchant_instance_serial = (SELECT merchant_serial" - " FROM merchant_instances mi" - " WHERE mi.merchant_pub = $3)," " charity_max_per_year = $5," " charity_receipts_to_date = $6," " current_year = $7" - " WHERE" - " charity_id = $4" + " WHERE charity_id = $4" + " AND merchant_instance_serial " + " = (SELECT merchant_serial" + " FROM merchant_instances mi" + " WHERE mi.merchant_pub = $3)," " AND donau_url = $1;"); return GNUNET_PQ_eval_prepared_non_select (pg->conn, "update_existing_donau_instance", params); -} -\ No newline at end of file +} diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c @@ -172,6 +172,7 @@ #ifdef HAVE_DONAU_DONAU_SERVICE_H #include "donau/donau_service.h" #include "pg_insert_donau_instance.h" +#include "pg_check_donau_instance.h" #include "pg_select_donau_instance_by_serial.h" #include "pg_select_all_donau_instances.h" #include "pg_select_donau_instances.h" @@ -687,6 +688,8 @@ libtaler_plugin_merchantdb_postgres_init (void *cls) #ifdef HAVE_DONAU_DONAU_SERVICE_H plugin->insert_donau_instance = &TMH_PG_insert_donau_instance; + plugin->check_donau_instance + = &TMH_PG_check_donau_instance; plugin->select_donau_instance_by_serial = &TMH_PG_select_donau_instance_by_serial; plugin->select_all_donau_instances diff --git a/src/include/taler_merchantdb_plugin.h b/src/include/taler_merchantdb_plugin.h @@ -4295,7 +4295,24 @@ struct TALER_MERCHANTDB_Plugin void *cls, const char *donau_url, const struct DONAU_Charity *charity, - const uint64_t charity_id + uint64_t charity_id + ); + + + /** + * Check if information about a Donau instance exists. + * + * @param cls closure + * @param merchant_pub public key of the instance + * @param donau_url URL of the Donau instance + * @param charity_id charity ID of the Donau instance + */ + enum GNUNET_DB_QueryStatus + (*check_donau_instance)( + void *cls, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const char *donau_url, + uint64_t charity_id ); /** @@ -4430,7 +4447,7 @@ struct TALER_MERCHANTDB_Plugin void *cls, const char *donau_url, const struct DONAU_Charity *charity, - const uint64_t charity_id + uint64_t charity_id ); #endif @@ -4445,7 +4462,7 @@ struct TALER_MERCHANTDB_Plugin (*delete_donau_instance)( void *cls, const char *id, - const uint64_t charity_id + uint64_t charity_id ); /**