merchant

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

commit 1e9a9faea9025f6b4fa81393146c40cf7f3740ed
parent bbf17ee238bf2eac6bfeb593af6e2239c7e47329
Author: bohdan-potuzhnyi <bohdan.potuzhnyi@gmail.com>
Date:   Wed, 16 Jul 2025 18:01:24 +0200

meeting fixme's

Diffstat:
Msrc/backend/.gitignore | 4----
Msrc/backend/taler-merchant-donaukeyupdate.c | 2+-
Msrc/backend/taler-merchant-httpd_post-orders-ID-pay.c | 152++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/backend/taler-merchant-httpd_private-post-orders.c | 21++++++++++++---------
Msrc/backenddb/pg_lookup_order_charity.c | 23+++++++++++++----------
5 files changed, 103 insertions(+), 99 deletions(-)

diff --git a/src/backend/.gitignore b/src/backend/.gitignore @@ -4,8 +4,4 @@ taler-merchant-kyccheck taler-merchant-reconciliation taler-merchant-webhook taler-merchant-wirewatch -<<<<<<< HEAD taler-merchant-donaukeyupdate -======= -taler-merchant-donaukeyupdate ->>>>>>> master diff --git a/src/backend/taler-merchant-donaukeyupdate.c b/src/backend/taler-merchant-donaukeyupdate.c @@ -16,7 +16,7 @@ /** * @file taler-merchant-donaukeyupdate.c * @brief Process that ensures our /keys data for all Donau instances is current - * @author [Your Name] + * @author Bohdan Potuzhnyi */ #include "platform.h" #include <gnunet/gnunet_util_lib.h> diff --git a/src/backend/taler-merchant-httpd_post-orders-ID-pay.c b/src/backend/taler-merchant-httpd_post-orders-ID-pay.c @@ -706,13 +706,14 @@ struct PayContext /** * Private key of the charity(related to the private key of the merchant). */ - struct DONAU_CharityPrivateKeyP *charity_priv; + struct DONAU_CharityPrivateKeyP charity_priv; } charity; /** * Struct to hold the clients bkps + donau request handler */ + /*FIXME: merge with the donaudata, birh to another phase*/ struct { /** @@ -1876,9 +1877,9 @@ phase_payment_notification (struct PayContext *pc) * is malformed. */ static void -signatures_to_JSON (const size_t num_sig, - struct DONAU_BlindedDonationUnitSignature *signatures, - json_t *j_signatures) +signature_to_json (const size_t num_sig, + struct DONAU_BlindedDonationUnitSignature *signatures, + json_t *j_signatures) { for (size_t i = 0; i < num_sig; i++) { @@ -1905,19 +1906,11 @@ merchant_donau_issue_receipt_cb (void *cls, { struct PayContext *pc = cls; - /* Usually, Donau replies asynchronously, so we expect the PayContext + /* Donau replies asynchronously, so we expect the PayContext * to be suspended. */ GNUNET_assert (GNUNET_YES == pc->suspended); - if (NULL == resp) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Donau response is NULL (internal or parse error)\n"); - resume_pay_with_error (pc, - TALER_EC_GENERIC_CLIENT_INTERNAL_ERROR, - "Donau response missing"); - return; - } + /* REVIEW NULL == resp in donau testing*/ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Donau responded with status=%u, ec=%u\n", @@ -1929,6 +1922,11 @@ merchant_donau_issue_receipt_cb (void *cls, { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Donau replied with status 0 => invalid or parse error\n"); + /* FIXME: TALER_EC_MERCHANT_DONAU_TALKING_ISSUE_ + * resume_pay_with_donau_error so include everything as possible from donau + * 502 for return + * PayResponse new bad_gateway part with donau hint error, so on + * change to switch*/ resume_pay_with_error (pc, TALER_EC_GENERIC_CLIENT_INTERNAL_ERROR, "Donau parse error"); @@ -1967,6 +1965,7 @@ merchant_donau_issue_receipt_cb (void *cls, } } + /*FIXME: Remove NULL check versus json_array alloc*/ pc->donau_receipt.donau_sigs_json = json_array (); if (NULL == pc->donau_receipt.donau_sigs_json) { @@ -1977,9 +1976,9 @@ merchant_donau_issue_receipt_cb (void *cls, return; } - signatures_to_JSON (pc->donau_receipt.num_sigs, - pc->donau_receipt.sigs, - pc->donau_receipt.donau_sigs_json); + signature_to_json (pc->donau_receipt.num_sigs, + pc->donau_receipt.sigs, + pc->donau_receipt.donau_sigs_json); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Donau accepted donation receipts with total_issued=%s\n", @@ -2032,7 +2031,8 @@ merchant_parse_json_bkp (struct DONAU_BlindedUniqueDonorIdentifierKeyPair *bkp, GNUNET_break_op (0); return GNUNET_SYSERR; } - /* FIXME: Check for duplicate blinded UDIs.*/ + /* FIXME: Add donau signatures length to the batch issue */ + /* FIXME: Check that the blinded_udi are different in the parsing part*/ return GNUNET_OK; } @@ -2057,7 +2057,7 @@ phase_generate_donation_receipt (struct PayContext *pc) pc->donau_handler.birh = DONAU_charity_issue_receipt (TMH_curl_ctx, pc->parse_wallet_data.donau.donau_url, - pc->charity.charity_priv, + &pc->charity.charity_priv, pc->charity.charity_id, pc->parse_wallet_data.donau.donation_year, pc->donau_handler.num_bkps, @@ -2683,6 +2683,9 @@ phase_execute_pay_transaction (struct PayContext *pc) } } + /*FIXME: Change to the switch, get out the choice + * + assert output_len is the same as output_tokens_len */ + /* Store signed output tokens in database. */ for (size_t i = 0; i<pc->validate_tokens.output_tokens_len; i++) { @@ -2729,34 +2732,35 @@ phase_execute_pay_transaction (struct PayContext *pc) } // REVIEW: Do we really need to save the BUDIs? and what is the point of it? - if (NULL != pc->parse_wallet_data.donau.budikeypairs) - { - enum GNUNET_DB_QueryStatus qs; - qs = TMH_db->insert_order_budis (TMH_db->cls, - pc->order_id, - pc->parse_wallet_data.donau.budikeypairs); - switch (qs) - { - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - /* Case we are looking for */ - break; - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - // REVIEW: Do we really want to ignore, or to fetch the ones from the DB? - // Maybe we even want to do it in the parse_wallet_data part... - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Order BUDIs already present, ignoring.\n"); - break; - case GNUNET_DB_STATUS_SOFT_ERROR: - case GNUNET_DB_STATUS_HARD_ERROR: - TMH_db->rollback (TMH_db->cls); - pay_end (pc, - TALER_MHD_reply_with_error (pc->connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_DB_STORE_FAILED, - "insert_order_budis")); - return; - } - } + /* FIXME: Review this part */ +// if (NULL != pc->parse_wallet_data.donau.budikeypairs) +// { +// enum GNUNET_DB_QueryStatus qs; +// qs = TMH_db->insert_order_budis (TMH_db->cls, +// pc->order_id, +// pc->parse_wallet_data.donau.budikeypairs); +// switch (qs) +// { +// case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: +// /* Case we are looking for */ +// break; +// case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: +// // REVIEW: Do we really want to ignore, or to fetch the ones from the DB? +// // Maybe we even want to do it in the parse_wallet_data part... +// GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, +// "Order BUDIs already present, ignoring.\n"); +// break; +// case GNUNET_DB_STATUS_SOFT_ERROR: +// case GNUNET_DB_STATUS_HARD_ERROR: +// TMH_db->rollback (TMH_db->cls); +// pay_end (pc, +// TALER_MHD_reply_with_error (pc->connection, +// MHD_HTTP_INTERNAL_SERVER_ERROR, +// TALER_EC_GENERIC_DB_STORE_FAILED, +// "insert_order_budis")); +// return; +// } +// } TMH_notify_order_change (hc->instance, @@ -2813,6 +2817,7 @@ phase_execute_pay_transaction (struct PayContext *pc) } } + /* Ternary iterator */ if (NULL != pc->parse_wallet_data.donau.donau_url) { /* We have a Donau URL => we do the new donation receipt phase. */ @@ -3092,8 +3097,9 @@ find_family (const struct PayContext *pc, * @param pc context for the pay request * @param output contract output we need to process * @param output_index index of this output in the contract's outputs array - * @return GNUNET_OK on success, GNUNET_NO if an error was encountered + * @return #GNUNET_OK on success, #GNUNET_NO if an error was encountered */ +/* FIXME: Maybe move to boolean*/ static enum GNUNET_GenericReturnValue handle_output_token (struct PayContext *pc, const struct TALER_MERCHANT_ContractOutput *output, @@ -3148,6 +3154,7 @@ handle_output_token (struct PayContext *pc, pc->check_contract.contract_terms->timestamp, pc->check_contract.contract_terms->pay_deadline, &details); + /* FIXME: NO_RESPONSE 404, ERRORs */ if (qs <= 0) { GNUNET_log ( @@ -3185,6 +3192,7 @@ handle_output_token (struct PayContext *pc, output->details.token.count)) { /* sign_token_envelopes() already queued up an error via pay_end() */ + /* FIXME: GNUNET_break(0); */ return GNUNET_NO; } @@ -3195,18 +3203,18 @@ handle_output_token (struct PayContext *pc, /** * Handle checks for contract output of type TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT. - * For now, this does nothing and simply returns GNUNET_OK. + * For now, this does nothing and simply returns #GNUNET_OK. * * @param pc context for the pay request * @param output the contract output describing the donation receipt requirement * @param output_index index of this output in the contract's outputs array - * @return GNUNET_OK unconditionally (placeholder) + * @return #GNUNET_OK unconditionally (placeholder) */ static enum GNUNET_GenericReturnValue -handle_output_donation_receipt (struct PayContext *pc, - const struct - TALER_MERCHANT_ContractOutput *output, - unsigned int output_index) +handle_output_donation_receipt ( + struct PayContext *pc, + const struct TALER_MERCHANT_ContractOutput *output, + unsigned int output_index) { // FIXME: Rethink this one, as most checks can be done immediately after receiving the wallet_data /* FIXME: Implement this function. @@ -3405,6 +3413,7 @@ deposit_paid_check ( } +/* FIXME: Add comment */ static void input_tokens_paid_check ( void *cls, @@ -3913,19 +3922,14 @@ phase_parse_wallet_data (struct PayContext *pc) } #ifdef HAVE_DONAU_DONAU_SERVICE_H - pc->parse_wallet_data.donau.donau_url = NULL; - pc->parse_wallet_data.donau.donation_year = 0; - pc->parse_wallet_data.donau.budikeypairs = NULL; - pc->donau_handler.num_bkps = 0; - pc->donau_handler.bkps = NULL; - if (NULL != donau_obj) { - const char *donau_url_tmp = NULL; - uint64_t donation_year_tmp = 0; - const json_t *budikeypairs = NULL; + const char *donau_url_tmp; + uint64_t donation_year_tmp; + const json_t *budikeypairs; /* Fetching and checking that all 3 are present in some way */ + /* FIXME: Put pc->parse_....donation_year already*/ struct GNUNET_JSON_Specification dspec[] = { GNUNET_JSON_spec_string ("url", &donau_url_tmp), @@ -3950,8 +3954,10 @@ phase_parse_wallet_data (struct PayContext *pc) return; } + /* FIXME: remove check as already in array const */ if (! json_is_array (budikeypairs) || (0 == json_array_size (budikeypairs))) { + GNUNET_break_op (0); resume_pay_with_error (pc, TALER_EC_GENERIC_PARAMETER_MALFORMED, "Missing or empty 'budikeypairs' array"); @@ -3961,14 +3967,13 @@ phase_parse_wallet_data (struct PayContext *pc) // Check if the needed data is present for the given donau URL { enum GNUNET_DB_QueryStatus qs; - pc->charity.charity_priv = GNUNET_new (struct DONAU_CharityPrivateKeyP); /* Part where we fetch info about the charity*/ qs = TMH_db->lookup_order_charity ( TMH_db->cls, donau_url_tmp, &pc->charity.charity_id, - pc->charity.charity_priv); + &pc->charity.charity_priv); switch (qs) { @@ -3984,7 +3989,8 @@ phase_parse_wallet_data (struct PayContext *pc) TALER_EC_GENERIC_PARAMETER_MALFORMED, "No matching Donau charity found for the given URL")); return; - default: + case GNUNET_DB_STATUS_SOFT_ERROR: + case GNUNET_DB_STATUS_HARD_ERROR: /* SOFT or HARD errors, MULTIPLE is also here(but select single)? ask C about it */ TMH_db->rollback (TMH_db->cls); pay_end (pc, @@ -3999,7 +4005,6 @@ phase_parse_wallet_data (struct PayContext *pc) pc->parse_wallet_data.donau.donau_url = GNUNET_strdup (donau_url_tmp); pc->parse_wallet_data.donau.donation_year = donation_year_tmp; - pc->parse_wallet_data.donau.budikeypairs = budikeypairs; // Stage to parse the budikeypairs from json to struct { @@ -4008,6 +4013,7 @@ phase_parse_wallet_data (struct PayContext *pc) GNUNET_new_array (num_bkps, struct DONAU_BlindedUniqueDonorIdentifierKeyPair); + /* Change to json for each*/ for (size_t i = 0; i < num_bkps; i++) { const json_t *bkp_obj = json_array_get (budikeypairs, i); @@ -4025,11 +4031,6 @@ phase_parse_wallet_data (struct PayContext *pc) pc->donau_handler.num_bkps = num_bkps; pc->donau_handler.bkps = bkps; } - - // FIXME: BUG #### Check the amount of the bkps, versus amount in the contract and maximum allowed for donau - { - - } } #else /* Donau not compiled in: reject request if a donau object was given. */ @@ -4084,10 +4085,11 @@ phase_parse_pay (struct PayContext *pc) { // TODO: Clean up this block when done // Print the request body for debugging purposes + // FIXME: IF DEBUG char *dump = json_dumps (pc->hc->request_body, - JSON_INDENT (2) /* human friendly */ - | JSON_ENCODE_ANY /* handle UTF-8 as \uXXXX */ - | JSON_SORT_KEYS /* deterministic output */); + JSON_INDENT (2) + | JSON_ENCODE_ANY + | JSON_SORT_KEYS); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "POST /orders/%s/pay – request body follows:\n%s\n", diff --git a/src/backend/taler-merchant-httpd_private-post-orders.c b/src/backend/taler-merchant-httpd_private-post-orders.c @@ -3338,10 +3338,11 @@ parse_order (struct OrderContext *oc) #ifdef HAVE_DONAU_DONAU_SERVICE_H -/* +/** * Callback function that is called for each donau instance. * It simply adds the provided donau_url to the json. */ +/* FIXME: very-very bad */ static void add_donau_url (void *cls, const char *donau_url, @@ -3367,10 +3368,12 @@ parse_donau_instances (struct OrderContext *oc, enum GNUNET_DB_QueryStatus qs; /* Invoke the database call, accumulating URLs in a JSON array */ + /* FIXME: select_donau_instanceS */ qs = TMH_db->select_donau_instance (TMH_db->cls, &add_donau_url, json_donau_instances); + /* REVIEW: If no */ if (qs < 0) { json_decref (json_donau_instances); @@ -3387,6 +3390,7 @@ parse_donau_instances (struct OrderContext *oc, size_t num_instances = json_array_size (json_donau_instances); if (num_instances > 0) { + /* FIXME: use the GNUNET_NEW_ARRAY */ output->details.donation_receipt.donau_urls = malloc (num_instances * sizeof(char *)); if (! output->details.donation_receipt.donau_urls) @@ -3403,9 +3407,10 @@ parse_donau_instances (struct OrderContext *oc, for (size_t i = 0; i < num_instances; i++) { - json_t *url_json = json_array_get (json_donau_instances, i); + const json_t *url_json = json_array_get (json_donau_instances, i); const char *url_str = json_string_value (url_json); - output->details.donation_receipt.donau_urls[i] = strdup (url_str); + output->details.donation_receipt.donau_urls[i] = GNUNET_strdup ( + url_str); } } } @@ -3615,14 +3620,12 @@ parse_choices (struct OrderContext *oc) output.details.donation_receipt.amount = choice->amount; } - /* Make some predefines for the donation receipt */ - output.details.donation_receipt.donau_urls = NULL; - output.details.donation_receipt.donau_urls_len = 0; - /* If the system was complied with donau support, we can parse the donau instances */ - #ifdef HAVE_DONAU_DONAU_SERVICE_H +#ifdef HAVE_DONAU_DONAU_SERVICE_H + /* FIXME: Change to fetch and move to new phase */ + /* filter by currency */ parse_donau_instances (oc, &output); - #endif +#endif GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Output details donation receipt donau urls %p\n", diff --git a/src/backenddb/pg_lookup_order_charity.c b/src/backenddb/pg_lookup_order_charity.c @@ -32,7 +32,7 @@ #include "pg_lookup_order_charity.h" #include "pg_helper.h" - +/* FIXME: add instance */ enum GNUNET_DB_QueryStatus TMH_PG_lookup_order_charity ( void *cls, @@ -48,8 +48,10 @@ TMH_PG_lookup_order_charity ( }; struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("charity_id", charity_id), - GNUNET_PQ_result_spec_auto_from_type ("merchant_priv", charity_priv), + GNUNET_PQ_result_spec_uint64 ("charity_id", + charity_id), + GNUNET_PQ_result_spec_auto_from_type ("merchant_priv", + charity_priv), GNUNET_PQ_result_spec_end }; @@ -57,13 +59,14 @@ TMH_PG_lookup_order_charity ( PREPARE (pg, "lookup_donau_charity", - "SELECT di.charity_id, k.merchant_priv " - "FROM merchant_donau_instances di " - "JOIN merchant_instances mi " - " ON di.charity_pub_key = mi.merchant_pub " - "JOIN merchant_keys k " - " ON mi.merchant_serial = k.merchant_serial " - "WHERE di.donau_url=$1" + "SELECT di.charity_id" + " ,k.merchant_priv " + " FROM merchant_donau_instances di" + " JOIN merchant_instances mi" + " ON di.charity_pub_key = mi.merchant_pub" + " JOIN merchant_keys k" + " ON mi.merchant_serial = k.merchant_serial" + " WHERE di.donau_url=$1" ";"); return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,