commit 45f620dc26c76ccd62f1985b1ed24eaf5fceb987
parent 2969d5cd6e26f3a49e72d14da50590d6ad44e05c
Author: Christian Grothoff <christian@grothoff.org>
Date: Mon, 20 Apr 2026 15:09:09 +0200
add max_pickup_duration/time support
Diffstat:
7 files changed, 137 insertions(+), 2 deletions(-)
diff --git a/src/backend/taler-merchant-httpd_exchanges.c b/src/backend/taler-merchant-httpd_exchanges.c
@@ -24,7 +24,6 @@
#include <taler/taler_dbevents.h>
#include "taler-merchant-httpd_exchanges.h"
#include "taler-merchant-httpd.h"
-#include <regex.h>
#include "merchant-database/get_kyc_limits.h"
#include "merchant-database/select_exchange_keys.h"
#include "merchant-database/event_listen.h"
diff --git a/src/backend/taler-merchant-httpd_post-templates-TEMPLATE_ID.c b/src/backend/taler-merchant-httpd_post-templates-TEMPLATE_ID.c
@@ -1631,6 +1631,19 @@ create_using_templates_inventory (struct UseContext *uc)
NULL == uc->parse_request.summary
? uc->template_contract.summary
: uc->parse_request.summary))));
+ if (! GNUNET_TIME_relative_is_forever (
+ uc->template_contract.max_pickup_duration))
+ {
+ GNUNET_assert (
+ 0 ==
+ json_object_set_new (
+ uc->ihc.request_body,
+ "max_pickup_time",
+ GNUNET_JSON_from_timestamp (
+ GNUNET_TIME_absolute_to_timestamp (
+ GNUNET_TIME_relative_to_absolute (
+ uc->template_contract.max_pickup_duration)))));
+ }
}
diff --git a/src/include/taler/taler_merchant_util.h b/src/include/taler/taler_merchant_util.h
@@ -368,6 +368,12 @@ struct TALER_MERCHANT_TemplateContract
*/
struct GNUNET_TIME_Relative pay_duration;
+ /**
+ * How long does the user have at most to access/pickup the (digital)
+ * goods or service they bought. Optional, defaults to FOREVER.
+ */
+ struct GNUNET_TIME_Relative max_pickup_duration;
+
union
{
@@ -1192,6 +1198,13 @@ struct TALER_MERCHANT_Contract
struct GNUNET_TIME_Timestamp delivery_date;
/**
+ * Latest time until which the good or service may be
+ * picked up by the customer. This is usually for digital
+ * goods where the customer has a finite window for downloading.
+ */
+ struct GNUNET_TIME_Timestamp max_pickup_time;
+
+ /**
* Merchant public key.
*/
struct TALER_MerchantPublicKeyP merchant_pub;
diff --git a/src/util/contract_parse.c b/src/util/contract_parse.c
@@ -1490,6 +1490,10 @@ TALER_MERCHANT_contract_parse (json_t *input,
GNUNET_JSON_spec_timestamp ("delivery_date",
&contract->delivery_date),
NULL),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_timestamp ("max_pickup_time",
+ &contract->max_pickup_time),
+ NULL),
(nonce_optional)
? GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_string_copy ("nonce",
@@ -1521,6 +1525,7 @@ TALER_MERCHANT_contract_parse (json_t *input,
unsigned int eline;
GNUNET_assert (NULL != input);
+ contract->max_pickup_time = GNUNET_TIME_UNIT_FOREVER_TS;
res = GNUNET_JSON_parse (input,
espec,
&ename,
diff --git a/src/util/contract_serialize.c b/src/util/contract_serialize.c
@@ -569,6 +569,12 @@ success:
GNUNET_JSON_pack_allow_null (
GNUNET_JSON_pack_timestamp ("delivery_date",
input->delivery_date)),
+ GNUNET_JSON_pack_allow_null (
+ GNUNET_TIME_absolute_is_never (input->max_pickup_time.abs_time)
+ ? GNUNET_JSON_pack_string ("dummy",
+ NULL)
+ : GNUNET_JSON_pack_timestamp ("max_pickup_time",
+ input->max_pickup_time)),
(nonce_optional)
? GNUNET_JSON_pack_allow_null (
GNUNET_JSON_pack_string ("nonce",
diff --git a/src/util/template_parse.c b/src/util/template_parse.c
@@ -268,6 +268,10 @@ TALER_MERCHANT_template_contract_parse (
&out->pay_duration),
NULL),
GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_relative_time ("max_pickup_duration",
+ &out->max_pickup_duration),
+ NULL),
+ GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_bool ("request_tip",
&out->request_tip),
NULL),
@@ -281,7 +285,7 @@ TALER_MERCHANT_template_contract_parse (
*error_name = "template_contract is NULL";
return GNUNET_SYSERR;
}
-
+ out->max_pickup_duration = GNUNET_TIME_UNIT_FOREVER_REL;
if (GNUNET_OK !=
GNUNET_JSON_parse ((json_t *) template_contract,
spec,
diff --git a/uncrustify.cfg b/uncrustify.cfg
@@ -0,0 +1,95 @@
+input_tab_size = 2
+output_tab_size = 2
+
+indent_columns = 2
+indent_with_tabs = 0
+indent_case_brace = 2
+indent_label=-16
+
+code_width=100
+#cmd_width=80
+
+# Leave most comments alone for now
+cmt_indent_multi=false
+sp_cmt_cpp_start=add
+
+sp_not=add
+
+sp_func_call_user_paren_paren=remove
+sp_inside_fparen=remove
+sp_after_cast=add
+
+ls_for_split_full=true
+ls_func_split_full=true
+ls_code_width=true
+
+# Arithmetic operations in wrapped expressions should be at the start
+# of the line.
+pos_arith=lead
+
+# Fully parenthesize boolean exprs
+mod_full_paren_if_bool=false
+
+# Braces should be on their own line
+nl_fdef_brace=add
+nl_enum_brace=add
+nl_struct_brace=add
+nl_union_brace=add
+nl_if_brace=add
+nl_brace_else=add
+nl_elseif_brace=add
+nl_while_brace=add
+nl_switch_brace=add
+
+# no newline between "else" and "if"
+nl_else_if=remove
+
+nl_func_paren=remove
+nl_assign_brace=remove
+
+# No extra newlines that cause noisy diffs
+nl_start_of_file=remove
+nl_after_func_proto = 2
+nl_after_func_body = 3
+# If there's no new line, it's not a text file!
+nl_end_of_file=add
+nl_max_blank_in_func = 3
+nl_max = 3
+
+sp_inside_paren = remove
+
+sp_arith = add
+sp_arith_additive = add
+
+# We want spaces before and after "="
+sp_before_assign = add
+sp_after_assign = add
+
+# we want "char *foo;"
+sp_after_ptr_star = remove
+sp_between_ptr_star = remove
+
+# we want "if (foo) { ... }"
+sp_before_sparen = add
+
+sp_inside_fparen = remove
+sp_inside_sparen = remove
+
+# add space before function call and decl: "foo (x)"
+sp_func_call_paren = add
+sp_func_proto_paren = add
+sp_func_proto_paren_empty = add
+sp_func_def_paren = add
+sp_func_def_paren_empty = add
+
+# We'd want it for "if ( (foo) || (bar) )", but not for "if (m())",
+# so as uncrustify doesn't give exactly what we want => ignore
+sp_paren_paren = ignore
+sp_inside_paren = remove
+sp_bool = force
+
+nl_func_type_name = force
+#nl_branch_else = add
+nl_else_brace = add
+nl_elseif_brace = add
+nl_for_brace = add