commit 22350d314c0437888ad76fa4cb7b8639807c59b3
parent bb1e888f8b6a520dd66ac1f5b6eaf4417cad161b
Author: Christian Grothoff <christian@grothoff.org>
Date: Mon, 25 May 2026 18:45:41 +0200
fix remaining FTBFS issues
Diffstat:
5 files changed, 334 insertions(+), 276 deletions(-)
diff --git a/src/backend/taler-merchant-httpd_post-private-orders.c b/src/backend/taler-merchant-httpd_post-private-orders.c
@@ -344,7 +344,7 @@ struct OrderContext
* from by selecting the respective index when signing the deposit
* confirmation.
*/
- struct TALER_MERCHANT_OrderChoice *choices;
+ struct TALER_MERCHANT_ContractChoice *choices;
/**
* Length of the @e choices array.
@@ -829,7 +829,7 @@ clean_order (void *cls)
}
for (unsigned int i = 0; i<oc->parse_choices.choices_len; i++)
{
- TALER_MERCHANT_order_choice_free (&oc->parse_choices.choices[i]);
+ TALER_MERCHANT_contract_choice_free (&oc->parse_choices.choices[i]);
}
GNUNET_array_grow (oc->parse_choices.choices,
oc->parse_choices.choices_len,
@@ -2074,7 +2074,7 @@ output_contract_choices (struct OrderContext *oc)
oc->set_max_fee.details.v1.max_fees[i];
GNUNET_assert (0 == json_array_append_new (
choices,
- TALER_MERCHANT_json_from_order_choice (
+ TALER_MERCHANT_json_from_contract_choice (
&oc->parse_choices.choices[i])));
}
return choices;
@@ -2177,19 +2177,21 @@ phase_serialize_order (struct OrderContext *oc)
{
json_t *xtra;
- switch (oc->parse_order.version)
+ switch (oc->parse_order.order->base->version)
{
case TALER_MERCHANT_CONTRACT_VERSION_0:
xtra = GNUNET_JSON_PACK (
TALER_JSON_pack_amount ("max_fee",
&oc->set_max_fee.details.v0.max_fee),
GNUNET_JSON_pack_allow_null (
- TALER_JSON_pack_amount ("tip",
- oc->parse_order.details.v0.no_tip
+ TALER_JSON_pack_amount (
+ "tip",
+ oc->parse_order.order->details.v0.no_tip
? NULL
- : &oc->parse_order.details.v0.tip)),
- TALER_JSON_pack_amount ("amount",
- &oc->parse_order.details.v0.brutto));
+ : &oc->parse_order.order->details.v0.tip)),
+ TALER_JSON_pack_amount (
+ "amount",
+ &oc->parse_order.order->details.v0.brutto));
break;
case TALER_MERCHANT_CONTRACT_VERSION_1:
{
@@ -2221,19 +2223,22 @@ phase_serialize_order (struct OrderContext *oc)
/* Pack does not work here, because it doesn't set zero-values for timestamps */
GNUNET_assert (0 ==
- json_object_set_new (oc->serialize_order.contract,
- "refund_deadline",
- GNUNET_JSON_from_timestamp (
- oc->parse_order.refund_deadline)));
+ json_object_set_new (
+ oc->serialize_order.contract,
+ "refund_deadline",
+ GNUNET_JSON_from_timestamp (
+ oc->parse_order.order->refund_deadline)));
/* auto_refund should only be set if it is not 0 */
- if (! GNUNET_TIME_relative_is_zero (oc->parse_order.auto_refund))
+ if (! GNUNET_TIME_relative_is_zero (
+ oc->parse_order.order->base->auto_refund))
{
/* Pack does not work here, because it sets zero-values for relative times */
GNUNET_assert (0 ==
- json_object_set_new (oc->serialize_order.contract,
- "auto_refund",
- GNUNET_JSON_from_time_rel (
- oc->parse_order.auto_refund)));
+ json_object_set_new (
+ oc->serialize_order.contract,
+ "auto_refund",
+ GNUNET_JSON_from_time_rel (
+ oc->parse_order.order->base->auto_refund)));
}
oc->phase++;
@@ -2294,12 +2299,12 @@ compute_fee (struct OrderContext *oc,
static void
phase_set_max_fee (struct OrderContext *oc)
{
- switch (oc->parse_order.version)
+ switch (oc->parse_order.order->base->version)
{
case TALER_MERCHANT_CONTRACT_VERSION_0:
compute_fee (oc,
- &oc->parse_order.details.v0.brutto,
- &oc->parse_order.details.v0.max_fee,
+ &oc->parse_order.order->details.v0.brutto,
+ &oc->parse_order.order->details.v0.max_fee,
&oc->set_exchanges.details.v0.max_stefan_fee,
&oc->set_max_fee.details.v0.max_fee);
break;
@@ -2347,11 +2352,11 @@ phase_select_wire_method (struct OrderContext *oc)
{
unsigned int num_choices = 0;
- switch (oc->parse_order.version)
+ switch (oc->parse_order.order->base->version)
{
case TALER_MERCHANT_CONTRACT_VERSION_0:
want_choices = 1;
- ea = &oc->parse_order.details.v0.brutto;
+ ea = &oc->parse_order.order->details.v0.brutto;
if (TALER_amount_is_zero (ea) ||
TALER_amount_set_test_above (&wmc->total_exchange_limits,
ea))
@@ -2536,11 +2541,11 @@ static void
update_stefan (struct OrderContext *oc,
const struct TALER_EXCHANGE_Keys *keys)
{
- switch (oc->parse_order.version)
+ switch (oc->parse_order.order->base->version)
{
case TALER_MERCHANT_CONTRACT_VERSION_0:
compute_stefan_fee (keys,
- &oc->parse_order.details.v0.brutto,
+ &oc->parse_order.order->details.v0.brutto,
&oc->set_exchanges.details.v0.max_stefan_fee);
break;
case TALER_MERCHANT_CONTRACT_VERSION_1:
@@ -3041,14 +3046,14 @@ static void
phase_add_payment_details (struct OrderContext *oc)
{
/* First, determine the maximum amounts that could be paid per currency */
- switch (oc->parse_order.version)
+ switch (oc->parse_order.order->base->version)
{
case TALER_MERCHANT_CONTRACT_VERSION_0:
GNUNET_array_append (oc->add_payment_details.max_choice_limits,
oc->add_payment_details.num_max_choice_limits,
- oc->parse_order.details.v0.brutto);
+ oc->parse_order.order->details.v0.brutto);
if (! TALER_amount_is_zero (
- &oc->parse_order.details.v0.brutto))
+ &oc->parse_order.order->details.v0.brutto))
{
oc->add_payment_details.need_exchange = true;
}
@@ -3167,25 +3172,26 @@ uint64_cmp (const void *a,
static void
phase_merge_inventory (struct OrderContext *oc)
{
- uint64_t pots[oc->parse_order.products_len + 1];
+ uint64_t pots[oc->parse_order.order->products_len + 1];
size_t pots_off = 0;
- if (0 != oc->parse_order.order_default_money_pot)
- pots[pots_off++] = oc->parse_order.order_default_money_pot;
+ if (0 != oc->parse_order.order->base->default_money_pot)
+ pots[pots_off++] = oc->parse_order.order->base->default_money_pot;
/**
* parse_request.inventory_products => instructions to add products to contract terms
* parse_order.products => contains products that are not from the backend-managed inventory.
*/
oc->merge_inventory.products = json_array ();
- for (size_t i = 0; i<oc->parse_order.products_len; i++)
+ for (size_t i = 0; i<oc->parse_order.order->products_len; i++)
{
GNUNET_assert (
0 ==
json_array_append_new (
oc->merge_inventory.products,
- TALER_MERCHANT_product_sold_serialize (&oc->parse_order.products[i])));
- if (0 != oc->parse_order.products[i].product_money_pot)
- pots[pots_off++] = oc->parse_order.products[i].product_money_pot;
+ TALER_MERCHANT_product_sold_serialize (
+ &oc->parse_order.order->products[i])));
+ if (0 != oc->parse_order.order->products[i].product_money_pot)
+ pots[pots_off++] = oc->parse_order.order->products[i].product_money_pot;
}
/* make sure pots array only has distinct elements */
@@ -3309,8 +3315,8 @@ phase_merge_inventory (struct OrderContext *oc)
return;
}
GNUNET_free (categories);
- oc->parse_order.minimum_age
- = GNUNET_MAX (oc->parse_order.minimum_age,
+ oc->parse_order.order->base->minimum_age
+ = GNUNET_MAX (oc->parse_order.order->base->minimum_age,
pd.minimum_age);
{
const char *eparam;
@@ -3361,7 +3367,7 @@ phase_merge_inventory (struct OrderContext *oc)
.prices_are_net = pd.price_is_net,
.image = pd.image,
.taxes = pd.taxes,
- .delivery_date = oc->parse_order.delivery_date,
+ .delivery_date = oc->parse_order.order->base->delivery_date,
.product_money_pot = pd.money_pot_id,
.unit = pd.unit,
@@ -3450,7 +3456,7 @@ add_donau_url (void *cls,
*/
static bool
add_donau_output (struct OrderContext *oc,
- struct TALER_MERCHANT_OrderOutput *output)
+ struct TALER_MERCHANT_ContractOutput *output)
{
enum GNUNET_DB_QueryStatus qs;
@@ -3488,9 +3494,7 @@ add_donau_output (struct OrderContext *oc,
static void
phase_parse_choices (struct OrderContext *oc)
{
- const json_t *jchoices;
-
- switch (oc->parse_order.version)
+ switch (oc->parse_order.order->base->version)
{
case TALER_MERCHANT_CONTRACT_VERSION_0:
oc->phase++;
@@ -3502,253 +3506,155 @@ phase_parse_choices (struct OrderContext *oc)
GNUNET_assert (0);
}
- jchoices = oc->parse_order.details.v1.choices;
-
- if (! json_is_array (jchoices))
- GNUNET_assert (0);
- if (0 == json_array_size (jchoices))
- {
- reply_with_error (oc,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PARAMETER_MALFORMED,
- "choices");
- return;
- }
+ /* Convert order choices to contract choices */
GNUNET_array_grow (oc->parse_choices.choices,
oc->parse_choices.choices_len,
- json_array_size (jchoices));
+ oc->parse_order.order->details.v1.choices_len);
for (unsigned int i = 0; i<oc->parse_choices.choices_len; i++)
{
- struct TALER_MERCHANT_OrderChoice *choice
+ const struct TALER_MERCHANT_OrderChoice *ochoice
+ = &oc->parse_order.order->details.v1.choices[i];
+ struct TALER_MERCHANT_ContractChoice *cchoice
= &oc->parse_choices.choices[i];
- const char *error_name;
- unsigned int error_line;
- const json_t *jinputs;
- const json_t *joutputs;
- bool no_fee;
- struct GNUNET_JSON_Specification spec[] = {
- TALER_JSON_spec_amount_any ("amount",
- &choice->amount),
- GNUNET_JSON_spec_mark_optional (
- TALER_JSON_spec_amount_any ("tip",
- &choice->tip),
- &choice->no_tip),
- GNUNET_JSON_spec_mark_optional (
- TALER_JSON_spec_amount_any ("max_fee",
- &choice->max_fee),
- &no_fee),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_string_copy ("description",
- &choice->description),
- NULL),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_object_copy ("description_i18n",
- &choice->description_i18n),
- NULL),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_array_const ("inputs",
- &jinputs),
- NULL),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_array_const ("outputs",
- &joutputs),
- NULL),
- GNUNET_JSON_spec_end ()
- };
- enum GNUNET_GenericReturnValue ret;
-
- ret = GNUNET_JSON_parse (json_array_get (jchoices,
- i),
- spec,
- &error_name,
- &error_line);
- if (GNUNET_OK != ret)
- {
- GNUNET_break_op (0);
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Choice parsing failed: %s:%u\n",
- error_name,
- error_line);
- reply_with_error (oc,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PARAMETER_MALFORMED,
- "choice");
- return;
- }
- if ( (! no_fee) &&
- (GNUNET_OK !=
- TALER_amount_cmp_currency (&choice->amount,
- &choice->max_fee)) )
- {
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (spec);
- reply_with_error (oc,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_CURRENCY_MISMATCH,
- "different currencies used for 'max_fee' and 'amount' currency");
- return;
- }
- if ( (! choice->no_tip) &&
- (GNUNET_OK !=
- TALER_amount_cmp_currency (&choice->amount,
- &choice->tip)) )
- {
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (spec);
- reply_with_error (oc,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_CURRENCY_MISMATCH,
- "tip and amount");
- return;
- }
+ unsigned int off;
if (! TMH_test_exchange_configured_for_currency (
- choice->amount.currency))
+ ochoice->amount.currency))
{
GNUNET_break_op (0);
- GNUNET_JSON_parse_free (spec);
reply_with_error (oc,
MHD_HTTP_CONFLICT,
TALER_EC_MERCHANT_PRIVATE_POST_ORDERS_NO_EXCHANGE_FOR_CURRENCY,
- choice->amount.currency);
+ ochoice->amount.currency);
return;
}
-
- if (NULL != jinputs)
+ cchoice->amount = ochoice->amount;
+ cchoice->tip = ochoice->tip;
+ cchoice->no_tip = ochoice->no_tip;
+ cchoice->description = GNUNET_strdup (ochoice->description);
+ cchoice->description_i18n = json_incref (ochoice->description_i18n);
+ cchoice->max_fee = ochoice->max_fee;
+
+ /* convert inputs */
+ GNUNET_array_grow (cchoice->inputs,
+ cchoice->inputs_len,
+ ochoice->inputs_len);
+ off = 0;
+ for (unsigned int j = 0; j < ochoice->inputs_len; j++)
{
- const json_t *jinput;
- size_t idx;
- json_array_foreach ((json_t *) jinputs, idx, jinput)
- {
- struct TALER_MERCHANT_OrderInput input = {
- .details.token.count = 1
- };
+ const struct TALER_MERCHANT_OrderInput *order_input
+ = &ochoice->inputs[j];
+ struct TALER_MERCHANT_ContractInput *contract_input
+ = &cchoice->inputs[off];
+ contract_input->type = order_input->type;
+ switch (order_input->type)
+ {
+ case TALER_MERCHANT_CONTRACT_INPUT_TYPE_INVALID:
+ GNUNET_assert (0);
+ break;
+ case TALER_MERCHANT_CONTRACT_INPUT_TYPE_TOKEN:
+ /* Ignore inputs tokens with 'count' field set to 0 */
+ if (0 == order_input->details.token.count)
+ continue;
+ contract_input->details.token.count
+ = order_input->details.token.count;
+ contract_input->details.token.token_family_slug
+ = order_input->details.token.token_family_slug;
if (GNUNET_OK !=
- TALER_MERCHANT_parse_order_choice_input (
- (json_t *) jinput,
- &input,
- idx))
+ add_input_token_family (oc,
+ contract_input->details.token.token_family_slug))
{
GNUNET_break_op (0);
reply_with_error (oc,
MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PARAMETER_MALFORMED,
- "input");
+ TALER_EC_MERCHANT_PRIVATE_POST_ORDERS_TOKEN_FAMILY_SLUG_UNKNOWN,
+ contract_input->details.token.token_family_slug);
return;
}
+ off++;
+ continue;
+ } /* switch input type */
+ GNUNET_assert (0);
+ } /* for all inputs */
+ GNUNET_array_grow (cchoice->inputs,
+ cchoice->inputs_len,
+ off);
+
+ /* convert outputs */
+ GNUNET_array_grow (cchoice->outputs,
+ cchoice->outputs_len,
+ ochoice->outputs_len);
+ off = 0;
+ for (unsigned int j = 0; j < ochoice->outputs_len; j++)
+ {
+ const struct TALER_MERCHANT_OrderOutput *order_output
+ = &ochoice->outputs[j];
+ struct TALER_MERCHANT_ContractOutput *contract_output
+ = &cchoice->outputs[off];
- switch (input.type)
+ switch (order_output->type)
+ {
+ case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_INVALID:
+ GNUNET_assert (0);
+ break;
+ case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT:
+ if (! order_output->details.donation_receipt.no_amount)
{
- case TALER_MERCHANT_CONTRACT_INPUT_TYPE_INVALID:
- GNUNET_assert (0);
- break;
- case TALER_MERCHANT_CONTRACT_INPUT_TYPE_TOKEN:
- /* Ignore inputs tokens with 'count' field set to 0 */
- if (0 == input.details.token.count)
- continue;
-
- if (GNUNET_OK !=
- add_input_token_family (oc,
- input.details.token.token_family_slug))
-
- {
- GNUNET_break_op (0);
- reply_with_error (oc,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_MERCHANT_PRIVATE_POST_ORDERS_TOKEN_FAMILY_SLUG_UNKNOWN,
- input.details.token.token_family_slug);
- return;
- }
-
- GNUNET_array_append (choice->inputs,
- choice->inputs_len,
- input);
- continue;
+ contract_output->details.donation_receipt.amount
+ = ochoice->amount;
}
- GNUNET_assert (0);
- }
- }
-
- if (NULL != joutputs)
- {
- const json_t *joutput;
- size_t idx;
- json_array_foreach ((json_t *) joutputs, idx, joutput)
- {
- struct TALER_MERCHANT_OrderOutput output = {
- .details.token.count = 1
- };
-
- if (GNUNET_OK !=
- TALER_MERCHANT_parse_order_choice_output (
- (json_t *) joutput,
- &output,
- idx))
+ else
{
- reply_with_error (oc,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PARAMETER_MALFORMED,
- "output");
+ contract_output->details.donation_receipt.amount
+ = order_output->details.donation_receipt.amount;
+ }
+ if (! add_donau_output (oc,
+ contract_output))
+ {
+ GNUNET_break (0);
return;
}
+ off++;
+ continue;
+ case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN:
+ /* Ignore inputs tokens with 'count' field set to 0 */
+ if (0 == order_output->details.token.count)
+ continue;
+
+ contract_output->details.token.token_family_slug
+ = order_output->details.token.token_family_slug;
+ contract_output->details.token.count
+ = order_output->details.token.count;
+ if (0 == order_output->details.token.valid_at.abs_time.abs_value_us)
+ contract_output->details.token.valid_at
+ = GNUNET_TIME_timestamp_get ();
+ else
+ contract_output->details.token.valid_at
+ = order_output->details.token.valid_at;
+ if (GNUNET_OK !=
+ add_output_token_family (
+ oc,
+ contract_output->details.token.token_family_slug,
+ contract_output->details.token.valid_at,
+ &contract_output->details.token.key_index))
- switch (output.type)
{
- case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_INVALID:
- GNUNET_assert (0);
- break;
- case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT:
- output.details.donation_receipt.amount = choice->amount;
- // FIXME: This is also already a transformation,
- // not reflected in the "Order" type!
- if (! add_donau_output (oc,
- &output))
- {
- GNUNET_break (0);
- return;
- }
- GNUNET_array_append (choice->outputs,
- choice->outputs_len,
- output);
- continue;
- case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN:
- /* Ignore inputs tokens with 'count' field set to 0 */
- if (0 == output.details.token.count)
- continue;
-
- if (0 == output.details.token.valid_at.abs_time.abs_value_us)
- output.details.token.valid_at
- = GNUNET_TIME_timestamp_get ();
- // FIXME: This is another transformation,
- // not reflected in the "Order" type!
- // => need yet another type for the data that is
- // actually POSTed to this endpoint!
- // (Note: the 'metadata' is another one that
- // is currently *wrong*!)
- if (GNUNET_OK !=
- add_output_token_family (oc,
- output.details.token.token_family_slug,
- output.details.token.valid_at,
- &output.details.token.key_index))
-
- {
- /* note: reply_with_error() was already called */
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Could not handle output token family `%s'\n",
- output.details.token.token_family_slug);
- return;
- }
-
- GNUNET_array_append (choice->outputs,
- choice->outputs_len,
- output);
- continue;
+ /* note: reply_with_error() was already called */
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Could not handle output token family `%s'\n",
+ contract_output->details.token.token_family_slug);
+ return;
}
- GNUNET_assert (0);
- }
- }
- }
+ off++;
+ continue;
+ } /* end switch */
+ GNUNET_assert (0);
+ } /* for outputs */
+ GNUNET_array_grow (cchoice->outputs,
+ cchoice->outputs_len,
+ off);
+ } /* for all choices */
oc->phase++;
}
@@ -3767,7 +3673,6 @@ phase_parse_order (struct OrderContext *oc)
{
const struct TALER_MERCHANTDB_InstanceSettings *settings =
&oc->hc->instance->settings;
- enum GNUNET_GenericReturnValue ret;
bool computed_refund_deadline = false;
oc->parse_order.order
@@ -3790,7 +3695,6 @@ phase_parse_order (struct OrderContext *oc)
oc->parse_order.order->details.v0.brutto.currency))
{
GNUNET_break_op (0);
- GNUNET_JSON_parse_free (spec);
reply_with_error (
oc,
MHD_HTTP_CONFLICT,
@@ -3803,7 +3707,6 @@ phase_parse_order (struct OrderContext *oc)
break;
default:
GNUNET_break_op (0);
- GNUNET_JSON_parse_free (spec);
reply_with_error (oc,
MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_VERSION_MALFORMED,
@@ -3825,7 +3728,6 @@ phase_parse_order (struct OrderContext *oc)
tm_info = localtime (&timer);
if (NULL == tm_info)
{
- GNUNET_JSON_parse_free (spec);
reply_with_error (
oc,
MHD_HTTP_INTERNAL_SERVER_ERROR,
@@ -3860,7 +3762,7 @@ phase_parse_order (struct OrderContext *oc)
{
const char *pos;
- pos = strstr (oc->parse_order.odrer->base->fulfillment_url,
+ pos = strstr (oc->parse_order.order->base->fulfillment_url,
"${ORDER_ID}");
if (NULL != pos)
{
@@ -3899,8 +3801,9 @@ phase_parse_order (struct OrderContext *oc)
(GNUNET_TIME_absolute_is_never (
oc->parse_order.order->pay_deadline.abs_time)) )
{
- oc->parse_order.pay_deadline = GNUNET_TIME_relative_to_timestamp (
- settings->default_pay_delay);
+ oc->parse_order.order->pay_deadline
+ = GNUNET_TIME_relative_to_timestamp (
+ settings->default_pay_delay);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Pay deadline was zero (or never), setting to %s\n",
GNUNET_TIME_timestamp2s (
@@ -3986,14 +3889,14 @@ phase_parse_order (struct OrderContext *oc)
}
if (GNUNET_TIME_absolute_is_never (
- oc->parse_order.order->wire_deadline.abs_time))
+ oc->parse_order.order->wire_transfer_deadline.abs_time))
{
struct GNUNET_TIME_Absolute start;
start = GNUNET_TIME_absolute_max (
oc->parse_order.order->refund_deadline.abs_time,
oc->parse_order.order->pay_deadline.abs_time);
- oc->parse_order.order->wire_deadline
+ oc->parse_order.order->wire_transfer_deadline
= GNUNET_TIME_absolute_to_timestamp (
GNUNET_TIME_round_up (
GNUNET_TIME_absolute_add (
@@ -4001,7 +3904,7 @@ phase_parse_order (struct OrderContext *oc)
settings->default_wire_transfer_delay),
settings->default_wire_transfer_rounding_interval));
if (GNUNET_TIME_absolute_is_never (
- oc->parse_order.order->wire_deadline.abs_time))
+ oc->parse_order.order->wire_transfer_deadline.abs_time))
{
GNUNET_break_op (0);
reply_with_error (
@@ -4018,12 +3921,14 @@ phase_parse_order (struct OrderContext *oc)
and did have a configured wire_deadline, make sure that
the refund_deadline is at or below the wire_deadline. */
oc->parse_order.order->refund_deadline
- = GNUNET_TIME_timestamp_min (oc->parse_order.order->refund_deadline,
- oc->parse_order.order->wire_deadline);
+ = GNUNET_TIME_timestamp_min (
+ oc->parse_order.order->refund_deadline,
+ oc->parse_order.order->wire_transfer_deadline);
}
- if (GNUNET_TIME_timestamp_cmp (oc->parse_order.order->wire_deadline,
- <,
- oc->parse_order.order->refund_deadline))
+ if (GNUNET_TIME_timestamp_cmp (
+ oc->parse_order.order->wire_transfer_deadline,
+ <,
+ oc->parse_order.order->refund_deadline))
{
GNUNET_break_op (0);
reply_with_error (
diff --git a/src/include/taler/taler_merchant_util.h b/src/include/taler/taler_merchant_util.h
@@ -472,7 +472,7 @@ struct TALER_MERCHANT_ContractOutput
struct
{
/**
- * Amount of the donation. (optional)
+ * Amount of the donation.
*/
struct TALER_Amount amount;
diff --git a/src/util/contract_choice_serialize.c b/src/util/contract_choice_serialize.c
@@ -109,9 +109,8 @@ json_from_contract_output (
"tax-receipt"),
GNUNET_JSON_pack_array_steal ("donau_urls",
donau_urls),
- GNUNET_JSON_pack_allow_null (
- TALER_JSON_pack_amount ("amount",
- &output->details.donation_receipt.amount)));
+ TALER_JSON_pack_amount ("amount",
+ &output->details.donation_receipt.amount));
}
}
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
diff --git a/src/util/meson.build b/src/util/meson.build
@@ -26,6 +26,7 @@ libtalermerchantutil_SOURCES = [
'merchant_parse.c',
'mfa.c',
'order_choice_parse.c',
+ 'order_choice_serialize.c',
'order_parse.c',
'os_installation.c',
'product_parse.c',
diff --git a/src/util/order_choice_serialize.c b/src/util/order_choice_serialize.c
@@ -0,0 +1,153 @@
+/*
+ This file is part of GNU Taler
+ Copyright (C) 2024, 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 src/util/order_choice_serialize.c
+ * @brief shared logic for order choice serialization
+ * @author Iván Ávalos
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <gnunet/gnunet_json_lib.h>
+#include <gnunet/gnunet_common.h>
+#include <taler/taler_json_lib.h>
+#include <jansson.h>
+#include "taler/taler_util.h"
+#include "taler/taler_merchant_util.h"
+
+/**
+ * Get JSON representation of order choice input.
+ *
+ * @param[in] input order terms choice input
+ * @return JSON representation of @a input; NULL on error
+ */
+static json_t *
+json_from_order_input (
+ const struct TALER_MERCHANT_OrderInput *input)
+{
+ switch (input->type)
+ {
+ case TALER_MERCHANT_CONTRACT_INPUT_TYPE_INVALID:
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "invalid order input type");
+ GNUNET_assert (0);
+ return NULL;
+ case TALER_MERCHANT_CONTRACT_INPUT_TYPE_TOKEN:
+ return GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("type",
+ "token"),
+ GNUNET_JSON_pack_string ("token_family_slug",
+ input->details.token.token_family_slug),
+ GNUNET_JSON_pack_int64 ("count",
+ input->details.token.count));
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "unsupported order input type %d",
+ input->type);
+ GNUNET_assert (0);
+ return NULL;
+}
+
+
+/**
+ * Get JSON representation of order choice output.
+ *
+ * @param[in] output order terms choice output
+ * @return JSON representation of @a output; NULL on error
+ */
+static json_t *
+json_from_order_output (
+ const struct TALER_MERCHANT_OrderOutput *output)
+{
+ switch (output->type)
+ {
+ case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_INVALID:
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "invalid order output type");
+ GNUNET_assert (0);
+ return NULL;
+ case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN:
+ return GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("type",
+ "token"),
+ GNUNET_JSON_pack_string ("token_family_slug",
+ output->details.token.token_family_slug),
+ GNUNET_JSON_pack_uint64 ("count",
+ output->details.token.count));
+ case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT:
+ return GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("type",
+ "tax-receipt"),
+ GNUNET_JSON_pack_allow_null (
+ TALER_JSON_pack_amount ("amount",
+ output->details.donation_receipt.no_amount
+ ? NULL
+ : &output->details.donation_receipt.amount)));
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unsupported order output type %d",
+ output->type);
+ GNUNET_assert (0);
+ return NULL;
+}
+
+
+json_t *
+TALER_MERCHANT_json_from_order_choice (
+ const struct TALER_MERCHANT_OrderChoice *choice)
+{
+ json_t *inputs;
+ json_t *outputs;
+
+ inputs = json_array ();
+ GNUNET_assert (NULL != inputs);
+ for (unsigned int i = 0; i < choice->inputs_len; i++)
+ GNUNET_assert (0 ==
+ json_array_append_new (inputs,
+ json_from_order_input (
+ &choice->inputs[i])));
+ outputs = json_array ();
+ GNUNET_assert (NULL != outputs);
+ for (unsigned int i = 0; i < choice->outputs_len; i++)
+ GNUNET_assert (0 ==
+ json_array_append_new (outputs,
+ json_from_order_output (
+ &choice->outputs[i])));
+
+ return GNUNET_JSON_PACK (
+ TALER_JSON_pack_amount ("amount",
+ &choice->amount),
+ GNUNET_JSON_pack_allow_null (
+ TALER_JSON_pack_amount ("tip",
+ choice->no_tip
+ ? NULL
+ : &choice->tip)),
+ GNUNET_JSON_pack_allow_null (
+ GNUNET_JSON_pack_string ("description",
+ choice->description)),
+ GNUNET_JSON_pack_allow_null (
+ GNUNET_JSON_pack_object_incref ("description_i18n",
+ choice->description_i18n)),
+ GNUNET_JSON_pack_allow_null (
+ TALER_JSON_pack_amount ("max_fee",
+ choice->no_max_fee
+ ? NULL
+ : &choice->max_fee)),
+ GNUNET_JSON_pack_array_steal ("inputs",
+ inputs),
+ GNUNET_JSON_pack_array_steal ("outputs",
+ outputs));
+}