merchant

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

commit c2fdcad95404316a673c4fcd5d8ab0f1af7dffbc
parent 035e9c486adf382c0ce07f5702e9b69d0d987aae
Author: Christian Grothoff <christian@grothoff.org>
Date:   Tue, 28 Oct 2025 22:36:26 +0100

fix #9360 and also #9078.

Diffstat:
Mconfigure.ac | 6+++---
Msrc/backend/taler-merchant-httpd_private-get-instances-ID.c | 3+++
Msrc/backend/taler-merchant-httpd_private-patch-instances-ID.c | 13+++++++++----
Msrc/backend/taler-merchant-httpd_private-post-instances.c | 13+++++++++----
Msrc/backend/taler-merchant-httpd_private-post-orders.c | 214+++++++++++++++++++++++++------------------------------------------------------
Msrc/backenddb/Makefile.am | 1+
Asrc/backenddb/merchant-0025.sql | 40++++++++++++++++++++++++++++++++++++++++
Msrc/backenddb/pg_insert_instance.c | 22+++++++++++++---------
Msrc/backenddb/pg_lookup_instances.c | 17+++++++++++++++++
Msrc/backenddb/pg_update_instance.c | 6+++++-
Msrc/include/taler_merchant_service.h | 11+++++++++++
Msrc/include/taler_merchantdb_plugin.h | 6++++++
Msrc/lib/merchant_api_get_instance.c | 10++++++++++
Msrc/lib/merchant_api_patch_instance.c | 7++++++-
Msrc/lib/merchant_api_post_instances.c | 4++++
Msrc/testing/test_kyc_api.c | 6++++++
Msrc/testing/test_merchant_api.c | 26++++++++++++++++++++------
Msrc/testing/test_reconciliation.c | 3+++
Msrc/testing/testing_api_cmd_post_instances.c | 3++-
19 files changed, 236 insertions(+), 175 deletions(-)

