commit 2dcbc692f955e9a5a40fd2570694ac0e2fae7222
parent d9cf9ee80fe28e01aa94c604c34e411b51a0d7ff
Author: bohdan-potuzhnyi <bohdan.potuzhnyi@gmail.com>
Date: Mon, 14 Jul 2025 14:56:26 +0200
correct donau return code
Diffstat:
3 files changed, 191 insertions(+), 179 deletions(-)
diff --git a/src/backend/taler-merchant-httpd_post-orders-ID-pay.c b/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
@@ -692,35 +692,37 @@ struct PayContext
} batch_deposits;
#ifdef HAVE_DONAU_DONAU_SERVICE_H
- struct {
- /**
- * The id of the charity as saved on the donau.
- */
- uint64_t charity_id;
-
- /**
- * Private key of the charity(related to the private key of the merchant).
- */
- struct DONAU_CharityPrivateKeyP *charity_priv;
-
- } charity;
-
- struct {
- /**
- * Receipts for the donations from the Donau.
- */
- struct DONAU_BlindedDonationUnitSignature *sigs;
-
- /**
- * Number of receipts for the donations from the Donau.
- */
- unsigned int num_sigs;
-
- /**
- * The donation receipt in json format.
- */
- json_t *donau_sigs_json;
- } donau_receipt;
+ struct
+ {
+ /**
+ * The id of the charity as saved on the donau.
+ */
+ uint64_t charity_id;
+
+ /**
+ * Private key of the charity(related to the private key of the merchant).
+ */
+ struct DONAU_CharityPrivateKeyP *charity_priv;
+
+ } charity;
+
+ struct
+ {
+ /**
+ * Receipts for the donations from the Donau.
+ */
+ struct DONAU_BlindedDonationUnitSignature *sigs;
+
+ /**
+ * Number of receipts for the donations from the Donau.
+ */
+ unsigned int num_sigs;
+
+ /**
+ * The donation receipt in json format.
+ */
+ json_t *donau_sigs_json;
+ } donau_receipt;
#endif
};
@@ -1776,9 +1778,9 @@ phase_success_response (struct PayContext *pc)
GNUNET_JSON_pack_array_steal ("token_sigs",
token_sigs)),
#ifdef HAVE_DONAU_DONAU_SERVICE_H
- GNUNET_JSON_pack_allow_null (
- GNUNET_JSON_pack_array_steal ("donau_sigs",
- pc->donau_receipt.donau_sigs_json)),
+ GNUNET_JSON_pack_allow_null (
+ GNUNET_JSON_pack_array_steal ("donau_sigs",
+ pc->donau_receipt.donau_sigs_json)),
#endif
GNUNET_JSON_pack_data_auto ("sig",
&sig)));
@@ -1841,6 +1843,7 @@ phase_payment_notification (struct PayContext *pc)
pc->phase = PP_SUCCESS_RESPONSE;
}
+
#ifdef HAVE_DONAU_DONAU_SERVICE_H
/**
@@ -1869,6 +1872,7 @@ signatures_to_JSON (const size_t num_sig,
}
}
+
static void
merchant_donau_issue_receipt_cb (void *cls,
const struct DONAU_BatchIssueResponse *resp)
@@ -1921,13 +1925,13 @@ merchant_donau_issue_receipt_cb (void *cls,
return;
}
- /* If the HTTP status is 200 (OK), we can read the union contents. */
- if (MHD_HTTP_OK == http_status)
+ /* If the HTTP status is 201 (CREATED), we can read the union contents. */
+ if (MHD_HTTP_CREATED == http_status)
{
pc->donau_receipt.sigs =
resp->details.ok.blinded_sigs; /* array of signatures */
- pc->donau_receipt.donau_sigs_json = json_array();
+ pc->donau_receipt.donau_sigs_json = json_array ();
if (NULL == pc->donau_receipt.donau_sigs_json)
{
GNUNET_break_op (0);
@@ -1964,6 +1968,7 @@ merchant_donau_issue_receipt_cb (void *cls,
pay_resume (pc);
}
+
/**
* Parse a bkp encoded in JSON.
*
@@ -1996,6 +2001,7 @@ merchant_parse_json_bkp (struct DONAU_BlindedUniqueDonorIdentifierKeyPair *bkp,
return GNUNET_OK;
}
+
#endif
@@ -2003,84 +2009,85 @@ static void
phase_generate_donation_receipt (struct PayContext *pc)
{
#ifndef HAVE_DONAU_DONAU_SERVICE_H
- /* If Donau is disabled at compile-time, skip. */
- pc->phase = PP_PAYMENT_NOTIFICATION;
- return;
+ /* If Donau is disabled at compile-time, skip. */
+ pc->phase = PP_PAYMENT_NOTIFICATION;
+ return;
#else
- /* 1) Parse the BUDIs array from JSON into an array of
- * DONAU_BlindedUniqueDonorIdentifierKeyPair. */
- const json_t *budikeypairs = pc->parse_wallet_data.donau.budikeypairs;
- size_t num_bkps = 0;
- struct DONAU_BlindedUniqueDonorIdentifierKeyPair *bkps = NULL;
+ /* 1) Parse the BUDIs array from JSON into an array of
+ * DONAU_BlindedUniqueDonorIdentifierKeyPair. */
+ const json_t *budikeypairs = pc->parse_wallet_data.donau.budikeypairs;
+ size_t num_bkps = 0;
+ struct DONAU_BlindedUniqueDonorIdentifierKeyPair *bkps = NULL;
- if ((NULL == budikeypairs) || (! json_is_array (budikeypairs)))
- {
- /* Missing or invalid budikeypairs array */
- resume_pay_with_error (pc,
- TALER_EC_GENERIC_PARAMETER_MALFORMED,
- "Missing or invalid 'budikeypairs' array");
- return;
- }
+ if ((NULL == budikeypairs) || (! json_is_array (budikeypairs)))
+ {
+ /* Missing or invalid budikeypairs array */
+ resume_pay_with_error (pc,
+ TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "Missing or invalid 'budikeypairs' array");
+ return;
+ }
- num_bkps = json_array_size (budikeypairs);
- /* Looks strange, but theoretically must work, at least donau uses it*/
- pc->donau_receipt.num_sigs = num_bkps;
- if (0 == num_bkps)
- {
- /* Theoretically is part is never reached, how do we behave? */
- resume_pay_with_error (pc,
- TALER_EC_GENERIC_PARAMETER_MALFORMED,
- "No budikeypairs provided");
- return;
- }
+ num_bkps = json_array_size (budikeypairs);
+ /* Looks strange, but theoretically must work, at least donau uses it*/
+ pc->donau_receipt.num_sigs = num_bkps;
+ if (0 == num_bkps)
+ {
+ /* Theoretically is part is never reached, how do we behave? */
+ resume_pay_with_error (pc,
+ TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "No budikeypairs provided");
+ return;
+ }
- bkps = GNUNET_new_array (num_bkps,
- struct DONAU_BlindedUniqueDonorIdentifierKeyPair);
+ bkps = GNUNET_new_array (num_bkps,
+ struct DONAU_BlindedUniqueDonorIdentifierKeyPair);
- /* Parse each BUDI object */
- for (size_t i = 0; i < num_bkps; i++)
- {
- const json_t *bkp_obj = json_array_get (budikeypairs, i);
- if (GNUNET_SYSERR == merchant_parse_json_bkp (&bkps[i], bkp_obj))
- {
- GNUNET_break_op (0);
- GNUNET_free (bkps);
- resume_pay_with_error (pc,
- TALER_EC_GENERIC_PARAMETER_MALFORMED,
- "Failed to parse budikeypairs");
- return;
- }
- }
-
- /* 2) Call DONAU_charity_issue_receipt() asynchronously. */
- struct DONAU_BatchIssueReceiptHandle *birh =
- DONAU_charity_issue_receipt (TMH_curl_ctx,
- pc->parse_wallet_data.donau.donau_url,
- pc->charity.charity_priv,
- pc->charity.charity_id,
- pc->parse_wallet_data.donau.donation_year,
- num_bkps,
- bkps,
- &merchant_donau_issue_receipt_cb,
- pc);
- if (NULL == birh)
+ /* Parse each BUDI object */
+ for (size_t i = 0; i < num_bkps; i++)
+ {
+ const json_t *bkp_obj = json_array_get (budikeypairs, i);
+ if (GNUNET_SYSERR == merchant_parse_json_bkp (&bkps[i], bkp_obj))
{
- /* The request was invalid from the library’s perspective. */
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to create Donau receipt request\n");
- resume_pay_with_error (pc,
- TALER_EC_GENERIC_CLIENT_INTERNAL_ERROR,
- "Donau error");
+ GNUNET_break_op (0);
GNUNET_free (bkps);
+ resume_pay_with_error (pc,
+ TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "Failed to parse budikeypairs");
return;
}
+ }
- /* As we do in the batch_issue for the exchange*/
- MHD_suspend_connection (pc->connection);
- pc->suspended = GNUNET_YES;
+ /* 2) Call DONAU_charity_issue_receipt() asynchronously. */
+ struct DONAU_BatchIssueReceiptHandle *birh =
+ DONAU_charity_issue_receipt (TMH_curl_ctx,
+ pc->parse_wallet_data.donau.donau_url,
+ pc->charity.charity_priv,
+ pc->charity.charity_id,
+ pc->parse_wallet_data.donau.donation_year,
+ num_bkps,
+ bkps,
+ &merchant_donau_issue_receipt_cb,
+ pc);
+ if (NULL == birh)
+ {
+ /* The request was invalid from the library’s perspective. */
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to create Donau receipt request\n");
+ resume_pay_with_error (pc,
+ TALER_EC_GENERIC_CLIENT_INTERNAL_ERROR,
+ "Donau error");
+ GNUNET_free (bkps);
+ return;
+ }
+
+ /* As we do in the batch_issue for the exchange*/
+ MHD_suspend_connection (pc->connection);
+ pc->suspended = GNUNET_YES;
#endif
}
+
/**
* Function called with information about a coin that was deposited.
*
@@ -2687,7 +2694,7 @@ phase_execute_pay_transaction (struct PayContext *pc)
{
const struct TALER_MERCHANT_ContractChoice *choice =
&pc->check_contract.contract_terms->details.v1
- .choices[pc->parse_wallet_data.choice_index];
+ .choices[pc->parse_wallet_data.choice_index];
/* If the matching contract-output is a donation-receipt, we skip it. */
if (i < choice->outputs_len &&
@@ -2750,7 +2757,7 @@ phase_execute_pay_transaction (struct PayContext *pc)
pc->charity.charity_priv = GNUNET_new (struct DONAU_CharityPrivateKeyP);
/* Part where we fetch info about the charity*/
- qs = TMH_db->lookup_order_charity(
+ qs = TMH_db->lookup_order_charity (
TMH_db->cls,
pc->parse_wallet_data.donau.donau_url,
&pc->charity.charity_id,
@@ -2878,7 +2885,7 @@ find_valid_input_tokens (
struct TokenUseConfirmation *tuc = &pc->parse_pay.tokens[index + j];
const struct TALER_MERCHANT_ContractTokenFamilyKey *key = NULL;
- for (unsigned int i=0; i<family->keys_len; i++)
+ for (unsigned int i = 0; i<family->keys_len; i++)
{
const struct TALER_MERCHANT_ContractTokenFamilyKey *ki
= &family->keys[i];
@@ -3121,9 +3128,9 @@ find_family (const struct PayContext *pc,
* @return GNUNET_OK on success, GNUNET_NO if an error was encountered
*/
static enum GNUNET_GenericReturnValue
-handle_output_token(struct PayContext *pc,
- const struct TALER_MERCHANT_ContractOutput *output,
- unsigned int output_index)
+handle_output_token (struct PayContext *pc,
+ const struct TALER_MERCHANT_ContractOutput *output,
+ unsigned int output_index)
{
const struct TALER_MERCHANT_ContractTokenFamily *family;
struct TALER_MERCHANT_ContractTokenFamilyKey *key;
@@ -3133,18 +3140,18 @@ handle_output_token(struct PayContext *pc,
/* Locate token family in the contract. This should never fail if
* the contract passed validation before insertion. */
- family = find_family(pc,
- output->details.token.token_family_slug);
+ family = find_family (pc,
+ output->details.token.token_family_slug);
if (NULL == family)
{
/* This "should never happen", so treat it as an internal error */
- GNUNET_break(0);
- pay_end(pc,
- TALER_MHD_reply_with_error(
- pc->connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
- "token family not found in order"));
+ GNUNET_break (0);
+ pay_end (pc,
+ TALER_MHD_reply_with_error (
+ pc->connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
+ "token family not found in order"));
return GNUNET_NO; /* signals error */
}
@@ -3152,13 +3159,13 @@ handle_output_token(struct PayContext *pc,
if (output->details.token.key_index >= family->keys_len)
{
/* Also "should never happen", contract was presumably validated on insert */
- GNUNET_break(0);
- pay_end(pc,
- TALER_MHD_reply_with_error(
- pc->connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
- "key index invalid for token family"));
+ GNUNET_break (0);
+ pay_end (pc,
+ TALER_MHD_reply_with_error (
+ pc->connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
+ "key index invalid for token family"));
return GNUNET_NO;
}
@@ -3167,7 +3174,7 @@ handle_output_token(struct PayContext *pc,
/* Fetch the private key from the DB for the merchant instance and
* this particular family/time interval. */
- qs = TMH_db->lookup_token_family_key(
+ qs = TMH_db->lookup_token_family_key (
TMH_db->cls,
pc->hc->instance->settings.id,
family->slug,
@@ -3176,36 +3183,39 @@ handle_output_token(struct PayContext *pc,
&details);
if (qs <= 0)
{
- GNUNET_log(
+ GNUNET_log (
GNUNET_ERROR_TYPE_ERROR,
"Did not find key for %s at [%llu,%llu]\n",
family->slug,
- (unsigned long long) pc->check_contract.contract_terms->timestamp.abs_time.abs_value_us,
- (unsigned long long) pc->check_contract.contract_terms->pay_deadline.abs_time.abs_value_us);
- GNUNET_break(0);
- pay_end(pc,
- TALER_MHD_reply_with_error(
- pc->connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- NULL));
+ (unsigned long
+ long) pc->check_contract.contract_terms->timestamp.abs_time.abs_value_us,
+ (unsigned long
+ long) pc->check_contract.contract_terms->pay_deadline.abs_time.
+ abs_value_us);
+ GNUNET_break (0);
+ pay_end (pc,
+ TALER_MHD_reply_with_error (
+ pc->connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ NULL));
return GNUNET_NO;
}
- GNUNET_assert(NULL != details.priv.private_key);
+ GNUNET_assert (NULL != details.priv.private_key);
/* Depending on the token family, decide if the token envelope
* is mandatory or optional. (Simplified logic here: adapt as needed.) */
- mandatory = test_tfk_mandatory(details.token_family.kind);
+ mandatory = test_tfk_mandatory (details.token_family.kind);
/* Actually sign the number of token envelopes specified in 'count'.
* 'output_index' is the offset into the parse_wallet_data arrays. */
if (GNUNET_OK !=
- sign_token_envelopes(pc,
- key,
- &details.priv,
- mandatory,
- output_index,
- output->details.token.count))
+ sign_token_envelopes (pc,
+ key,
+ &details.priv,
+ mandatory,
+ output_index,
+ output->details.token.count))
{
/* sign_token_envelopes() already queued up an error via pay_end() */
return GNUNET_NO;
@@ -3215,6 +3225,7 @@ handle_output_token(struct PayContext *pc,
return GNUNET_OK;
}
+
/**
* Handle checks for contract output of type TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT.
* For now, this does nothing and simply returns GNUNET_OK.
@@ -3226,7 +3237,8 @@ handle_output_token(struct PayContext *pc,
*/
static enum GNUNET_GenericReturnValue
handle_output_donation_receipt (struct PayContext *pc,
- const struct TALER_MERCHANT_ContractOutput *output,
+ const struct
+ TALER_MERCHANT_ContractOutput *output,
unsigned int output_index)
{
/* FIXME: Implement this function.
@@ -3241,7 +3253,6 @@ handle_output_donation_receipt (struct PayContext *pc,
}
-
/**
* Validate tokens and token envelopes. First, we check if all tokens listed
* in the 'inputs' array of the selected choice are present in the 'tokens'
@@ -3319,29 +3330,30 @@ phase_validate_tokens (struct PayContext *pc)
const struct TALER_MERCHANT_ContractOutput *output
= &selected->outputs[i];
- switch(output->type){
- case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN:
- if (GNUNET_OK !=
- handle_output_token (pc,
- output,
- i))
- {
- /* Error is already scheduled from handle_output_token. */
- return;
- }
- break;
- case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT:
- if (GNUNET_OK !=
- handle_output_donation_receipt (pc,
- output,
- i))
- {
- /* Error is already scheduled from handle_output_donation_receipt. */
- return;
- }
- continue;
- default:
- continue;
+ switch (output->type)
+ {
+ case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN:
+ if (GNUNET_OK !=
+ handle_output_token (pc,
+ output,
+ i))
+ {
+ /* Error is already scheduled from handle_output_token. */
+ return;
+ }
+ break;
+ case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT:
+ if (GNUNET_OK !=
+ handle_output_donation_receipt (pc,
+ output,
+ i))
+ {
+ /* Error is already scheduled from handle_output_donation_receipt. */
+ return;
+ }
+ continue;
+ default:
+ continue;
}
}
}
@@ -3959,14 +3971,14 @@ phase_parse_wallet_data (struct PayContext *pc)
if (NULL != donau_url_tmp)
pc->parse_wallet_data.donau.donau_url = GNUNET_strdup (donau_url_tmp);
- //FIXME: Probably some error handling could happen here
+ // FIXME: Probably some error handling could happen here
}
pc->parse_wallet_data.donau.donation_year = 0;
{
pc->parse_wallet_data.donau.donation_year = donation_year_tmp;
- //FIXME: What if the url is set but the year is not?
+ // FIXME: What if the url is set but the year is not?
// add error throwing
}
@@ -3975,7 +3987,7 @@ phase_parse_wallet_data (struct PayContext *pc)
{
pc->parse_wallet_data.donau.budikeypairs = budikeypairs;
- //FIXME: What if the url is set but the budis not?
+ // FIXME: What if the url is set but the budis not?
}
TALER_json_hash (pc->parse_pay.wallet_data,
@@ -4021,7 +4033,7 @@ phase_parse_pay (struct PayContext *pc)
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_SORT_KEYS /* deterministic output */);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"POST /orders/%s/pay – request body follows:\n%s\n",
diff --git a/src/include/taler_merchant_donau.h b/src/include/taler_merchant_donau.h
@@ -48,7 +48,7 @@ struct TALER_MERCHANT_DONAU_Charity
struct DONAU_CharityPublicKeyP charity_pub;
/**
- * Max donation amout for this charitiy and @e current_year.
+ * Max donation amount for this charitiy and @e current_year.
*/
struct TALER_Amount max_per_year;
@@ -145,7 +145,7 @@ typedef void
const struct TALER_Amount *charity_receipts_to_date,
int64_t current_year,
const json_t *donau_keys_json
-);
+ );
/**
* SPECIFICATION FOR REQUESTS /donau
@@ -262,7 +262,7 @@ typedef void
* @return the instance handle; NULL upon error
*/
struct TALER_MERCHANT_DonauInstanceGetHandle *
-TALER_MERCHANT_donau_instances_get(
+TALER_MERCHANT_donau_instances_get (
struct GNUNET_CURL_Context *ctx,
const char *backend_url,
TALER_MERCHANT_DonauInstanceGetCallback cb,
@@ -276,7 +276,7 @@ TALER_MERCHANT_donau_instances_get(
* @param dgh request to cancel.
*/
void
-TALER_MERCHANT_donau_instances_get_cancel(
+TALER_MERCHANT_donau_instances_get_cancel (
struct TALER_MERCHANT_DonauInstanceGetHandle *dgh);
@@ -310,7 +310,7 @@ typedef void
* @return the instance handle, or NULL upon error
*/
struct TALER_MERCHANT_DonauInstancePostHandle *
-TALER_MERCHANT_donau_instances_post(
+TALER_MERCHANT_donau_instances_post (
struct GNUNET_CURL_Context *ctx,
const char *backend_url,
const struct TALER_MERCHANT_DONAU_Charity *charity,
@@ -325,7 +325,7 @@ TALER_MERCHANT_donau_instances_post(
* @param dph request to cancel
*/
void
-TALER_MERCHANT_donau_instances_post_cancel(
+TALER_MERCHANT_donau_instances_post_cancel (
struct TALER_MERCHANT_DonauInstancePostHandle *dph);
@@ -356,7 +356,7 @@ typedef void
* @return Handle for the DELETE operation, or NULL on error.
*/
struct TALER_MERCHANT_DonauInstanceDeleteHandle *
-TALER_MERCHANT_donau_instance_delete(
+TALER_MERCHANT_donau_instance_delete (
struct GNUNET_CURL_Context *ctx,
const char *backend_url,
uint64_t charity_id,
@@ -369,7 +369,7 @@ TALER_MERCHANT_donau_instance_delete(
* @param ddh Handle for the operation to cancel.
*/
void
-TALER_MERCHANT_donau_instance_delete_cancel(
+TALER_MERCHANT_donau_instance_delete_cancel (
struct TALER_MERCHANT_DonauInstanceDeleteHandle *ddh);
#endif
\ No newline at end of file
diff --git a/src/testing/testing_api_cmd_pay_order.c b/src/testing/testing_api_cmd_pay_order.c
@@ -104,7 +104,7 @@ struct MerchantDonauPayData
uint64_t year;
/**
- * BUDI keypairs used in the payment (blinded_udi + pubkey).
+ * BUDI key pairs used in the payment (blinded_udi + pubkey).
*/
struct DONAU_BlindedUniqueDonorIdentifierKeyPair *bkps;