commit 08ce214e695e73a79e8344eed0e648a870121f61
parent 04b3192dbba7262bfa2714ff15cf44b55185bd89
Author: bohdan-potuzhnyi <bohdan.potuzhnyi@gmail.com>
Date: Tue, 15 Jul 2025 13:00:41 +0200
fixing errors, and a bit of restructuring
Diffstat:
5 files changed, 573 insertions(+), 469 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
@@ -374,6 +374,10 @@ struct ExchangeGroup
};
+/**
+ * Information about donau, that can be fetched even
+ * if the merhchant doesn't support donau
+ */
struct DonauData
{
/**
@@ -706,6 +710,27 @@ struct PayContext
} charity;
+ /**
+ * Struct to hold the clients bkps + donau request handler
+ */
+ struct
+ {
+ /**
+ * Number of the blinded key pairs
+ */
+ unsigned int num_bkps;
+
+ /**
+ * Blinded key pairs received from the wallet
+ */
+ struct DONAU_BlindedUniqueDonorIdentifierKeyPair *bkps;
+
+ /**
+ * Handler of the donau request
+ */
+ struct DONAU_BatchIssueReceiptHandle *birh;
+ } donau_handler;
+
struct
{
/**
@@ -1888,17 +1913,13 @@ merchant_donau_issue_receipt_cb (void *cls,
return;
}
- /* Extract overall HTTP status and Taler error code from 'resp->hr' */
- unsigned int http_status = resp->hr.http_status;
- enum TALER_ErrorCode ec = resp->hr.ec;
-
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Donau responded with status=%u, ec=%u\n",
- http_status,
- ec);
+ resp->hr.http_status,
+ resp->hr.ec);
/* If Donau gave 0 => means the reply was malformed or invalid. */
- if (0 == http_status)
+ if (0 == resp->hr.http_status)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Donau replied with status 0 => invalid or parse error\n");
@@ -1909,33 +1930,28 @@ merchant_donau_issue_receipt_cb (void *cls,
}
/* If Taler error code is non-zero => Donau signaled an error. */
- if (TALER_EC_NONE != ec)
+ if (TALER_EC_NONE != resp->hr.ec)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Donau responded with Taler error code %u\n",
- ec);
+ resp->hr.ec);
resume_pay_with_error (pc,
- ec,
+ resp->hr.ec,
"Donau returned an error");
return;
}
- /* If the HTTP status is 201 (CREATED), we can read the union contents. */
- if (MHD_HTTP_CREATED == http_status)
+ if (MHD_HTTP_CREATED == resp->hr.http_status)
{
pc->donau_receipt.sigs =
- resp->details.ok.blinded_sigs; /* array of signatures */
+ resp->details.ok.blinded_sigs;
- // TODO: For each output we have one signature(or rather for the selected donau_output_token),
- // we need to put them into the output token.
- // sigs.blinded_sig to the output_tokens[i].sig.signature
for (size_t i = 0; i<pc->validate_tokens.output_tokens_len; i++)
{
const struct TALER_MERCHANT_ContractChoice *choice =
&pc->check_contract.contract_terms->details.v1
.choices[pc->parse_wallet_data.choice_index];
- /* If the matching contract-output is a donation-receipt, we skip it. */
if (i < choice->outputs_len &&
TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT ==
choice->outputs[i].type)
@@ -1969,7 +1985,7 @@ merchant_donau_issue_receipt_cb (void *cls,
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Donau responded with HTTP code %u\n",
- http_status);
+ resp->hr.http_status);
resume_pay_with_error (pc,
TALER_EC_GENERIC_CLIENT_INTERNAL_ERROR,
@@ -2022,11 +2038,11 @@ merchant_parse_json_bkp (struct DONAU_BlindedUniqueDonorIdentifierKeyPair *bkp,
static void
phase_generate_donation_receipt (struct PayContext *pc)
{
- #ifndef HAVE_DONAU_DONAU_SERVICE_H
+#ifndef HAVE_DONAU_DONAU_SERVICE_H
/* If Donau is disabled at compile-time, skip. */
pc->phase = PP_PAYMENT_NOTIFICATION;
return;
- #else
+#else
/* 1) Parse the BUDIs array from JSON into an array of
* DONAU_BlindedUniqueDonorIdentifierKeyPair. */
const json_t *budikeypairs = pc->parse_wallet_data.donau.budikeypairs;
@@ -2098,7 +2114,7 @@ phase_generate_donation_receipt (struct PayContext *pc)
/* As we do in the batch_issue for the exchange*/
MHD_suspend_connection (pc->connection);
pc->suspended = GNUNET_YES;
- #endif
+#endif
}
@@ -2742,7 +2758,6 @@ phase_execute_pay_transaction (struct PayContext *pc)
}
// REVIEW: insert donau blinded inputs (into DB here!)
- // REVIEW: fetching the charity private key and ID from the DB
if (NULL != pc->parse_wallet_data.donau.budikeypairs)
{
enum GNUNET_DB_QueryStatus qs;
@@ -2767,42 +2782,6 @@ phase_execute_pay_transaction (struct PayContext *pc)
return;
}
}
-
- 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,
- pc->parse_wallet_data.donau.donau_url,
- &pc->charity.charity_id,
- pc->charity.charity_priv);
-
- if (0 > qs)
- {
- TMH_db->rollback (TMH_db->cls);
-
- /* just fail. */
- pay_end (pc,
- TALER_MHD_reply_with_error (
- pc->connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- "lookup_order_charity"));
- return;
- }
- else if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
- {
- /* The given donau_url was not found in merchant_donau_instances
- or the corresponding merchant_keys for the private key. */
- TMH_db->rollback (TMH_db->cls);
- pay_end (pc,
- TALER_MHD_reply_with_error (
- pc->connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PARAMETER_MALFORMED,
- "No matching Donau charity found for the given URL"));
- return;
- }
}
@@ -3847,9 +3826,7 @@ static void
phase_parse_wallet_data (struct PayContext *pc)
{
const json_t *tokens_evs;
- const json_t *budikeypairs = NULL;
- const char *donau_url_tmp = NULL;
- uint64_t donation_year_tmp = 0;
+ const json_t *donau_obj;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_mark_optional (
@@ -3860,30 +3837,10 @@ phase_parse_wallet_data (struct PayContext *pc)
GNUNET_JSON_spec_array_const ("tokens_evs",
&tokens_evs),
NULL),
-
- /* FIELDS for DONAU ------------------------------------- */
- /* "donau_url" is optional (a JSON string) */
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_string ("donau_url",
- &donau_url_tmp),
- NULL),
- /* "donation_year" is optional (parsed as uint64_t) */
GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_uint64 ("donau_year",
- &donation_year_tmp),
+ GNUNET_JSON_spec_object_const ("donau",
+ &donau_obj),
NULL),
- /* "budikeypairs" is optional (a JSON array) */
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_array_const ("donau_budikeypairs",
- &budikeypairs),
- NULL),
- /* ---------------------------------------------------------- */
- // REVIEW: extend spec for wallet to submit
- // - URL of selected donau
- // - year
- // - BUDIs with blinded donation receipts (donau-key-hash, blinded value)
- // + check in later phase (once we have the contract)
- // that the selected donau was offered and the BUDIs are below the allowed amount
GNUNET_JSON_spec_end ()
};
@@ -3980,29 +3937,139 @@ phase_parse_wallet_data (struct PayContext *pc)
}
}
- pc->parse_wallet_data.donau.donau_url = NULL;
+#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)
{
- if (NULL != donau_url_tmp)
- pc->parse_wallet_data.donau.donau_url = GNUNET_strdup (donau_url_tmp);
+ const char *donau_url_tmp = NULL;
+ uint64_t donation_year_tmp = 0;
+ const json_t *budikeypairs = NULL;
+
+ /* All three fields inside the object are required together. */
+ struct GNUNET_JSON_Specification dspec[] = {
+ GNUNET_JSON_spec_string ("url",
+ &donau_url_tmp),
+ GNUNET_JSON_spec_uint64 ("year",
+ &donation_year_tmp),
+ GNUNET_JSON_spec_array_const ("budikeypairs",
+ &budikeypairs),
+ GNUNET_JSON_spec_end ()
+ };
+ enum GNUNET_GenericReturnValue res;
- // FIXME: Probably some error handling could happen here
- }
+ res = TALER_MHD_parse_json_data (pc->connection,
+ donau_obj,
+ dspec);
+ if (GNUNET_YES != res)
+ {
+ GNUNET_break_op (0);
+ pay_end (pc,
+ (GNUNET_NO == res)
+ ? MHD_YES
+ : MHD_NO);
+ return;
+ }
- pc->parse_wallet_data.donau.donation_year = 0;
- {
- pc->parse_wallet_data.donau.donation_year = donation_year_tmp;
+ if (! json_is_array (budikeypairs) || (0 == json_array_size (budikeypairs)))
+ {
+ resume_pay_with_error (pc,
+ TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "Missing or empty 'budikeypairs' array");
+ return;
+ }
- // FIXME: What if the url is set but the year is not?
- // add error throwing
+ // Fetchning the charity information from the database based on the selected 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);
+
+ // TODO: Change to switch
+ if (0 > qs)
+ {
+ TMH_db->rollback (TMH_db->cls);
- }
+ /* just fail. */
+ pay_end (pc,
+ TALER_MHD_reply_with_error (
+ pc->connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ "lookup_order_charity"));
+ return;
+ }
+ else if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+ {
+ /* The given donau_url was not found in merchant_donau_instances
+ or the corresponding merchant_keys for the private key. */
+ TMH_db->rollback (TMH_db->cls);
+ pay_end (pc,
+ TALER_MHD_reply_with_error (
+ pc->connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "No matching Donau charity found for the given URL"));
+ return;
+ }
+ }
- pc->parse_wallet_data.donau.budikeypairs = NULL;
- {
+ 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;
- // FIXME: What if the url is set but the budis not?
+ // Stage to parse the budikeypairs from json to struct
+ {
+ size_t num_bkps = json_array_size (budikeypairs);
+ struct DONAU_BlindedUniqueDonorIdentifierKeyPair *bkps =
+ GNUNET_new_array (num_bkps,
+ struct DONAU_BlindedUniqueDonorIdentifierKeyPair);
+
+ 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;
+ }
+ }
+
+ 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. */
+ if (NULL != donau_obj)
+ {
+ pay_end (pc,
+ TALER_MHD_reply_with_error (pc->connection,
+ MHD_HTTP_NOT_IMPLEMENTED,
+ TALER_EC_MERCHANT_GENERIC_FEATURE_NOT_AVAILABLE,
+ "donau support disabled"));
+ return;
}
+#endif /* HAVE_DONAU_DONAU_SERVICE_H */
TALER_json_hash (pc->parse_pay.wallet_data,
&pc->parse_wallet_data.h_wallet_data);
diff --git a/src/backend/taler-merchant-httpd_private-post-orders.c b/src/backend/taler-merchant-httpd_private-post-orders.c
@@ -78,7 +78,7 @@
* refuses a forced download.
*/
#define MAX_KEYS_WAIT \
- GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 2500)
+ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 2500)
/**
* Generate the base URL for the given merchant instance.
@@ -2209,6 +2209,7 @@ set_max_fee (struct OrderContext *oc)
oc->phase++;
}
+
/**
* Exchange `/keys` processing is done, resume handling
* the order.
@@ -3353,24 +3354,26 @@ add_donau_url (void *cls,
const json_t *donau_keys_json)
{
json_t *json_instances = cls;
- GNUNET_assert(0 == json_array_append_new(json_instances, json_string(donau_url)));
+ GNUNET_assert (0 == json_array_append_new (json_instances, json_string (
+ donau_url)));
}
+
static void
parse_donau_instances (struct OrderContext *oc,
struct TALER_MERCHANT_ContractOutput *output)
{
- json_t *json_donau_instances = json_array();
+ json_t *json_donau_instances = json_array ();
enum GNUNET_DB_QueryStatus qs;
/* Invoke the database call, accumulating URLs in a JSON array */
- qs = TMH_db->select_donau_instance(TMH_db->cls,
- &add_donau_url,
- json_donau_instances);
+ qs = TMH_db->select_donau_instance (TMH_db->cls,
+ &add_donau_url,
+ json_donau_instances);
if (qs < 0)
{
- json_decref(json_donau_instances);
+ json_decref (json_donau_instances);
GNUNET_break_op (0);
reply_with_error (oc,
MHD_HTTP_INTERNAL_SERVER_ERROR,
@@ -3380,33 +3383,36 @@ parse_donau_instances (struct OrderContext *oc,
}
/* Convert the JSON array of strings into a C array of URLs */
- size_t num_instances = json_array_size(json_donau_instances);
- if (num_instances > 0)
{
- output->details.donation_receipt.donau_urls = malloc(num_instances * sizeof(char *));
- if (!output->details.donation_receipt.donau_urls)
+ size_t num_instances = json_array_size (json_donau_instances);
+ if (num_instances > 0)
{
- json_decref(json_donau_instances);
- GNUNET_break_op (0);
- reply_with_error (oc,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_CLIENT_INTERNAL_ERROR,
- "donau url parsing allocating memory");
- return;
- }
- output->details.donation_receipt.donau_urls_len = num_instances;
+ output->details.donation_receipt.donau_urls = malloc (num_instances
+ * sizeof(char *));
+ if (! output->details.donation_receipt.donau_urls)
+ {
+ json_decref (json_donau_instances);
+ GNUNET_break_op (0);
+ reply_with_error (oc,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_CLIENT_INTERNAL_ERROR,
+ "donau url parsing allocating memory");
+ return;
+ }
+ output->details.donation_receipt.donau_urls_len = num_instances;
- for (size_t i = 0; i < num_instances; i++)
- {
- 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);
+ for (size_t i = 0; i < num_instances; i++)
+ {
+ 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);
+ }
}
}
-
- json_decref(json_donau_instances);
+ json_decref (json_donau_instances);
}
+
#endif
/**
@@ -3603,8 +3609,8 @@ parse_choices (struct OrderContext *oc)
output.details.donation_receipt.amount.currency);
/* If amount wasn't set, we need to get it from the overall amount */
- if(GNUNET_OK !=
- TALER_amount_is_valid (&output.details.donation_receipt.amount))
+ if (GNUNET_OK !=
+ TALER_amount_is_valid (&output.details.donation_receipt.amount))
{
output.details.donation_receipt.amount = choice->amount;
}
@@ -3615,7 +3621,7 @@ parse_choices (struct OrderContext *oc)
/* If the system was complied with donau support, we can parse the donau instances */
#ifdef HAVE_DONAU_DONAU_SERVICE_H
- parse_donau_instances (oc, &output);
+ parse_donau_instances (oc, &output);
#endif
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
diff --git a/src/backenddb/pg_upsert_donau_keys.c b/src/backenddb/pg_upsert_donau_keys.c
@@ -39,33 +39,36 @@ TMH_PG_upsert_donau_keys (
if (NULL == jkeys)
return GNUNET_DB_STATUS_HARD_ERROR;
- struct GNUNET_PQ_QueryParam params[] = {
- TALER_PQ_query_param_json (jkeys),
- GNUNET_PQ_query_param_string (keys->donau_url),
- GNUNET_PQ_query_param_end
- };
+ {
+ struct GNUNET_PQ_QueryParam params[] = {
+ TALER_PQ_query_param_json (jkeys),
+ GNUNET_PQ_query_param_string (keys->donau_url),
+ GNUNET_PQ_query_param_end
+ };
- check_connection (pg);
- PREPARE (pg,
- "insert_donau_keys",
- "INSERT INTO merchant_donau_keys"
- "(keys_json"
- ",donau_url"
- ") VALUES ($1, $2);");
- PREPARE (pg,
- "update_donau_keys",
- "UPDATE merchant_donau_keys SET"
- " keys_json=$1"
- " WHERE"
- " donau_url=$2;");
+ check_connection (pg);
+ PREPARE (pg,
+ "insert_donau_keys",
+ "INSERT INTO merchant_donau_keys"
+ "(keys_json"
+ ",donau_url"
+ ") VALUES ($1, $2);");
+ PREPARE (pg,
+ "update_donau_keys",
+ "UPDATE merchant_donau_keys SET"
+ " keys_json=$1"
+ " WHERE"
+ " donau_url=$2;");
- qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "update_donau_keys",
- params);
- if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_donau_keys",
+ "update_donau_keys",
params);
+ if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+ qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_donau_keys",
+ params);
+ }
+
json_decref (jkeys);
return qs;
}
\ No newline at end of file
diff --git a/src/lib/taler_merchant_pay_service.c b/src/lib/taler_merchant_pay_service.c
@@ -71,7 +71,7 @@ struct TALER_MERCHANT_OrderPayHandle
struct TALER_PrivateContractHashP h_contract_terms;
bool has_merchant_pub;
- struct TALER_MerchantPublicKeyP merchant_pub;
+ struct TALER_MerchantPublicKeyP merchant_pub;
bool has_choice_index;
int choice_index;
@@ -81,17 +81,20 @@ struct TALER_MERCHANT_OrderPayHandle
const struct TALER_Amount *max_fee;
/* raw arrays as passed in via set_options(): */
- struct {
+ struct
+ {
unsigned int num_coins;
const struct TALER_MERCHANT_PayCoin *coins;
} coins;
- struct {
+ struct
+ {
unsigned int num_tokens;
const struct TALER_MERCHANT_UseToken *tokens;
} input_tokens;
- struct {
+ struct
+ {
unsigned int num_output_tokens;
const struct TALER_MERCHANT_OutputToken *output_tokens;
} output_tokens;
@@ -114,16 +117,18 @@ struct TALER_MERCHANT_OrderPayHandle
bool am_wallet;
+ json_t *donau_data;
+ // TODO: Remove this block;
/* --- Donau (optional) ------------------------------------------------- */
#ifdef HAVE_DONAU_DONAU_SERVICE_H
- bool has_donau_url;
- char *donau_url;
+ bool has_donau_url;
+ char *donau_url;
- bool has_donau_year;
- uint64_t donau_year;
+ bool has_donau_year;
+ uint64_t donau_year;
- bool has_donau_budis;
- json_t *donau_budikeypairs; /* array we’ll own */
+ bool has_donau_budis;
+ json_t *donau_budikeypairs; /* array we’ll own */
#endif
};
@@ -173,6 +178,7 @@ parse_tokens (const json_t *token_sigs,
return GNUNET_YES;
}
+
/**
* Function called when we're done processing the
* HTTP /pay request.
@@ -183,8 +189,8 @@ parse_tokens (const json_t *token_sigs,
*/
static void
handle_finished (void *cls,
- long response_code,
- const void *resp)
+ long response_code,
+ const void *resp)
{
struct TALER_MERCHANT_OrderPayHandle *oph = cls;
const json_t *json = resp;
@@ -207,123 +213,123 @@ handle_finished (void *cls,
(unsigned int) response_code);
switch (response_code)
{
- case 0:
- pr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
- break;
- case MHD_HTTP_OK:
- if (oph->am_wallet)
+ case 0:
+ pr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
+ break;
+ case MHD_HTTP_OK:
+ if (oph->am_wallet)
+ {
+ const json_t *token_sigs = NULL;
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_fixed_auto ("sig",
+ &pr.details.ok.merchant_sig),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_string ("pos_confirmation",
+ &pr.details.ok.pos_confirmation),
+ NULL),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_array_const ("token_sigs",
+ &token_sigs),
+ NULL),
+ GNUNET_JSON_spec_end ()
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (json,
+ spec,
+ NULL, NULL))
{
- const json_t *token_sigs = NULL;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("sig",
- &pr.details.ok.merchant_sig),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_string ("pos_confirmation",
- &pr.details.ok.pos_confirmation),
- NULL),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_array_const ("token_sigs",
- &token_sigs),
- NULL),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (json,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- pr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
- pr.hr.http_status = 0;
- pr.hr.hint = "sig field missing in response";
- break;
- }
+ GNUNET_break_op (0);
+ pr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
+ pr.hr.http_status = 0;
+ pr.hr.hint = "sig field missing in response";
+ break;
+ }
- if (GNUNET_OK !=
- parse_tokens (token_sigs,
- &pr.details.ok.tokens,
- &pr.details.ok.num_tokens))
- {
- GNUNET_break_op (0);
- pr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
- pr.hr.http_status = 0;
- pr.hr.hint = "failed to parse token_sigs field in response";
- break;
- }
+ if (GNUNET_OK !=
+ parse_tokens (token_sigs,
+ &pr.details.ok.tokens,
+ &pr.details.ok.num_tokens))
+ {
+ GNUNET_break_op (0);
+ pr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
+ pr.hr.http_status = 0;
+ pr.hr.hint = "failed to parse token_sigs field in response";
+ break;
+ }
- if (GNUNET_OK !=
- TALER_merchant_pay_verify (&oph->h_contract_terms,
- &oph->merchant_pub,
- &pr.details.ok.merchant_sig))
- {
- GNUNET_break_op (0);
- pr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
- pr.hr.http_status = 0;
- pr.hr.hint = "signature invalid";
- }
+ if (GNUNET_OK !=
+ TALER_merchant_pay_verify (&oph->h_contract_terms,
+ &oph->merchant_pub,
+ &pr.details.ok.merchant_sig))
+ {
+ GNUNET_break_op (0);
+ pr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
+ pr.hr.http_status = 0;
+ pr.hr.hint = "signature invalid";
}
- break;
- /* Tolerating Not Acceptable because sometimes
- * - especially in tests - we might want to POST
- * coins one at a time. */
- case MHD_HTTP_NOT_ACCEPTABLE:
- pr.hr.ec = TALER_JSON_get_error_code (json);
- pr.hr.hint = TALER_JSON_get_error_hint (json);
- break;
- case MHD_HTTP_BAD_REQUEST:
- pr.hr.ec = TALER_JSON_get_error_code (json);
- pr.hr.hint = TALER_JSON_get_error_hint (json);
- /* This should never happen, either us
- * or the merchant is buggy (or API version conflict);
- * just pass JSON reply to the application */
- break;
- case MHD_HTTP_PAYMENT_REQUIRED:
- /* was originally paid, but then refunded */
- pr.hr.ec = TALER_JSON_get_error_code (json);
- pr.hr.hint = TALER_JSON_get_error_hint (json);
- break;
- case MHD_HTTP_FORBIDDEN:
- pr.hr.ec = TALER_JSON_get_error_code (json);
- pr.hr.hint = TALER_JSON_get_error_hint (json);
- break;
- case MHD_HTTP_NOT_FOUND:
- pr.hr.ec = TALER_JSON_get_error_code (json);
- pr.hr.hint = TALER_JSON_get_error_hint (json);
- /* Nothing really to verify, this should never
- happen, we should pass the JSON reply to the
- application */
- break;
- case MHD_HTTP_REQUEST_TIMEOUT:
- pr.hr.ec = TALER_JSON_get_error_code (json);
- pr.hr.hint = TALER_JSON_get_error_hint (json);
- /* The merchant couldn't generate a timely response, likely because
- it itself waited too long on the exchange.
- Pass on to application. */
- break;
- case MHD_HTTP_CONFLICT:
- TALER_MERCHANT_parse_error_details_ (json,
- MHD_HTTP_CONFLICT,
- &pr.hr);
- break;
- case MHD_HTTP_GONE:
- TALER_MERCHANT_parse_error_details_ (json,
- response_code,
- &pr.hr);
- /* The merchant says we are too late, the offer has expired or some
- denomination key of a coin involved has expired.
- Might be a disagreement in timestamps? Still, pass on to application. */
- break;
- case MHD_HTTP_PRECONDITION_FAILED:
- TALER_MERCHANT_parse_error_details_ (json,
- response_code,
- &pr.hr);
- /* Nothing really to verify, the merchant is blaming us for failing to
- satisfy some constraint (likely it does not like our exchange because
- of some disagreement on the PKI). We should pass the JSON reply to the
- application */
- break;
- case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
+ }
+ break;
+ /* Tolerating Not Acceptable because sometimes
+ * - especially in tests - we might want to POST
+ * coins one at a time. */
+ case MHD_HTTP_NOT_ACCEPTABLE:
+ pr.hr.ec = TALER_JSON_get_error_code (json);
+ pr.hr.hint = TALER_JSON_get_error_hint (json);
+ break;
+ case MHD_HTTP_BAD_REQUEST:
+ pr.hr.ec = TALER_JSON_get_error_code (json);
+ pr.hr.hint = TALER_JSON_get_error_hint (json);
+ /* This should never happen, either us
+ * or the merchant is buggy (or API version conflict);
+ * just pass JSON reply to the application */
+ break;
+ case MHD_HTTP_PAYMENT_REQUIRED:
+ /* was originally paid, but then refunded */
+ pr.hr.ec = TALER_JSON_get_error_code (json);
+ pr.hr.hint = TALER_JSON_get_error_hint (json);
+ break;
+ case MHD_HTTP_FORBIDDEN:
+ pr.hr.ec = TALER_JSON_get_error_code (json);
+ pr.hr.hint = TALER_JSON_get_error_hint (json);
+ break;
+ case MHD_HTTP_NOT_FOUND:
+ pr.hr.ec = TALER_JSON_get_error_code (json);
+ pr.hr.hint = TALER_JSON_get_error_hint (json);
+ /* Nothing really to verify, this should never
+ happen, we should pass the JSON reply to the
+ application */
+ break;
+ case MHD_HTTP_REQUEST_TIMEOUT:
+ pr.hr.ec = TALER_JSON_get_error_code (json);
+ pr.hr.hint = TALER_JSON_get_error_hint (json);
+ /* The merchant couldn't generate a timely response, likely because
+ it itself waited too long on the exchange.
+ Pass on to application. */
+ break;
+ case MHD_HTTP_CONFLICT:
+ TALER_MERCHANT_parse_error_details_ (json,
+ MHD_HTTP_CONFLICT,
+ &pr.hr);
+ break;
+ case MHD_HTTP_GONE:
+ TALER_MERCHANT_parse_error_details_ (json,
+ response_code,
+ &pr.hr);
+ /* The merchant says we are too late, the offer has expired or some
+ denomination key of a coin involved has expired.
+ Might be a disagreement in timestamps? Still, pass on to application. */
+ break;
+ case MHD_HTTP_PRECONDITION_FAILED:
+ TALER_MERCHANT_parse_error_details_ (json,
+ response_code,
+ &pr.hr);
+ /* Nothing really to verify, the merchant is blaming us for failing to
+ satisfy some constraint (likely it does not like our exchange because
+ of some disagreement on the PKI). We should pass the JSON reply to the
+ application */
+ break;
+ case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
{
json_t *ebus = json_object_get (json,
"exchange_base_urls");
@@ -363,54 +369,54 @@ handle_finished (void *cls,
pr.details.unavailable_for_legal_reasons.exchanges
= ebua;
oph->cb (oph->cb_cls,
- &pr);
+ &pr);
TALER_MERCHANT_order_pay_cancel1 (oph);
return;
}
}
- break;
- case MHD_HTTP_INTERNAL_SERVER_ERROR:
- TALER_MERCHANT_parse_error_details_ (json,
- response_code,
- &pr.hr);
- /* Server had an internal issue; we should retry,
- but this API leaves this to the application */
- break;
- case MHD_HTTP_BAD_GATEWAY:
- /* Nothing really to verify, the merchant is blaming the exchange.
- We should pass the JSON reply to the application */
- TALER_MERCHANT_parse_error_details_ (json,
- response_code,
- &pr.hr);
- break;
- case MHD_HTTP_SERVICE_UNAVAILABLE:
- TALER_MERCHANT_parse_error_details_ (json,
- response_code,
- &pr.hr);
- /* Exchange couldn't respond properly; the retry is
- left to the application */
- break;
- case MHD_HTTP_GATEWAY_TIMEOUT:
- TALER_MERCHANT_parse_error_details_ (json,
- response_code,
- &pr.hr);
- /* Exchange couldn't respond in a timely fashion;
- the retry is left to the application */
- break;
- default:
- TALER_MERCHANT_parse_error_details_ (json,
- response_code,
- &pr.hr);
- /* unexpected response code */
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u/%d\n",
- (unsigned int) response_code,
- (int) pr.hr.ec);
- GNUNET_break_op (0);
- break;
+ break;
+ case MHD_HTTP_INTERNAL_SERVER_ERROR:
+ TALER_MERCHANT_parse_error_details_ (json,
+ response_code,
+ &pr.hr);
+ /* Server had an internal issue; we should retry,
+ but this API leaves this to the application */
+ break;
+ case MHD_HTTP_BAD_GATEWAY:
+ /* Nothing really to verify, the merchant is blaming the exchange.
+ We should pass the JSON reply to the application */
+ TALER_MERCHANT_parse_error_details_ (json,
+ response_code,
+ &pr.hr);
+ break;
+ case MHD_HTTP_SERVICE_UNAVAILABLE:
+ TALER_MERCHANT_parse_error_details_ (json,
+ response_code,
+ &pr.hr);
+ /* Exchange couldn't respond properly; the retry is
+ left to the application */
+ break;
+ case MHD_HTTP_GATEWAY_TIMEOUT:
+ TALER_MERCHANT_parse_error_details_ (json,
+ response_code,
+ &pr.hr);
+ /* Exchange couldn't respond in a timely fashion;
+ the retry is left to the application */
+ break;
+ default:
+ TALER_MERCHANT_parse_error_details_ (json,
+ response_code,
+ &pr.hr);
+ /* unexpected response code */
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unexpected response code %u/%d\n",
+ (unsigned int) response_code,
+ (int) pr.hr.ec);
+ GNUNET_break_op (0);
+ break;
}
oph->cb (oph->cb_cls,
- &pr);
+ &pr);
if (pr.details.ok.tokens)
{
@@ -422,13 +428,15 @@ handle_finished (void *cls,
TALER_MERCHANT_order_pay_cancel1 (oph);
}
+
struct TALER_MERCHANT_OrderPayHandle *
TALER_MERCHANT_order_pay_create (struct GNUNET_CURL_Context *ctx,
TALER_MERCHANT_OrderPayCallback cb,
- TALER_MERCHANT_ORDER_PAY_CALLBACK_CLOSURE_TYPE *cb_cls)
+ TALER_MERCHANT_ORDER_PAY_CALLBACK_CLOSURE_TYPE
+ *cb_cls)
{
struct TALER_MERCHANT_OrderPayHandle *ph =
- GNUNET_new (struct TALER_MERCHANT_OrderPayHandle);
+ GNUNET_new (struct TALER_MERCHANT_OrderPayHandle);
ph->ctx = ctx;
ph->cb = cb;
ph->cb_cls = cb_cls;
@@ -437,6 +445,7 @@ TALER_MERCHANT_order_pay_create (struct GNUNET_CURL_Context *ctx,
return ph;
}
+
void
TALER_MERCHANT_order_pay_cancel1 (struct TALER_MERCHANT_OrderPayHandle *ph)
{
@@ -458,12 +467,9 @@ TALER_MERCHANT_order_pay_cancel1 (struct TALER_MERCHANT_OrderPayHandle *ph)
json_decref (ph->tokens_evs);
ph->tokens_evs = NULL;
- #ifdef HAVE_DONAU_DONAU_SERVICE_H
- GNUNET_free (ph->donau_url);
- if (ph->donau_budikeypairs)
- json_decref (ph->donau_budikeypairs);
- #endif
-
+ GNUNET_free (ph->donau_url);
+ if (ph->donau_budikeypairs)
+ json_decref (ph->donau_budikeypairs);
GNUNET_free (ph->url);
GNUNET_free (ph->merchant_url);
@@ -472,12 +478,14 @@ TALER_MERCHANT_order_pay_cancel1 (struct TALER_MERCHANT_OrderPayHandle *ph)
GNUNET_free (ph);
}
+
static enum TALER_MERCHANT_OrderPayOptionErrorCode
store_json_option (struct TALER_MERCHANT_OrderPayHandle *ph,
enum TALER_MERCHANT_OrderPayOptionType ot,
json_t *snippet)
{
- if (ph->field_seen[ot]) {
+ if (ph->field_seen[ot])
+ {
json_decref (snippet);
return TALER_MERCHANT_OPOEC_DUPLICATE_OPTION;
}
@@ -487,39 +495,46 @@ store_json_option (struct TALER_MERCHANT_OrderPayHandle *ph,
return TALER_MERCHANT_OPOEC_OK;
}
+
enum TALER_MERCHANT_OrderPayOptionErrorCode
TALER_MERCHANT_order_pay_set_options (struct TALER_MERCHANT_OrderPayHandle *ph,
- const struct TALER_MERCHANT_OrderPayOption options[],
+ const struct TALER_MERCHANT_OrderPayOption
+ options[],
size_t max_options)
{
for (size_t i = 0; i < max_options
- && options[i].ot != TALER_MERCHANT_OrderPayOptionType_END; i++)
+ && options[i].ot != TALER_MERCHANT_OrderPayOptionType_END; i++)
{
const struct TALER_MERCHANT_OrderPayOption *o = &options[i];
switch (o->ot)
{
- case TALER_MERCHANT_OrderPayOptionType_MERCHANT_URL:
- ph->merchant_url = GNUNET_strdup(o->details.merchant_url);
- break;
+ case TALER_MERCHANT_OrderPayOptionType_MERCHANT_URL:
+ ph->merchant_url = GNUNET_strdup (o->details.merchant_url);
+ break;
- case TALER_MERCHANT_OrderPayOptionType_SESSION_ID:
- ph->session_id = GNUNET_strdup(o->details.session_id);
- /* add straight into JSON body */
- {
- json_t *js = GNUNET_JSON_PACK(GNUNET_JSON_pack_string("session_id", o->details.session_id));
- enum TALER_MERCHANT_OrderPayOptionErrorCode ec = store_json_option(ph, o->ot, js);
- if (TALER_MERCHANT_OPOEC_OK != ec)
- return ec;
- break;
- }
+ case TALER_MERCHANT_OrderPayOptionType_SESSION_ID:
+ ph->session_id = GNUNET_strdup (o->details.session_id);
+ /* add straight into JSON body */
+ {
+ json_t *js = GNUNET_JSON_PACK (GNUNET_JSON_pack_string ("session_id",
+ o->details.
+ session_id));
+ enum TALER_MERCHANT_OrderPayOptionErrorCode ec = store_json_option (ph,
+ o->
+ ot,
+ js);
+ if (TALER_MERCHANT_OPOEC_OK != ec)
+ return ec;
+ break;
+ }
- case TALER_MERCHANT_OrderPayOptionType_ORDER_ID:
+ case TALER_MERCHANT_OrderPayOptionType_ORDER_ID:
{
- ph->order_id = GNUNET_strdup(o->details.order_id);
+ ph->order_id = GNUNET_strdup (o->details.order_id);
break;
}
- case TALER_MERCHANT_OrderPayOptionType_H_CONTRACT:
+ case TALER_MERCHANT_OrderPayOptionType_H_CONTRACT:
{
ph->h_contract_terms = *o->details.h_contract;
ph->has_h_contract = true;
@@ -527,24 +542,24 @@ TALER_MERCHANT_order_pay_set_options (struct TALER_MERCHANT_OrderPayHandle *ph,
break;
}
- case TALER_MERCHANT_OrderPayOptionType_CHOICE_INDEX:
- ph->choice_index = o->details.choice_index;
- ph->has_choice_index = true;
- break;
+ case TALER_MERCHANT_OrderPayOptionType_CHOICE_INDEX:
+ ph->choice_index = o->details.choice_index;
+ ph->has_choice_index = true;
+ break;
- case TALER_MERCHANT_OrderPayOptionType_AMOUNT:
+ case TALER_MERCHANT_OrderPayOptionType_AMOUNT:
{
ph->amount = &o->details.amount;
break;
}
- case TALER_MERCHANT_OrderPayOptionType_MAX_FEE:
+ case TALER_MERCHANT_OrderPayOptionType_MAX_FEE:
{
ph->max_fee = &o->details.max_fee;
break;
}
- case TALER_MERCHANT_OrderPayOptionType_MERCHANT_PUB:
+ case TALER_MERCHANT_OrderPayOptionType_MERCHANT_PUB:
{
ph->merchant_pub = o->details.merchant_pub;
ph->has_merchant_pub = true;
@@ -552,26 +567,26 @@ TALER_MERCHANT_order_pay_set_options (struct TALER_MERCHANT_OrderPayHandle *ph,
break;
}
- case TALER_MERCHANT_OrderPayOptionType_TIMESTAMP:
+ case TALER_MERCHANT_OrderPayOptionType_TIMESTAMP:
{
ph->timestamp = o->details.timestamp;
break;
}
- case TALER_MERCHANT_OrderPayOptionType_REFUND_DEADLINE:
+ case TALER_MERCHANT_OrderPayOptionType_REFUND_DEADLINE:
{
ph->refund_deadline = o->details.refund_deadline;
break;
}
- case TALER_MERCHANT_OrderPayOptionType_PAY_DEADLINE:
+ case TALER_MERCHANT_OrderPayOptionType_PAY_DEADLINE:
{
- //FIXME: This one comes from the merchant_api_post_order_pay
+ // FIXME: This one comes from the merchant_api_post_order_pay
// no idea do we still need it or not?
break;
}
- case TALER_MERCHANT_OrderPayOptionType_H_WIRE:
+ case TALER_MERCHANT_OrderPayOptionType_H_WIRE:
{
ph->h_wire = o->details.h_wire;
ph->has_h_wire = true;
@@ -579,79 +594,93 @@ TALER_MERCHANT_order_pay_set_options (struct TALER_MERCHANT_OrderPayHandle *ph,
break;
}
- case TALER_MERCHANT_OrderPayOptionType_COINS:
- /* stash for later signing */
- GNUNET_assert(o->details.coins.num_coins >= 0);
- ph->coins.num_coins = o->details.coins.num_coins;
- ph->coins.coins = o->details.coins.coins;
- //ph->field_seen[o->ot] = true;
- break;
+ case TALER_MERCHANT_OrderPayOptionType_COINS:
+ /* stash for later signing */
+ GNUNET_assert (o->details.coins.num_coins >= 0);
+ ph->coins.num_coins = o->details.coins.num_coins;
+ ph->coins.coins = o->details.coins.coins;
+ // ph->field_seen[o->ot] = true;
+ break;
- case TALER_MERCHANT_OrderPayOptionType_INPUT_TOKENS:
- /* stash for later signing */
- ph->input_tokens.num_tokens = o->details.input_tokens.num_tokens;
- ph->input_tokens.tokens = o->details.input_tokens.tokens;
- break;
+ case TALER_MERCHANT_OrderPayOptionType_INPUT_TOKENS:
+ /* stash for later signing */
+ ph->input_tokens.num_tokens = o->details.input_tokens.num_tokens;
+ ph->input_tokens.tokens = o->details.input_tokens.tokens;
+ break;
- case TALER_MERCHANT_OrderPayOptionType_OUTPUT_TOKENS:
- /* store JSON array directly, *and* stash for hash */
- ph->output_tokens.num_output_tokens = o->details.output_tokens.num_output_tokens;
- ph->output_tokens.output_tokens = o->details.output_tokens.output_tokens;
+ case TALER_MERCHANT_OrderPayOptionType_OUTPUT_TOKENS:
+ /* store JSON array directly, *and* stash for hash */
+ ph->output_tokens.num_output_tokens =
+ o->details.output_tokens.num_output_tokens;
+ ph->output_tokens.output_tokens = o->details.output_tokens.output_tokens;
+ {
+ /* build and store tokens_evs */
+ json_t *arr = json_array ();
+ for (unsigned j = 0; j < ph->output_tokens.num_output_tokens; j++)
{
- /* build and store tokens_evs */
- json_t *arr = json_array();
- for (unsigned j = 0; j < ph->output_tokens.num_output_tokens; j++)
- {
- const struct TALER_MERCHANT_OutputToken *otk = &ph->output_tokens.output_tokens[j];
- json_t *je = GNUNET_JSON_PACK(TALER_JSON_pack_token_envelope(NULL, &otk->envelope));
- json_array_append_new(arr, je);
- }
+ const struct TALER_MERCHANT_OutputToken *otk =
+ &ph->output_tokens.output_tokens[j];
+ json_t *je = GNUNET_JSON_PACK (TALER_JSON_pack_token_envelope (NULL,
+ &otk->
+ envelope));
+ json_array_append_new (arr, je);
+ }
- ph->tokens_evs = arr;
+ ph->tokens_evs = arr;
- ph->field_seen[o->ot] = true;
- }
+ ph->field_seen[o->ot] = true;
+ }
+ break;
+
+ case TALER_MERCHANT_OrderPayOptionType_DONAU_URL:
+ {
+ if (ph->donau_data == NULL)
+ ph->donau_data = json_object ();
+ GNUNET_assert (0 == json_object_set_new (
+ ph->donau_data,
+ "url",
+ json_string (o->details.donau_url)));
+ break;
+ }
+
+ case TALER_MERCHANT_OrderPayOptionType_DONAU_YEAR:
+ {
+ // TODO: As the donau_year is part of the donau object, we can already put it inside the json_t donau_data
+ if (ph->donau_data == NULL)
+ ph->donau_data = json_object ();
+ GNUNET_assert (0 == json_object_set_new (
+ ph->donau_data,
+ "year",
+ json_integer ((json_int_t) o->details.donau_year)));
+ break;
+ }
+
+ case TALER_MERCHANT_OrderPayOptionType_DONAU_BUDIS:
+ {
+ if (ph->donau_data == NULL)
+ ph->donau_data = json_object ();
+ GNUNET_assert (0 == json_object_set_new (
+ ph->donau_data,
+ "budikeypairs",
+ json_incref (o->details.donau_budis_json)));
break;
+ }
-#ifdef HAVE_DONAU_DONAU_SERVICE_H
- /* ---------- Donau ------------ */
- case TALER_MERCHANT_OrderPayOptionType_DONAU_URL:
- {
- ph->has_donau_url = true;
- ph->donau_url = GNUNET_strdup (o->details.donau_url);
- break;
- }
-
- case TALER_MERCHANT_OrderPayOptionType_DONAU_YEAR:
- {
- ph->has_donau_year = true;
- ph->donau_year = o->details.donau_year;
- break;
- }
-
- case TALER_MERCHANT_OrderPayOptionType_DONAU_BUDIS:
- {
- ph->has_donau_budis = true;
- ph->donau_budikeypairs = o->details.donau_budis_json;
- json_incref (ph->donau_budikeypairs);
- break;
- }
-#endif /* HAVE_DONAU_DONAU_SERVICE_H */
-
- default:
- return TALER_MERCHANT_OPOEC_UNKNOWN_OPTION;
+ default:
+ return TALER_MERCHANT_OPOEC_UNKNOWN_OPTION;
}
}
return TALER_MERCHANT_OPOEC_OK;
}
+
enum TALER_MERCHANT_OrderPayOptionErrorCode
TALER_MERCHANT_order_pay_start (struct TALER_MERCHANT_OrderPayHandle *ph)
{
/* all the old mandatory checks */
- if (!ph->merchant_url || !ph->order_id)
+ if (! ph->merchant_url || ! ph->order_id)
return TALER_MERCHANT_OPOEC_MISSING_MANDATORY;
- if ( !(ph->coins.num_coins >= 0) )
+ if (! (ph->coins.num_coins >= 0) )
return TALER_MERCHANT_OPOEC_MISSING_MANDATORY;
if (GNUNET_YES !=
@@ -662,31 +691,21 @@ TALER_MERCHANT_order_pay_start (struct TALER_MERCHANT_OrderPayHandle *ph)
}
/* --- build wallet_data hash for signing coins & tokens --- */
- if (ph->has_choice_index) {
- /* base fields */
- json_t *wd = GNUNET_JSON_PACK (
- GNUNET_JSON_pack_int64 ("choice_index", ph->choice_index),
- GNUNET_JSON_pack_allow_null (
- GNUNET_JSON_pack_array_incref ("tokens_evs", ph->tokens_evs))
+ if (ph->has_choice_index)
+ {
+ /* base fields */
+ json_t *wd = GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_int64 ("choice_index", ph->choice_index),
+ GNUNET_JSON_pack_allow_null (
+ GNUNET_JSON_pack_array_incref ("tokens_evs", ph->tokens_evs))
);
- #ifdef HAVE_DONAU_DONAU_SERVICE_H
- /* Donau extras (optional) */
- if (ph->has_donau_url)
- GNUNET_assert (0 == json_object_set_new (wd,
- "donau_url",
- json_string (ph->donau_url)));
-
- if (ph->has_donau_year)
- GNUNET_assert (0 == json_object_set_new (wd,
- "donau_year",
- json_integer ((json_int_t) ph->donau_year)));
-
- if (ph->has_donau_budis)
- GNUNET_assert (0 == json_object_set_new (wd,
- "donau_budikeypairs",
- json_incref (ph->donau_budikeypairs)));
- #endif
+ // Putting prepared donau_data into the wallet_data
+ if (ph->donau_data)
+ GNUNET_assert (0 == json_object_set_new (
+ wd,
+ "donau",
+ json_incref (ph->donau_data)));
ph->wallet_data = wd;
@@ -714,26 +733,27 @@ TALER_MERCHANT_order_pay_start (struct TALER_MERCHANT_OrderPayHandle *ph)
struct TALER_Amount fee;
struct TALER_DenominationHashP h_denom_pub;
- TALER_denom_pub_hash(&c->denom_pub, &h_denom_pub);
- if (0 > TALER_amount_subtract(&fee, &c->amount_with_fee, &c->amount_without_fee))
+ TALER_denom_pub_hash (&c->denom_pub, &h_denom_pub);
+ if (0 > TALER_amount_subtract (&fee, &c->amount_with_fee,
+ &c->amount_without_fee))
return TALER_MERCHANT_OPOEC_INVALID_VALUE;
- TALER_wallet_deposit_sign(&c->amount_with_fee,
- &fee,
- &ph->h_wire,
- &ph->h_contract_terms,
- (NULL != ph->wallet_data)
+ TALER_wallet_deposit_sign (&c->amount_with_fee,
+ &fee,
+ &ph->h_wire,
+ &ph->h_contract_terms,
+ (NULL != ph->wallet_data)
? &ph->wallet_data_hash
: NULL,
- c->h_age_commitment,
- NULL,
- &h_denom_pub,
- ph->timestamp,
- &ph->merchant_pub,
- ph->refund_deadline,
- &c->coin_priv,
- &pc.coin_sig);
+ c->h_age_commitment,
+ NULL,
+ &h_denom_pub,
+ ph->timestamp,
+ &ph->merchant_pub,
+ ph->refund_deadline,
+ &c->coin_priv,
+ &pc.coin_sig);
pc.denom_pub = c->denom_pub;
pc.denom_sig = c->denom_sig;
@@ -741,17 +761,23 @@ TALER_MERCHANT_order_pay_start (struct TALER_MERCHANT_OrderPayHandle *ph)
pc.amount_with_fee = c->amount_with_fee;
pc.amount_without_fee = c->amount_without_fee;
pc.exchange_url = c->exchange_url;
- GNUNET_CRYPTO_eddsa_key_get_public(&c->coin_priv.eddsa_priv,
- &pc.coin_pub.eddsa_pub);
+ GNUNET_CRYPTO_eddsa_key_get_public (&c->coin_priv.eddsa_priv,
+ &pc.coin_pub.eddsa_pub);
/* JSON ------------------------------------------------------------ */
- json_t *je = GNUNET_JSON_PACK(TALER_JSON_pack_amount("contribution", &pc.amount_with_fee),
- GNUNET_JSON_pack_data_auto("coin_pub", &pc.coin_pub),
- GNUNET_JSON_pack_string("exchange_url", pc.exchange_url),
- GNUNET_JSON_pack_data_auto("h_denom", &h_denom_pub),
- TALER_JSON_pack_denom_sig("ub_sig", &pc.denom_sig),
- GNUNET_JSON_pack_data_auto("coin_sig", &pc.coin_sig));
- json_array_append_new(arr, je);
+ json_t *je = GNUNET_JSON_PACK (TALER_JSON_pack_amount ("contribution",
+ &pc.amount_with_fee),
+ GNUNET_JSON_pack_data_auto ("coin_pub",
+ &pc.coin_pub),
+ GNUNET_JSON_pack_string ("exchange_url",
+ pc.exchange_url),
+ GNUNET_JSON_pack_data_auto ("h_denom",
+ &h_denom_pub),
+ TALER_JSON_pack_denom_sig ("ub_sig",
+ &pc.denom_sig),
+ GNUNET_JSON_pack_data_auto ("coin_sig",
+ &pc.coin_sig));
+ json_array_append_new (arr, je);
/* optional totals if you need them later
(kept here because they existed in the legacy code) */
@@ -759,7 +785,8 @@ TALER_MERCHANT_order_pay_start (struct TALER_MERCHANT_OrderPayHandle *ph)
{
total_fee = fee;
total_amount = pc.amount_with_fee;
- } else
+ }
+ else
{
if ( (0 >
TALER_amount_add (&total_fee,
@@ -777,9 +804,9 @@ TALER_MERCHANT_order_pay_start (struct TALER_MERCHANT_OrderPayHandle *ph)
enum TALER_MERCHANT_OrderPayOptionErrorCode ec =
store_json_option (ph,
- TALER_MERCHANT_OrderPayOptionType_COINS,
- GNUNET_JSON_PACK (
- GNUNET_JSON_pack_array_steal ("coins", arr)
+ TALER_MERCHANT_OrderPayOptionType_COINS,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_array_steal ("coins", arr)
));
if (TALER_MERCHANT_OPOEC_OK != ec)
{
@@ -788,10 +815,12 @@ TALER_MERCHANT_order_pay_start (struct TALER_MERCHANT_OrderPayHandle *ph)
}
/* --- sign & pack input_tokens into used_tokens array in body --- */
- if (ph->input_tokens.num_tokens > 0) {
+ if (ph->input_tokens.num_tokens > 0)
+ {
struct TALER_MERCHANT_UsedToken ut[ph->input_tokens.num_tokens];
json_t *arr = json_array ();
- for (unsigned i = 0; i < ph->input_tokens.num_tokens; i++) {
+ for (unsigned i = 0; i < ph->input_tokens.num_tokens; i++)
+ {
const struct TALER_MERCHANT_UseToken *in = &ph->input_tokens.tokens[i];
struct TALER_MERCHANT_UsedToken *t = &ut[i];
@@ -813,7 +842,7 @@ TALER_MERCHANT_order_pay_start (struct TALER_MERCHANT_OrderPayHandle *ph)
GNUNET_JSON_pack_data_auto ("h_issue",
&t->issue_pub.public_key->pub_key_hash),
GNUNET_JSON_pack_data_auto ("token_pub", &t->token_pub)
- );
+ );
json_array_append_new (arr, je);
}
@@ -821,8 +850,8 @@ TALER_MERCHANT_order_pay_start (struct TALER_MERCHANT_OrderPayHandle *ph)
TALER_MERCHANT_OrderPayOptionType_INPUT_TOKENS,
GNUNET_JSON_PACK (
GNUNET_JSON_pack_array_steal ("tokens", arr)
- )
- );
+ )
+ );
}
diff --git a/src/util/contract_parse.c b/src/util/contract_parse.c
@@ -241,7 +241,6 @@ TALER_MERCHANT_parse_choice_output (
break;
case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN:
{
- output->details.token.count = 1;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_string ("token_family_slug",
&output->details.token.token_family_slug),