merchant

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

commit a5342fa86c1b769e5196db9944947364a4c6aa01
parent 08026a7069b870471221d62993104044e573c1f2
Author: Christian Grothoff <grothoff@gnunet.org>
Date:   Thu, 23 Oct 2025 10:57:20 +0200

implement backend support for #9148

Diffstat:
Msrc/backend/taler-merchant-httpd.c | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/backend/taler-merchant-httpd.h | 15+++++++++++++++
Msrc/backend/taler-merchant-httpd_private-get-instances-ID.c | 2++
Msrc/backend/taler-merchant-httpd_private-patch-instances-ID.c | 8++++++++
Msrc/backend/taler-merchant-httpd_private-post-instances.c | 12+++++++++++-
Msrc/backenddb/Makefile.am | 1+
Asrc/backenddb/merchant-0024.sql | 35+++++++++++++++++++++++++++++++++++
Msrc/backenddb/pg_insert_instance.c | 4+++-
Msrc/backenddb/pg_lookup_instances.c | 6++++++
Msrc/backenddb/pg_update_instance.c | 15+++++++++------
Msrc/backenddb/test_merchantdb.c | 3++-
Msrc/include/taler_merchant_service.h | 4++++
Msrc/include/taler_merchantdb_plugin.h | 6++++++
Msrc/lib/Makefile.am | 2+-
Msrc/lib/merchant_api_patch_instance.c | 5++++-
Msrc/lib/merchant_api_post_instances.c | 3+++
Msrc/testing/testing_api_cmd_patch_instance.c | 2++
Msrc/testing/testing_api_cmd_post_instances.c | 2++
18 files changed, 173 insertions(+), 11 deletions(-)

diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c @@ -143,6 +143,12 @@ struct TALER_MERCHANTDB_Plugin *TMH_db; struct GNUNET_CONTAINER_MultiHashMap *TMH_by_id_map; +struct GNUNET_TIME_Relative TMH_default_wire_transfer_delay; + +struct GNUNET_TIME_Relative TMH_default_pay_delay; + +struct GNUNET_TIME_Relative TMH_default_refund_delay; + int TMH_strict_v19; int TMH_auth_disabled; @@ -2850,6 +2856,59 @@ run (void *cls, } if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_time (cfg, + "merchant", + "LEGAL_PRESERVATION", + &TMH_legal_expiration)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "merchant", + "LEGAL_PRESERVATION"); + global_ret = EXIT_NOTCONFIGURED; + GNUNET_SCHEDULER_shutdown (); + return; + } + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_time (cfg, + "merchant", + "DEFAULT_WIRE_TRANSFER_DELAY", + &TMH_default_wire_transfer_delay)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_INFO, + "merchant", + "DEFAULT_WIRE_TRANSFER_DELAY"); + TMH_default_wire_transfer_delay = GNUNET_TIME_UNIT_MONTHS; + } + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_time (cfg, + "merchant", + "DEFAULT_PAY_DELAY", + &TMH_default_pay_delay)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_INFO, + "merchant", + "DEFAULT_PAY_DELAY"); + TMH_default_pay_delay = GNUNET_TIME_UNIT_DAYS; + } + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_time (cfg, + "merchant", + "DEFAULT_REFUND_DELAY", + &TMH_default_refund_delay)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_INFO, + "merchant", + "DEFAULT_REFUND_DELAY"); + TMH_default_refund_delay = GNUNET_TIME_relative_multiply ( + GNUNET_TIME_UNIT_DAYS, + 15); + } + + + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "merchant", "PAYMENT_TARGET_TYPES", diff --git a/src/backend/taler-merchant-httpd.h b/src/backend/taler-merchant-httpd.h @@ -792,6 +792,21 @@ extern struct GNUNET_CONTAINER_MultiHashMap *TMH_by_id_map; extern struct GNUNET_TIME_Relative TMH_legal_expiration; /** + * Default wire delay for new instances. + */ +extern struct GNUNET_TIME_Relative TMH_default_wire_transfer_delay; + +/** + * Default payment delay for new instances. + */ +extern struct GNUNET_TIME_Relative TMH_default_pay_delay; + +/** + * Default refund delay for new instances. + */ +extern struct GNUNET_TIME_Relative TMH_default_refund_delay; + +/** * #GNUNET_YES if protocol version 19 is strictly enforced. * (Default is #GNUNET_NO) */ diff --git a/src/backend/taler-merchant-httpd_private-get-instances-ID.c b/src/backend/taler-merchant-httpd_private-get-instances-ID.c @@ -110,6 +110,8 @@ get_instances_ID (struct TMH_MerchantInstance *mi, mi->settings.default_wire_transfer_delay), GNUNET_JSON_pack_time_rel ("default_pay_delay", mi->settings.default_pay_delay), + GNUNET_JSON_pack_time_rel ("default_refund_delay", + mi->settings.default_refund_delay), 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 @@ -67,6 +67,7 @@ patch_instances_ID (struct TMH_MerchantInstance *mi, const char *name; struct TMH_WireMethod *wm_head = NULL; struct TMH_WireMethod *wm_tail = NULL; + bool no_refund_delay; struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_string ("name", &name), @@ -96,6 +97,10 @@ patch_instances_ID (struct TMH_MerchantInstance *mi, &is.default_wire_transfer_delay), GNUNET_JSON_spec_relative_time ("default_pay_delay", &is.default_pay_delay), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_relative_time ("default_refund_delay", + &is.default_refund_delay), + &no_refund_delay), GNUNET_JSON_spec_end () }; enum GNUNET_DB_QueryStatus qs; @@ -145,6 +150,9 @@ patch_instances_ID (struct TMH_MerchantInstance *mi, "jurisdiction"); } + if (no_refund_delay) + is.default_refund_delay = mi->settings.default_refund_delay; + if ( (NULL != is.phone) && (NULL != mi->settings.phone) && 0 == strcmp (mi->settings.phone, diff --git a/src/backend/taler-merchant-httpd_private-post-instances.c b/src/backend/taler-merchant-httpd_private-post-instances.c @@ -64,6 +64,7 @@ post_instances (const struct TMH_RequestHandler *rh, struct TMH_WireMethod *wm_head = NULL; struct TMH_WireMethod *wm_tail = NULL; const json_t *jauth; + bool no_refund_delay; struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_string ("id", (const char **) &is.id), @@ -97,6 +98,10 @@ post_instances (const struct TMH_RequestHandler *rh, &is.default_wire_transfer_delay), GNUNET_JSON_spec_relative_time ("default_pay_delay", &is.default_pay_delay), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_relative_time ("default_refund_delay", + &is.default_refund_delay), + &no_refund_delay), GNUNET_JSON_spec_end () }; @@ -111,6 +116,8 @@ post_instances (const struct TMH_RequestHandler *rh, ? MHD_YES : MHD_NO; } + if (no_refund_delay) + is.default_refund_delay = TMH_default_refund_delay; { enum GNUNET_GenericReturnValue ret; @@ -234,7 +241,10 @@ post_instances (const struct TMH_RequestHandler *rh, is.default_wire_transfer_delay)) && (GNUNET_TIME_relative_cmp (mi->settings.default_pay_delay, ==, - is.default_pay_delay)) ) + is.default_pay_delay)) && + (GNUNET_TIME_relative_cmp (mi->settings.default_refund_delay, + ==, + is.default_refund_delay)) ) { GNUNET_JSON_parse_free (spec); return TALER_MHD_reply_static (connection, diff --git a/src/backenddb/Makefile.am b/src/backenddb/Makefile.am @@ -40,6 +40,7 @@ sql_DATA = \ merchant-0021.sql \ merchant-0022.sql \ merchant-0023.sql \ + merchant-0024.sql \ drop.sql BUILT_SOURCES = \ diff --git a/src/backenddb/merchant-0024.sql b/src/backenddb/merchant-0024.sql @@ -0,0 +1,35 @@ +-- +-- 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-0024.sql +-- @brief Create table to store MFA related information +-- @author Christian Grothoff + + +BEGIN; + +-- Check patch versioning is in place. +SELECT _v.register_patch('merchant-0024', NULL, NULL); + +SET search_path TO merchant; + +ALTER TABLE merchant_instances + ADD COLUMN default_refund_delay INT8 NOT NULL DEFAULT 1296000000; -- 15 days + +COMMENT ON COLUMN merchant_instances.default_refund_delay + IS 'How long are refunds possible for orders by default for this instance'; + +COMMIT; diff --git a/src/backenddb/pg_insert_instance.c b/src/backenddb/pg_insert_instance.c @@ -48,6 +48,7 @@ TMH_PG_insert_instance ( GNUNET_PQ_query_param_relative_time ( &is->default_wire_transfer_delay), GNUNET_PQ_query_param_relative_time (&is->default_pay_delay), + GNUNET_PQ_query_param_relative_time (&is->default_refund_delay), (NULL == is->website) ? GNUNET_PQ_query_param_null () : GNUNET_PQ_query_param_string (is->website), @@ -86,6 +87,7 @@ TMH_PG_insert_instance ( ",use_stefan" ",default_wire_transfer_delay" ",default_pay_delay" + ",default_refund_delay" ",website" ",email" ",logo" @@ -94,7 +96,7 @@ TMH_PG_insert_instance ( ",email_validated" ",validation_needed)" "VALUES" - "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)") + "($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", diff --git a/src/backenddb/pg_lookup_instances.c b/src/backenddb/pg_lookup_instances.c @@ -114,6 +114,8 @@ lookup_instances_cb (void *cls, &is.default_wire_transfer_delay), GNUNET_PQ_result_spec_relative_time ("default_pay_delay", &is.default_pay_delay), + GNUNET_PQ_result_spec_relative_time ("default_refund_delay", + &is.default_refund_delay), GNUNET_PQ_result_spec_allow_null ( GNUNET_PQ_result_spec_string ("website", &is.website), @@ -190,6 +192,7 @@ TMH_PG_lookup_instances (void *cls, ",mi.use_stefan" ",mi.default_wire_transfer_delay" ",mi.default_pay_delay" + ",mi.default_refund_delay" ",mi.website" ",mi.email" ",mi.phone_number" @@ -214,6 +217,7 @@ TMH_PG_lookup_instances (void *cls, ",mi.use_stefan" ",mi.default_wire_transfer_delay" ",mi.default_pay_delay" + ",mi.default_refund_delay" ",mi.website" ",mi.email" ",mi.phone_number" @@ -272,6 +276,7 @@ TMH_PG_lookup_instance (void *cls, ",mi.use_stefan" ",mi.default_wire_transfer_delay" ",mi.default_pay_delay" + ",mi.default_refund_delay" ",mi.website" ",mi.email" ",mi.phone_number" @@ -297,6 +302,7 @@ TMH_PG_lookup_instance (void *cls, ",mi.use_stefan" ",mi.default_wire_transfer_delay" ",mi.default_pay_delay" + ",mi.default_refund_delay" ",mi.website" ",mi.email" ",mi.phone_number" diff --git a/src/backenddb/pg_update_instance.c b/src/backenddb/pg_update_instance.c @@ -42,6 +42,8 @@ TMH_PG_update_instance (void *cls, &is->default_wire_transfer_delay), GNUNET_PQ_query_param_relative_time ( &is->default_pay_delay), + GNUNET_PQ_query_param_relative_time ( + &is->default_refund_delay), (NULL == is->website) ? GNUNET_PQ_query_param_null () : GNUNET_PQ_query_param_string (is->website), @@ -69,12 +71,13 @@ TMH_PG_update_instance (void *cls, ",use_stefan=$5" ",default_wire_transfer_delay=$6" ",default_pay_delay=$7" - ",website=$8" - ",email=$9" - ",logo=$10" - ",phone_number=$11" - ",phone_validated=$12" - ",email_validated=$13" + ",default_refund_delay=$8" + ",website=$9" + ",email=$10" + ",logo=$11" + ",phone_number=$12" + ",phone_validated=$13" + ",email_validated=$14" " WHERE merchant_id=$1"); return GNUNET_PQ_eval_prepared_non_select (pg->conn, "update_instance", diff --git a/src/backenddb/test_merchantdb.c b/src/backenddb/test_merchantdb.c @@ -122,7 +122,8 @@ make_instance (const char *instance_id, instance->instance.use_stefan = true; instance->instance.default_wire_transfer_delay = GNUNET_TIME_relative_get_minute_ (); - instance->instance.default_pay_delay = GNUNET_TIME_relative_get_second_ (); + instance->instance.default_pay_delay = GNUNET_TIME_UNIT_SECONDS; + instance->instance.default_refund_delay = GNUNET_TIME_UNIT_MINUTES; } diff --git a/src/include/taler_merchant_service.h b/src/include/taler_merchant_service.h @@ -584,6 +584,7 @@ typedef void * @param use_stefan use STEFAN curve for acceptable fees * @param default_wire_transfer_delay default wire transfer delay merchant will ask for * @param default_pay_delay default validity period for offers merchant makes + * @param default_refund_delay default refund period * @param auth_token authentication token to use for access control, NULL for external auth; MUST follow RFC 8959 * @param cb function to call with the * backend's instances information @@ -601,6 +602,7 @@ TALER_MERCHANT_instances_post ( bool use_stefan, struct GNUNET_TIME_Relative default_wire_transfer_delay, struct GNUNET_TIME_Relative default_pay_delay, + struct GNUNET_TIME_Relative default_refund_delay, const char *auth_token, TALER_MERCHANT_InstancesPostCallback cb, void *cb_cls); @@ -649,6 +651,7 @@ typedef void * @param use_stefan use STEFAN curve for acceptable fees * @param default_wire_transfer_delay default wire transfer delay merchant will ask for * @param default_pay_delay default validity period for offers merchant makes + * @param default_refund_delay default refund period * @param cb function to call with the * backend's instances information * @param cb_cls closure for @a config_cb @@ -665,6 +668,7 @@ TALER_MERCHANT_instance_patch ( bool use_stefan, struct GNUNET_TIME_Relative default_wire_transfer_delay, struct GNUNET_TIME_Relative default_pay_delay, + struct GNUNET_TIME_Relative default_refund_delay, TALER_MERCHANT_InstancePatchCallback cb, void *cb_cls); diff --git a/src/include/taler_merchantdb_plugin.h b/src/include/taler_merchantdb_plugin.h @@ -240,6 +240,12 @@ struct TALER_MERCHANTDB_InstanceSettings */ struct GNUNET_TIME_Relative default_pay_delay; + /** + * If the frontend does NOT specify a refund deadline, how long should + * refunds be possible? + */ + struct GNUNET_TIME_Relative default_refund_delay; + }; diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am @@ -10,7 +10,7 @@ lib_LTLIBRARIES = \ libtalermerchant.la libtalermerchant_la_LDFLAGS = \ - -version-info 7:0:0 \ + -version-info 8:0:0 \ -no-undefined libtalermerchant_la_SOURCES = \ diff --git a/src/lib/merchant_api_patch_instance.c b/src/lib/merchant_api_patch_instance.c @@ -164,6 +164,7 @@ TALER_MERCHANT_instance_patch ( bool use_stefan, struct GNUNET_TIME_Relative default_wire_transfer_delay, struct GNUNET_TIME_Relative default_pay_delay, + struct GNUNET_TIME_Relative default_refund_delay, TALER_MERCHANT_InstancePatchCallback cb, void *cb_cls) { @@ -182,7 +183,9 @@ TALER_MERCHANT_instance_patch ( GNUNET_JSON_pack_time_rel ("default_wire_transfer_delay", default_wire_transfer_delay), GNUNET_JSON_pack_time_rel ("default_pay_delay", - default_pay_delay)); + default_pay_delay), + GNUNET_JSON_pack_time_rel ("default_refund_delay", + default_refund_delay)); 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 @@ -170,6 +170,7 @@ TALER_MERCHANT_instances_post ( bool use_stefan, struct GNUNET_TIME_Relative default_wire_transfer_delay, struct GNUNET_TIME_Relative default_pay_delay, + struct GNUNET_TIME_Relative default_refund_delay, const char *auth_password, TALER_MERCHANT_InstancesPostCallback cb, void *cb_cls) @@ -212,6 +213,8 @@ TALER_MERCHANT_instances_post ( default_wire_transfer_delay), GNUNET_JSON_pack_time_rel ("default_pay_delay", default_pay_delay), + GNUNET_JSON_pack_time_rel ("default_refund_delay", + default_refund_delay), GNUNET_JSON_pack_object_steal ("auth", auth_obj)); iph = GNUNET_new (struct TALER_MERCHANT_InstancesPostHandle); diff --git a/src/testing/testing_api_cmd_patch_instance.c b/src/testing/testing_api_cmd_patch_instance.c @@ -163,6 +163,8 @@ patch_instance_run (void *cls, pis->use_stefan, pis->default_wire_transfer_delay, pis->default_pay_delay, + GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_DAYS, + 15), &patch_instance_cb, pis); GNUNET_assert (NULL != pis->iph); diff --git a/src/testing/testing_api_cmd_post_instances.c b/src/testing/testing_api_cmd_post_instances.c @@ -172,6 +172,8 @@ post_instances_run ( pis->use_stefan, pis->default_wire_transfer_delay, pis->default_pay_delay, + GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_DAYS, + 15), pis->auth_token, &post_instances_cb, pis);