diff --git a/configure.ac b/configure.ac @@ -216,11 +216,11 @@ AS_CASE([$with_gnunet], [LDFLAGS="-L$with_gnunet/lib/$MULTIARCH -L$with_gnunet/lib/ $LDFLAGS" CPPFLAGS="-I$with_gnunet/include $CPPFLAGS"]) AC_CHECK_HEADERS([gnunet/gnunet_util_lib.h], - [AC_CHECK_LIB([gnunetutil], [GNUNET_SCHEDULER_run], libgnunetutil=1)]) + [AC_CHECK_LIB([gnunetutil], [GNUNET_TIME_round_up], libgnunetutil=1)]) AS_IF([test $libgnunetutil != 1], [AC_MSG_ERROR([[ *** -*** You need libgnunetutil >= 0.21.0 to build this program. +*** You need libgnunetutil >= 0.25.3 to build this program. *** This library is part of GNUnet, available at *** https://gnunet.org *** ]])]) @@ -232,7 +232,7 @@ AC_CHECK_HEADERS([gnunet/gnunet_pq_lib.h], AS_IF([test $libgnunetpq != 1], [AC_MSG_ERROR([[ *** -*** You need libgnunetpq >= 0.21.2 (API v7) to build this program. +*** You need libgnunetpq >= 0.25.3 (API v7) to build this program. *** This library is part of GNUnet, available at *** https://gnunet.org *** ]])]) diff --git a/src/backend/taler-merchant-httpd_private-get-instances-ID.c b/src/backend/taler-merchant-httpd_private-get-instances-ID.c @@ -112,6 +112,9 @@ get_instances_ID (struct TMH_MerchantInstance *mi, mi->settings.default_pay_delay), GNUNET_JSON_pack_time_rel ("default_refund_delay", mi->settings.default_refund_delay), + GNUNET_JSON_pack_time_rounder_interval ( + "default_wire_transfer_rounding_interval", + mi->settings.default_wire_transfer_rounding_interval), GNUNET_JSON_pack_object_steal ("auth", auth)); } diff --git a/src/backend/taler-merchant-httpd_private-patch-instances-ID.c b/src/backend/taler-merchant-httpd_private-patch-instances-ID.c @@ -96,10 +96,6 @@ patch_instances_ID (struct TMH_MerchantInstance *mi, GNUNET_JSON_spec_bool ("use_stefan", &is.use_stefan), GNUNET_JSON_spec_mark_optional ( - GNUNET_JSON_spec_relative_time ("default_wire_transfer_delay", - &is.default_wire_transfer_delay), - &no_transfer_delay), - GNUNET_JSON_spec_mark_optional ( GNUNET_JSON_spec_relative_time ("default_pay_delay", &is.default_pay_delay), &no_pay_delay), @@ -107,6 +103,15 @@ patch_instances_ID (struct TMH_MerchantInstance *mi, GNUNET_JSON_spec_relative_time ("default_refund_delay", &is.default_refund_delay), &no_refund_delay), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_relative_time ("default_wire_transfer_delay", + &is.default_wire_transfer_delay), + &no_transfer_delay), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_time_rounder_interval ( + "default_wire_transfer_rounding_interval", + &is.default_wire_transfer_rounding_interval), + NULL), GNUNET_JSON_spec_end () }; enum GNUNET_DB_QueryStatus qs; diff --git a/src/backend/taler-merchant-httpd_private-post-instances.c b/src/backend/taler-merchant-httpd_private-post-instances.c @@ -97,10 +97,6 @@ post_instances (const struct TMH_RequestHandler *rh, GNUNET_JSON_spec_bool ("use_stefan", &is.use_stefan), GNUNET_JSON_spec_mark_optional ( - GNUNET_JSON_spec_relative_time ("default_wire_transfer_delay", - &is.default_wire_transfer_delay), - &no_transfer_delay), - GNUNET_JSON_spec_mark_optional ( GNUNET_JSON_spec_relative_time ("default_pay_delay", &is.default_pay_delay), &no_pay_delay), @@ -108,6 +104,15 @@ post_instances (const struct TMH_RequestHandler *rh, GNUNET_JSON_spec_relative_time ("default_refund_delay", &is.default_refund_delay), &no_refund_delay), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_relative_time ("default_wire_transfer_delay", + &is.default_wire_transfer_delay), + &no_transfer_delay), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_time_rounder_interval ( + "default_wire_transfer_rounding_interval", + &is.default_wire_transfer_rounding_interval), + NULL), GNUNET_JSON_spec_end () }; diff --git a/src/backend/taler-merchant-httpd_private-post-orders.c b/src/backend/taler-merchant-httpd_private-post-orders.c @@ -347,6 +347,11 @@ struct OrderContext struct GNUNET_TIME_Timestamp wire_deadline; /** + * Wire transfer round-up interval to apply. + */ + enum GNUNET_TIME_RounderInterval wire_deadline_rounder; + + /** * Delivery date. */ struct GNUNET_TIME_Timestamp delivery_date; @@ -1478,65 +1483,22 @@ phase_salt_forgettable (struct OrderContext *oc) * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ static enum GNUNET_GenericReturnValue -get_rounded_time_interval (struct GNUNET_TIME_Relative precision, - struct GNUNET_TIME_Timestamp ts, - struct GNUNET_TIME_Timestamp *start) +get_rounded_time_interval_down (struct GNUNET_TIME_Relative precision, + struct GNUNET_TIME_Timestamp ts, + struct GNUNET_TIME_Timestamp *start) { - struct tm timeinfo; - time_t seconds; + enum GNUNET_TIME_RounderInterval ri; - seconds = GNUNET_TIME_timestamp_to_s (ts); - GNUNET_break (NULL != - localtime_r (&seconds, - &timeinfo)); - - if (GNUNET_TIME_relative_cmp (GNUNET_TIME_UNIT_YEARS, - ==, - precision)) - { - timeinfo.tm_mon = 0; - timeinfo.tm_mday = 1; - timeinfo.tm_hour = 0; - timeinfo.tm_min = 0; - timeinfo.tm_sec = 0; - } - else if (GNUNET_TIME_relative_cmp (GNUNET_TIME_UNIT_MONTHS, - ==, - precision)) - { - timeinfo.tm_mday = 1; - timeinfo.tm_hour = 0; - timeinfo.tm_min = 0; - timeinfo.tm_sec = 0; - } - else if (GNUNET_TIME_relative_cmp (GNUNET_TIME_UNIT_DAYS, - ==, - precision)) - { - timeinfo.tm_hour = 0; - timeinfo.tm_min = 0; - timeinfo.tm_sec = 0; - } - else if (GNUNET_TIME_relative_cmp (GNUNET_TIME_UNIT_HOURS, - ==, - precision)) - { - timeinfo.tm_min = 0; - timeinfo.tm_sec = 0; - } - else if (GNUNET_TIME_relative_cmp (GNUNET_TIME_UNIT_MINUTES, - ==, - precision)) - { - timeinfo.tm_sec = 0; - } - else + ri = GNUNET_TIME_relative_to_round_interval (precision); + if ( (GNUNET_TIME_RI_NONE == ri) && + (! GNUNET_TIME_relative_is_zero (precision)) ) { + *start = ts; return GNUNET_SYSERR; } - seconds = mktime (&timeinfo); - GNUNET_break (seconds != (time_t) -1); - *start = GNUNET_TIME_timestamp_from_s (seconds); + *start = GNUNET_TIME_absolute_to_timestamp ( + GNUNET_TIME_round_down (ts.abs_time, + ri)); return GNUNET_OK; } @@ -1556,66 +1518,18 @@ get_rounded_time_interval_up (struct GNUNET_TIME_Relative precision, struct GNUNET_TIME_Timestamp ts, struct GNUNET_TIME_Timestamp *start) { - struct tm timeinfo; - time_t seconds; + enum GNUNET_TIME_RounderInterval ri; - seconds = GNUNET_TIME_timestamp_to_s (ts); - GNUNET_break (NULL != - localtime_r (&seconds, - &timeinfo)); - - if (GNUNET_TIME_relative_cmp (GNUNET_TIME_UNIT_YEARS, - ==, - precision)) - { - timeinfo.tm_year++; - timeinfo.tm_mon = 0; - timeinfo.tm_mday = 1; - timeinfo.tm_hour = 0; - timeinfo.tm_min = 0; - timeinfo.tm_sec = 0; - } - else if (GNUNET_TIME_relative_cmp (GNUNET_TIME_UNIT_MONTHS, - ==, - precision)) - { - timeinfo.tm_mon++; - timeinfo.tm_mday = 1; - timeinfo.tm_hour = 0; - timeinfo.tm_min = 0; - timeinfo.tm_sec = 0; - } - else if (GNUNET_TIME_relative_cmp (GNUNET_TIME_UNIT_DAYS, - ==, - precision)) - { - timeinfo.tm_mday++; - timeinfo.tm_hour = 0; - timeinfo.tm_min = 0; - timeinfo.tm_sec = 0; - } - else if (GNUNET_TIME_relative_cmp (GNUNET_TIME_UNIT_HOURS, - ==, - precision)) - { - timeinfo.tm_hour++; - timeinfo.tm_min = 0; - timeinfo.tm_sec = 0; - } - else if (GNUNET_TIME_relative_cmp (GNUNET_TIME_UNIT_MINUTES, - ==, - precision)) - { - timeinfo.tm_min++; - timeinfo.tm_sec = 0; - } - else + ri = GNUNET_TIME_relative_to_round_interval (precision); + if ( (GNUNET_TIME_RI_NONE == ri) && + (! GNUNET_TIME_relative_is_zero (precision)) ) { + *start = ts; return GNUNET_SYSERR; } - seconds = mktime (&timeinfo); - GNUNET_break (seconds != (time_t) -1); - *start = GNUNET_TIME_timestamp_from_s (seconds); + *start = GNUNET_TIME_absolute_to_timestamp ( + GNUNET_TIME_round_up (ts.abs_time, + ri)); return GNUNET_OK; } @@ -2010,7 +1924,7 @@ add_output_token_family (struct OrderContext *oc, struct GNUNET_TIME_Timestamp round_start; if (GNUNET_OK != - get_rounded_time_interval ( + get_rounded_time_interval_down ( key_details.token_family.validity_granularity, valid_at, &round_start)) @@ -2026,7 +1940,7 @@ add_output_token_family (struct OrderContext *oc, reply_with_error (oc, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE, - "get_rounded_time_interval failed"); + "get_rounded_time_interval_down failed"); return GNUNET_SYSERR; } if (GNUNET_TIME_relative_cmp ( @@ -2064,7 +1978,7 @@ add_output_token_family (struct OrderContext *oc, key_details.token_family.duration)), key_details.token_family.valid_before); GNUNET_assert (GNUNET_OK == - get_rounded_time_interval ( + get_rounded_time_interval_down ( key_details.token_family.validity_granularity, key.valid_before, &key_expires)); @@ -4015,6 +3929,29 @@ phase_parse_order (struct OrderContext *oc) } } + if ( (GNUNET_TIME_absolute_is_zero (oc->parse_order.pay_deadline.abs_time)) || + (GNUNET_TIME_absolute_is_never (oc->parse_order.pay_deadline.abs_time)) ) + { + oc->parse_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 (oc->parse_order.pay_deadline)); + } + else if (GNUNET_TIME_absolute_is_past (oc->parse_order.pay_deadline.abs_time)) + { + GNUNET_break_op (0); + reply_with_error ( + oc, + MHD_HTTP_BAD_REQUEST, + TALER_EC_MERCHANT_PRIVATE_POST_ORDERS_PAY_DEADLINE_IN_PAST, + NULL); + return; + } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Pay deadline is %s\n", + GNUNET_TIME_timestamp2s (oc->parse_order.pay_deadline)); + /* Check soundness of refund deadline, and that a timestamp * is actually present. */ { @@ -4038,8 +3975,10 @@ phase_parse_order (struct OrderContext *oc) } else { - oc->parse_order.refund_deadline = GNUNET_TIME_relative_to_timestamp ( - oc->parse_request.refund_delay); + oc->parse_order.refund_deadline + = GNUNET_TIME_absolute_to_timestamp ( + GNUNET_TIME_absolute_add (oc->parse_order.pay_deadline.abs_time, + oc->parse_request.refund_delay)); } } @@ -4058,28 +3997,6 @@ phase_parse_order (struct OrderContext *oc) } } - if ( (GNUNET_TIME_absolute_is_zero (oc->parse_order.pay_deadline.abs_time)) || - (GNUNET_TIME_absolute_is_never (oc->parse_order.pay_deadline.abs_time)) ) - { - oc->parse_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 (oc->parse_order.pay_deadline)); - } - else if (GNUNET_TIME_absolute_is_past (oc->parse_order.pay_deadline.abs_time)) - { - GNUNET_break_op (0); - reply_with_error ( - oc, - MHD_HTTP_BAD_REQUEST, - TALER_EC_MERCHANT_PRIVATE_POST_ORDERS_PAY_DEADLINE_IN_PAST, - NULL); - return; - } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Pay deadline is %s\n", - GNUNET_TIME_timestamp2s (oc->parse_order.pay_deadline)); if ( (! GNUNET_TIME_absolute_is_zero ( oc->parse_order.refund_deadline.abs_time)) && (GNUNET_TIME_absolute_is_past ( @@ -4096,15 +4013,20 @@ phase_parse_order (struct OrderContext *oc) if (GNUNET_TIME_absolute_is_never (oc->parse_order.wire_deadline.abs_time)) { - struct GNUNET_TIME_Timestamp t; - - t = GNUNET_TIME_relative_to_timestamp ( - GNUNET_TIME_relative_max (settings->default_wire_transfer_delay, - oc->parse_request.refund_delay)); - oc->parse_order.wire_deadline = GNUNET_TIME_timestamp_max ( - oc->parse_order.refund_deadline, - t); - if (GNUNET_TIME_absolute_is_never (oc->parse_order.wire_deadline.abs_time)) + struct GNUNET_TIME_Absolute start; + + start = GNUNET_TIME_absolute_max ( + oc->parse_order.refund_deadline.abs_time, + oc->parse_order.pay_deadline.abs_time); + oc->parse_order.wire_deadline + = GNUNET_TIME_absolute_to_timestamp ( + GNUNET_TIME_round_up ( + GNUNET_TIME_absolute_add ( + start, + settings->default_wire_transfer_delay), + settings->default_wire_transfer_rounding_interval)); + if (GNUNET_TIME_absolute_is_never ( + oc->parse_order.wire_deadline.abs_time)) { GNUNET_break_op (0); reply_with_error ( diff --git a/src/backenddb/Makefile.am b/src/backenddb/Makefile.am @@ -41,6 +41,7 @@ sql_DATA = \ merchant-0022.sql \ merchant-0023.sql \ merchant-0024.sql \ + merchant-0025.sql \ drop.sql BUILT_SOURCES = \ diff --git a/src/backenddb/merchant-0025.sql b/src/backenddb/merchant-0025.sql @@ -0,0 +1,40 @@ +-- +-- This file is part of TALER +-- Copyright (C) 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 merchant-0025.sql +-- @brief Expand settings to cover new default_wire_transfer_rounding_interval +-- @author Christian Grothoff + + +BEGIN; + +-- Check patch versioning is in place. +SELECT _v.register_patch('merchant-0025', NULL, NULL); + +SET search_path TO merchant; + + +-- See enum GNUNET_TIME_RounderInterval +CREATE TYPE time_rounder_interval + AS ENUM ('NONE', 'SECOND', 'MINUTE', 'HOUR', 'DAY', 'WEEK', 'MONTH', 'QUARTER', 'YEAR'); + +ALTER TABLE merchant_instances + ADD COLUMN default_wire_transfer_rounding_interval time_rounder_interval NOT NULL DEFAULT 'NONE'::time_rounder_interval; + +COMMENT ON COLUMN merchant_instances.default_wire_transfer_rounding_interval + IS 'To what round value do we round up wire transfer deadlines computed on the basis of the default_wire_transfer_delay.'; + +COMMIT; diff --git a/src/backenddb/pg_insert_instance.c b/src/backenddb/pg_insert_instance.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2022 Taler Systems SA + Copyright (C) 2022, 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 @@ -64,6 +64,9 @@ TMH_PG_insert_instance ( GNUNET_PQ_query_param_bool (is->phone_validated), GNUNET_PQ_query_param_bool (is->email_validated), GNUNET_PQ_query_param_bool (validation_needed), + GNUNET_PQ_query_param_string ( + GNUNET_TIME_round_interval2s ( + is->default_wire_transfer_rounding_interval)), GNUNET_PQ_query_param_end }; struct GNUNET_PQ_QueryParam params_priv[] = { @@ -94,15 +97,11 @@ TMH_PG_insert_instance ( ",phone_number" ",phone_validated" ",email_validated" - ",validation_needed)" + ",validation_needed" + ",default_wire_transfer_rounding_interval)" "VALUES" - "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18)") - ; - qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_instance", - params); - if (qs <= 0) - return qs; + "($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11," + "$12,$13,$14,$15,$16,$17,$18,$19::time_rounder_interval)"); PREPARE (pg, "insert_keys", "INSERT INTO merchant_keys" @@ -111,6 +110,11 @@ TMH_PG_insert_instance ( " SELECT $1, merchant_serial" " FROM merchant_instances" " WHERE merchant_id=$2"); + qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_instance", + params); + if (qs <= 0) + return qs; return GNUNET_PQ_eval_prepared_non_select (pg->conn, "insert_keys", params_priv); diff --git a/src/backenddb/pg_lookup_instances.c b/src/backenddb/pg_lookup_instances.c @@ -78,6 +78,7 @@ lookup_instances_cb (void *cls, bool no_auth; bool no_salt; bool no_priv; + char *dwtri; struct GNUNET_PQ_ResultSpec rs[] = { GNUNET_PQ_result_spec_uint64 ("merchant_serial", &instance_serial), @@ -132,6 +133,9 @@ lookup_instances_cb (void *cls, GNUNET_PQ_result_spec_string ("logo", &is.logo), NULL), + GNUNET_PQ_result_spec_string ( + "default_wire_transfer_rounding_interval", + &dwtri), GNUNET_PQ_result_spec_end }; @@ -150,6 +154,15 @@ lookup_instances_cb (void *cls, lic->qs = GNUNET_DB_STATUS_HARD_ERROR; return; } + if (GNUNET_OK != + GNUNET_TIME_string_to_round_interval ( + dwtri, + &is.default_wire_transfer_rounding_interval)) + { + GNUNET_break (0); + lic->qs = GNUNET_DB_STATUS_HARD_ERROR; + return; + } lic->cb (lic->cb_cls, &merchant_pub, (no_priv) ? NULL : &merchant_priv, @@ -199,6 +212,7 @@ TMH_PG_lookup_instances (void *cls, ",mi.phone_validated" ",mi.email_validated" ",mi.logo" + ",mi.default_wire_transfer_rounding_interval::TEXT" ",mk.merchant_priv" " FROM merchant_instances mi" " LEFT JOIN merchant_keys mk" @@ -224,6 +238,7 @@ TMH_PG_lookup_instances (void *cls, ",mi.phone_validated" ",mi.email_validated" ",mi.logo" + ",mi.default_wire_transfer_rounding_interval::TEXT" ",mk.merchant_priv" " FROM merchant_instances mi" " JOIN merchant_keys mk" @@ -283,6 +298,7 @@ TMH_PG_lookup_instance (void *cls, ",mi.phone_validated" ",mi.email_validated" ",mi.logo" + ",mi.default_wire_transfer_rounding_interval::TEXT" ",mk.merchant_priv" " FROM merchant_instances mi" " LEFT JOIN merchant_keys mk" @@ -309,6 +325,7 @@ TMH_PG_lookup_instance (void *cls, ",mi.phone_validated" ",mi.email_validated" ",mi.logo" + ",mi.default_wire_transfer_rounding_interval::TEXT" ",mk.merchant_priv" " FROM merchant_instances mi" " JOIN merchant_keys mk" diff --git a/src/backenddb/pg_update_instance.c b/src/backenddb/pg_update_instance.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2022 Taler Systems SA + Copyright (C) 2022, 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 @@ -58,6 +58,9 @@ TMH_PG_update_instance (void *cls, : GNUNET_PQ_query_param_string (is->phone), GNUNET_PQ_query_param_bool (is->phone_validated), GNUNET_PQ_query_param_bool (is->email_validated), + GNUNET_PQ_query_param_string ( + GNUNET_TIME_round_interval2s ( + is->default_wire_transfer_rounding_interval)), GNUNET_PQ_query_param_end }; @@ -78,6 +81,7 @@ TMH_PG_update_instance (void *cls, ",phone_number=$12" ",phone_validated=$13" ",email_validated=$14" + ",default_wire_transfer_rounding_interval=($15::time_rounder_interval)" " WHERE merchant_id=$1"); return GNUNET_PQ_eval_prepared_non_select (pg->conn, "update_instance", diff --git a/src/include/taler_merchant_service.h b/src/include/taler_merchant_service.h @@ -889,6 +889,17 @@ struct TALER_MERCHANT_InstanceDetails */ struct GNUNET_TIME_Relative default_pay_delay; + /** + * default refund period for offers merchant makes + */ + struct GNUNET_TIME_Relative default_refund_delay; + + /** + * Default interval by which we round up wire transfer deadlines + * computed using the @e default_wire_transfer_delay. + */ + enum GNUNET_TIME_RounderInterval default_wire_transfer_rounding_interval; + }; diff --git a/src/include/taler_merchantdb_plugin.h b/src/include/taler_merchantdb_plugin.h @@ -246,6 +246,12 @@ struct TALER_MERCHANTDB_InstanceSettings */ struct GNUNET_TIME_Relative default_refund_delay; + /** + * How much should we round up the wire transfer deadline computed by + * adding the @e default_wire_transfer_delay to the refund deadline. + */ + enum GNUNET_TIME_RounderInterval default_wire_transfer_rounding_interval; + }; diff --git a/src/lib/merchant_api_get_instance.c b/src/lib/merchant_api_get_instance.c @@ -117,6 +117,16 @@ handle_get_instance_finished (void *cls, GNUNET_JSON_spec_relative_time ( "default_pay_delay", &igr.details.ok.details.default_pay_delay), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_relative_time ( + "default_refund_delay", + &igr.details.ok.details.default_refund_delay), + NULL), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_time_rounder_interval ( + "default_wire_transfer_rounding_interval", + &igr.details.ok.details.default_wire_transfer_rounding_interval), + NULL), GNUNET_JSON_spec_end () }; diff --git a/src/lib/merchant_api_patch_instance.c b/src/lib/merchant_api_patch_instance.c @@ -185,7 +185,12 @@ TALER_MERCHANT_instance_patch ( GNUNET_JSON_pack_time_rel ("default_pay_delay", default_pay_delay), GNUNET_JSON_pack_time_rel ("default_refund_delay", - default_refund_delay)); + default_refund_delay), + /* FIXME: add eventually to arguments when we transform the API... */ + GNUNET_JSON_pack_time_rounder_interval ( + "default_wire_transfer_rounding_interval", + GNUNET_TIME_RI_NONE) + ); iph = GNUNET_new (struct TALER_MERCHANT_InstancePatchHandle); iph->ctx = ctx; iph->cb = cb; diff --git a/src/lib/merchant_api_post_instances.c b/src/lib/merchant_api_post_instances.c @@ -215,6 +215,10 @@ TALER_MERCHANT_instances_post ( default_pay_delay), GNUNET_JSON_pack_time_rel ("default_refund_delay", default_refund_delay), + /* FIXME: add eventually to arguments when we transform the API... */ + GNUNET_JSON_pack_time_rounder_interval ( + "default_wire_transfer_rounding_interval", + GNUNET_TIME_RI_NONE), GNUNET_JSON_pack_object_steal ("auth", auth_obj)); iph = GNUNET_new (struct TALER_MERCHANT_InstancesPostHandle); diff --git a/src/testing/test_kyc_api.c b/src/testing/test_kyc_api.c @@ -300,6 +300,9 @@ run (void *cls, "test-oauth2", "pass", MHD_HTTP_SEE_OTHER), + TALER_TESTING_cmd_sleep ( + "Wait for wire transfer deadline", + 3), CMD_EXEC_AGGREGATOR ("run-aggregator"), TALER_TESTING_cmd_check_bank_transfer ( "check_bank_transfer-498c", @@ -432,6 +435,9 @@ run (void *cls, MHD_HTTP_OK), TALER_TESTING_cmd_check_bank_empty ( "check_bank_empty-aml-1"), + TALER_TESTING_cmd_sleep ( + "Wait for wire transfer deadline", + 3), CMD_EXEC_AGGREGATOR ("run-aggregator-aml-frozen"), /* AML-frozen: hence nothing happened at the bank yet: */ TALER_TESTING_cmd_check_bank_empty ( diff --git a/src/testing/test_merchant_api.c b/src/testing/test_merchant_api.c @@ -484,6 +484,9 @@ run (void *cls, "EUR:4.99", "session-0"), TALER_TESTING_cmd_check_bank_empty ("check_bank_empty-1"), + TALER_TESTING_cmd_sleep ( + "Wait for wire transfer deadline", + 3), CMD_EXEC_AGGREGATOR ("run-aggregator"), TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-498c", EXCHANGE_URL, @@ -961,6 +964,9 @@ run (void *cls, "EUR:5", "EUR:4.99", NULL), + TALER_TESTING_cmd_sleep ( + "Wait for wire transfer deadline", + 3), CMD_EXEC_AGGREGATOR ("run-aggregator-unincreased-refund"), TALER_TESTING_cmd_check_bank_transfer ( "check_bank_transfer-paid-unincreased-refund", @@ -1160,6 +1166,9 @@ run (void *cls, "EUR:5", "EUR:4.99", NULL), + TALER_TESTING_cmd_sleep ( + "Wait for wire transfer deadline", + 3), CMD_EXEC_AGGREGATOR ("run-aggregator-10"), TALER_TESTING_cmd_check_bank_transfer ("check_bank_transfer-9.97-10", EXCHANGE_URL, @@ -1221,6 +1230,9 @@ run (void *cls, merchant_url, "pay-fail-partial-double-11-good", MHD_HTTP_OK), + TALER_TESTING_cmd_sleep ( + "Wait for wire transfer deadline", + 3), CMD_EXEC_AGGREGATOR ("run-aggregator-11"), TALER_TESTING_cmd_check_bank_empty ("check_bank_empty-11"), TALER_TESTING_cmd_end () @@ -2030,8 +2042,9 @@ run (void *cls, "street", "bobjuryst"), true, - GNUNET_TIME_UNIT_MINUTES, - GNUNET_TIME_UNIT_MINUTES, + GNUNET_TIME_UNIT_ZERO, /* wire transfer */ + GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, + 2), /* small pay delay */ MHD_HTTP_NO_CONTENT), TALER_TESTING_cmd_merchant_get_instance ( "instances-get-i1-2", @@ -2055,8 +2068,8 @@ run (void *cls, json_pack ("{s:s}", "city", "lawyercity"), true, - GNUNET_TIME_UNIT_MINUTES, - GNUNET_TIME_UNIT_MINUTES, + GNUNET_TIME_UNIT_ZERO, /* wire transfer */ + GNUNET_TIME_UNIT_SECONDS, /* pay delay */ // FIXME: change this back once // we have a update auth test CMD // RFC_8959_PREFIX "EXAMPLE", @@ -2074,8 +2087,9 @@ run (void *cls, "street", "bobjuryst"), true, - GNUNET_TIME_UNIT_MINUTES, - GNUNET_TIME_UNIT_MINUTES, + GNUNET_TIME_UNIT_ZERO, /* wire transfer */ + GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, + 2), /* small pay delay */ MHD_HTTP_NO_CONTENT), TALER_TESTING_cmd_merchant_post_instances ( "instance-create-i2", diff --git a/src/testing/test_reconciliation.c b/src/testing/test_reconciliation.c @@ -225,6 +225,9 @@ run (void *cls, false, MHD_HTTP_OK, NULL), + TALER_TESTING_cmd_sleep ( + "Wait for wire transfer deadline", + 3), TALER_TESTING_cmd_exec_aggregator ("run-aggregator", config_file), TALER_TESTING_cmd_exec_transfer ("run-transfer", diff --git a/src/testing/testing_api_cmd_post_instances.c b/src/testing/testing_api_cmd_post_instances.c @@ -303,7 +303,8 @@ TALER_TESTING_cmd_merchant_post_instances ( json_pack ("{s:s}", "city", "lawyercity"), true, GNUNET_TIME_UNIT_ZERO, /* no wire transfer delay */ - GNUNET_TIME_UNIT_MINUTES, + GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, + 2), /* small pay delay */ NULL, http_status); }