merchant

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

commit beac1c1695d8a74864eac9461b9d5d9b0e0e3ae2
parent 3a52aa07dbef186b9f44268487c5c1d75e7aff7d
Author: Christian Grothoff <christian@grothoff.org>
Date:   Fri, 26 Sep 2025 19:09:02 +0200

cleanups related to #10454

Diffstat:
Msrc/backend/taler-merchant-httpd_get-orders-ID.c | 1-
Msrc/backend/taler-merchant-httpd_private-get-donau-instances.c | 10+++++-----
Msrc/backenddb/pg_insert_donau_instance.c | 12++++++------
Msrc/backenddb/pg_select_donau_instances.c | 11++++++-----
Msrc/include/taler_merchant_donau.h | 4++--
Msrc/lib/merchant_api_get_donau_instance.c | 79++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
Msrc/testing/test_merchant_api.c | 22+++++++++++++++++++++-
7 files changed, 86 insertions(+), 53 deletions(-)

diff --git a/src/backend/taler-merchant-httpd_get-orders-ID.c b/src/backend/taler-merchant-httpd_get-orders-ID.c @@ -1183,7 +1183,6 @@ phase_redirect_to_paid_order (struct GetOrderData *god) GNUNET_free (already_paid_order_id); return ret; } - GNUNET_break (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs); GNUNET_free (already_paid_order_id); } god->phase++; diff --git a/src/backend/taler-merchant-httpd_private-get-donau-instances.c b/src/backend/taler-merchant-httpd_private-get-donau-instances.c @@ -40,7 +40,7 @@ * @param charity_max_per_year the maximum donation amount per year * @param charity_receipts_to_date the total donations received so far this year * @param current_year the current year being tracked for donations - * @param donau_keys_json JSON object with key information specific to the Donau instance + * @param donau_keys_json JSON object with key information specific to the Donau instance, NULL if not (yet) available. */ static void add_donau_instance (void *cls, @@ -76,8 +76,9 @@ add_donau_instance (void *cls, charity_receipts_to_date), GNUNET_JSON_pack_int64 ("current_year", current_year), - GNUNET_JSON_pack_object_incref ("donau_keys_json", - (json_t *) donau_keys_json) + GNUNET_JSON_pack_allow_null ( + GNUNET_JSON_pack_object_incref ("donau_keys_json", + (json_t *) donau_keys_json)) ))); } @@ -118,4 +119,4 @@ TMH_private_get_donau_instances (const struct TMH_RequestHandler *rh, GNUNET_JSON_pack_array_steal ( "donau_instances", json_donau_instances)); -} -\ No newline at end of file +} diff --git a/src/backenddb/pg_insert_donau_instance.c b/src/backenddb/pg_insert_donau_instance.c @@ -69,20 +69,20 @@ TMH_PG_insert_donau_instance ( " 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," - " 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" - " AND donau_url = $1;"); + " 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", diff --git a/src/backenddb/pg_select_donau_instances.c b/src/backenddb/pg_select_donau_instances.c @@ -74,8 +74,7 @@ select_donau_instance_cb (void *cls, struct TALER_Amount charity_max_per_year; struct TALER_Amount charity_receipts_to_date; int64_t current_year; - json_t *donau_keys_json; - + json_t *donau_keys_json = NULL; struct GNUNET_PQ_ResultSpec rs[] = { GNUNET_PQ_result_spec_uint64 ("donau_instances_serial", &donau_instance_serial), @@ -93,8 +92,10 @@ select_donau_instance_cb (void *cls, &charity_receipts_to_date), GNUNET_PQ_result_spec_int64 ("current_year", &current_year), - TALER_PQ_result_spec_json ("keys_json", - &donau_keys_json), + GNUNET_PQ_result_spec_allow_null ( + TALER_PQ_result_spec_json ("keys_json", + &donau_keys_json), + NULL), GNUNET_PQ_result_spec_end }; @@ -155,7 +156,7 @@ TMH_PG_select_donau_instances (void *cls, ",di.current_year" ",dk.keys_json" " FROM merchant_donau_instances di" - " JOIN merchant_donau_keys dk" + " LEFT JOIN merchant_donau_keys dk" " ON di.donau_url = dk.donau_url" " JOIN merchant_instances mi" " ON di.merchant_instance_serial = mi.merchant_serial" diff --git a/src/include/taler_merchant_donau.h b/src/include/taler_merchant_donau.h @@ -142,7 +142,7 @@ struct TALER_MERCHANTDB_DonauInstance * @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. + * @param donau_keys_json JSON object containing additional key-related information for the Donau instance, NULL if not (yet) available. */ typedef void (*TALER_MERCHANTDB_DonauInstanceCallback)( @@ -228,7 +228,7 @@ struct TALER_MERCHANT_DonauInstanceEntry /** * Additional key information related to the Donau instance. */ - struct DONAU_Keys donau_keys; + const struct DONAU_Keys *donau_keys; }; /** diff --git a/src/lib/merchant_api_get_donau_instance.c b/src/lib/merchant_api_get_donau_instance.c @@ -83,6 +83,7 @@ parse_donau_instances (const json_t *ia, instances[GNUNET_NZL (instances_len)]; size_t index; json_t *value; + struct DONAU_Keys *donau_keys_ptr = NULL; if ((json_array_size (ia) != (size_t) instances_len)) { @@ -95,9 +96,7 @@ parse_donau_instances (const json_t *ia, value) { struct TALER_MERCHANT_DonauInstanceEntry *instance = &instances[index]; - const json_t *donau_keys_json; - struct DONAU_Keys *donau_keys_ptr; - + const json_t *donau_keys_json = NULL; struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_uint64 ("donau_instance_serial", &instance->donau_instance_serial), @@ -115,42 +114,47 @@ parse_donau_instances (const json_t *ia, &instance->charity_receipts_to_date), GNUNET_JSON_spec_int64 ("current_year", &instance->current_year), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_object_const ("donau_keys_json", + &donau_keys_json), + NULL), GNUNET_JSON_spec_end () }; - if (GNUNET_OK != GNUNET_JSON_parse (value, - spec, - NULL, - NULL)) + if (GNUNET_OK != + GNUNET_JSON_parse (value, + spec, + NULL, + NULL)) { GNUNET_break_op (0); return GNUNET_SYSERR; } /* Parse the Donau keys */ - donau_keys_json = json_object_get (value, - "donau_keys_json"); - if (NULL == donau_keys_json) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to parse donau keys JSON\n"); - return GNUNET_SYSERR; - } - donau_keys_ptr = DONAU_keys_from_json (donau_keys_json); - if (NULL == donau_keys_ptr) + if (NULL != donau_keys_json) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to convert donau keys from JSON\n"); - return GNUNET_SYSERR; + donau_keys_ptr = DONAU_keys_from_json (donau_keys_json); + if (NULL == donau_keys_ptr) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to convert donau keys from JSON\n"); + return GNUNET_SYSERR; + } + instance->donau_keys = donau_keys_ptr; } - - instance->donau_keys = *donau_keys_ptr; } igr->details.ok.donau_instances_length = instances_len; igr->details.ok.donau_instances = instances; - dgh->cb (dgh->cb_cls, igr); + dgh->cb (dgh->cb_cls, + igr); dgh->cb = NULL; + if (NULL != donau_keys_ptr) + { + DONAU_keys_decref (donau_keys_ptr); + donau_keys_ptr= NULL; + } return GNUNET_OK; } @@ -186,18 +190,26 @@ handle_get_donau_instances_finished (void *cls, { const json_t *donau_instances; struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_array_const ("donau_instances", &donau_instances), + GNUNET_JSON_spec_array_const ("donau_instances", + &donau_instances), GNUNET_JSON_spec_end () }; - if (GNUNET_OK != GNUNET_JSON_parse (json, spec, NULL, NULL)) + if (GNUNET_OK != + GNUNET_JSON_parse (json, + spec, + NULL, + NULL)) { igr.hr.http_status = 0; igr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; break; } - if (GNUNET_OK == parse_donau_instances (donau_instances, &igr, dgh)) + if (GNUNET_OK == + parse_donau_instances (donau_instances, + &igr, + dgh)) { TALER_MERCHANT_donau_instances_get_cancel (dgh); return; @@ -248,8 +260,9 @@ TALER_MERCHANT_donau_instances_get (struct GNUNET_CURL_Context *ctx, dgh->ctx = ctx; dgh->cb = cb; dgh->cb_cls = cb_cls; - - dgh->url = TALER_url_join (backend_url, "private/donau", NULL); + dgh->url = TALER_url_join (backend_url, + "private/donau", + NULL); if (NULL == dgh->url) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -257,12 +270,13 @@ TALER_MERCHANT_donau_instances_get (struct GNUNET_CURL_Context *ctx, GNUNET_free (dgh); return NULL; } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Requesting URL '%s'\n", dgh->url); - + "Requesting URL '%s'\n", + dgh->url); eh = TALER_MERCHANT_curl_easy_get_ (dgh->url); - dgh->job = GNUNET_CURL_job_add (ctx, eh, &handle_get_donau_instances_finished, + dgh->job = GNUNET_CURL_job_add (ctx, + eh, + &handle_get_donau_instances_finished, dgh); return dgh; @@ -280,7 +294,6 @@ TALER_MERCHANT_donau_instances_get_cancel ( { if (NULL != dgh->job) GNUNET_CURL_job_cancel (dgh->job); - GNUNET_free (dgh->url); GNUNET_free (dgh); } diff --git a/src/testing/test_merchant_api.c b/src/testing/test_merchant_api.c @@ -1880,11 +1880,31 @@ run (void *cls, "create-another-order-with-input-and-output", // reusing the merchant_reference for merchant_pub MHD_HTTP_CREATED), + TALER_TESTING_cmd_charity_post_merchant ("post-charity-conflict", + "example", + "example.com", + "EUR:50", // max_per_year + "EUR:0", // receipts_to_date + 2025, // current year + &bearer, + "create-another-order-with-input-and-output", + // reusing the merchant_reference for merchant_pub + MHD_HTTP_CONFLICT), TALER_TESTING_cmd_merchant_post_donau_instance ( "post-donau-instance", merchant_url, - "create-another-order-with-input-and-output", // reusing the merchant_reference + "create-another-order-with-input-and-output", + MHD_HTTP_NO_CONTENT), + TALER_TESTING_cmd_merchant_post_donau_instance ( + "post-donau-instance-idempotent", + merchant_url, + "create-another-order-with-input-and-output", MHD_HTTP_NO_CONTENT), + TALER_TESTING_cmd_merchant_get_donau_instances ( + "get-donau-instances-after-insert", + merchant_url, + 1, + MHD_HTTP_OK), TALER_TESTING_cmd_sleep ( "In this time donaukeyupdate must fetch the keys from the donau", 1),