merchant

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

commit ddbc213487a90dd1285c454b780fbdb3da5bb2a7
parent 0c13799e32be9f24b3915bca7814a216a6ffb6f5
Author: bohdan-potuzhnyi <bohdan.potuzhnyi@gmail.com>
Date:   Tue,  5 Aug 2025 12:52:32 +0200

Merge branch 'master' into dev/bohdan-potuzhnyi/donau-integration

Diffstat:
Msrc/backend/taler-merchant-httpd.c | 120+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
Msrc/backend/taler-merchant-httpd.h | 21+++++++++++++++++++++
Msrc/backend/taler-merchant-httpd_config.c | 15+++++++++++++++
Msrc/backend/taler-merchant-httpd_private-get-instances-ID.c | 10+++++-----
Msrc/backend/taler-merchant-httpd_private-get-instances.c | 3---
Msrc/backend/taler-merchant-httpd_private-patch-instances-ID.c | 7+++++++
Msrc/backend/taler-merchant-httpd_private-post-instances.c | 11++++++-----
Msrc/lib/merchant_api_get_instance.c | 4----
Msrc/lib/merchant_api_get_instances.c | 3---
9 files changed, 123 insertions(+), 71 deletions(-)

diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c @@ -125,68 +125,36 @@ */ #define DEFAULT_MAX_UPLOAD_SIZE (16 * 1024) -/** - * Which currency do we use? - */ char *TMH_currency; -/** - * What is the base URL for this merchant backend? NULL if it is not - * configured and is to be determined from HTTP headers (X-Forwarded-Host and - * X-Forwarded-Port and X-Forwarded-Prefix) of the reverse proxy. - */ char *TMH_base_url; -/** - * Inform the auditor for all deposit confirmations (global option) - */ int TMH_force_audit; -/** - * Connection handle to the our database - */ struct TALER_MERCHANTDB_Plugin *TMH_db; -/** - * Event handler for instance settings changes. - */ -static struct GNUNET_DB_EventHandler *instance_eh; - -/** - * Hashmap pointing at merchant instances by 'id'. An 'id' is - * just a string that identifies a merchant instance. When a frontend - * needs to specify an instance to the backend, it does so by 'id' - */ struct GNUNET_CONTAINER_MultiHashMap *TMH_by_id_map; -/** - * #GNUNET_YES if protocol version 19 is strictly enforced. - * (Default is #GNUNET_NO) - */ int TMH_strict_v19; -/** - * #GNUNET_YES if authentication is disabled (For testing only!!). - * (Default is #GNUNET_NO) - */ int TMH_auth_disabled; -/** - * How long do we need to keep information on paid contracts on file for tax - * or other legal reasons? Used to block deletions for younger transaction - * data. - */ +int TMH_have_self_provisioning; + +enum TEH_TanChannelSet TEH_mandatory_tan_channels; + struct GNUNET_TIME_Relative TMH_legal_expiration; -/** - * Length of the TMH_cspecs array. - */ unsigned int TMH_num_cspecs; +struct TALER_CurrencySpecification *TMH_cspecs; + +struct GNUNET_CURL_Context *TMH_curl_ctx; + /** - * Rendering specs for currencies. + * Event handler for instance settings changes. */ -struct TALER_CurrencySpecification *TMH_cspecs; +static struct GNUNET_DB_EventHandler *instance_eh; /** * True if we started any HTTP daemon. @@ -199,11 +167,6 @@ static bool have_daemons; static int merchant_connection_close; /** - * Context for all exchange operations (useful to the event loop). - */ -struct GNUNET_CURL_Context *TMH_curl_ctx; - -/** * Context for integrating #TMH_curl_ctx with the * GNUnet event loop. */ @@ -631,6 +594,7 @@ TMH_instance_decref (struct TMH_MerchantInstance *mi) GNUNET_free (mi->settings.id); GNUNET_free (mi->settings.name); GNUNET_free (mi->settings.email); + GNUNET_free (mi->settings.phone); GNUNET_free (mi->settings.website); GNUNET_free (mi->settings.logo); json_decref (mi->settings.address); @@ -2550,6 +2514,8 @@ add_instance_cb (void *cls, mi->settings.name = GNUNET_strdup (mi->settings.name); if (NULL != mi->settings.email) mi->settings.email = GNUNET_strdup (mi->settings.email); + if (NULL != mi->settings.phone) + mi->settings.email = GNUNET_strdup (mi->settings.phone); if (NULL != mi->settings.website) mi->settings.website = GNUNET_strdup (mi->settings.website); if (NULL != mi->settings.logo) @@ -2779,11 +2745,12 @@ run (void *cls, } if (GNUNET_SYSERR == - (TMH_strict_v19 = GNUNET_CONFIGURATION_get_value_yesno (cfg, - "merchant", - "STRICT_PROTOCOL_V19"))) + (TMH_strict_v19 + = GNUNET_CONFIGURATION_get_value_yesno (cfg, + "merchant", + "STRICT_PROTOCOL_V19"))) { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_INFO, "merchant", "STRICT_PROTOCOL_V19"); TMH_strict_v19 = GNUNET_NO; @@ -2800,6 +2767,19 @@ run (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "DANGEROUS: Endpoint Authentication disabled!"); } + + if (GNUNET_SYSERR == + (TMH_have_self_provisioning + = GNUNET_CONFIGURATION_get_value_yesno (cfg, + "merchant", + "ENABLE_SELF_PROVISIONING"))) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_INFO, + "merchant", + "ENABLE_SELF_PROVISIONING"); + TMH_have_self_provisioning = GNUNET_NO; + } + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg, "merchant", @@ -2813,6 +2793,44 @@ run (void *cls, GNUNET_SCHEDULER_shutdown (); return; } + + { + char *tan_channels; + + if (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_string (cfg, + "merchant", + "MANDATORY_TAN_CHANNELS", + &tan_channels)) + { + for (char *tok = strtok (tan_channels, + " "); + NULL != tok; + tok = strtok (NULL, + " ")) + { + if (0 == strcasecmp (tok, + "sms")) + TEH_mandatory_tan_channels |= TEH_TCS_SMS; + else if (0 == strcasecmp (tok, + "email")) + TEH_mandatory_tan_channels |= TEH_TCS_EMAIL; + else + { + GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, + "merchant", + "MANDATORY_TAN_CHANNELS", + tok); + global_ret = EXIT_NOTCONFIGURED; + GNUNET_SCHEDULER_shutdown (); + GNUNET_free (tan_channels); + return; + } + } + GNUNET_free (tan_channels); + } + } + if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, "merchant", diff --git a/src/backend/taler-merchant-httpd.h b/src/backend/taler-merchant-httpd.h @@ -769,6 +769,27 @@ extern int TMH_strict_v19; */ extern int TMH_auth_disabled; +/** + * True if self-provisioning is enabled. + */ +extern int TMH_have_self_provisioning; + +/** + * Set of TAN channels. + */ +enum TEH_TanChannelSet +{ + TEH_TCS_NONE = 0, + TEH_TCS_SMS = 1, + TEH_TCS_EMAIL = 2 +}; + + +/** + * Which TAN channels are mandatory for self-provisioned + * accounts and password resets? Bitmask. + */ +extern enum TEH_TanChannelSet TEH_mandatory_tan_channels; /** * Callback that frees an instances removing diff --git a/src/backend/taler-merchant-httpd_config.c b/src/backend/taler-merchant-httpd_config.c @@ -90,11 +90,21 @@ MH_handler_config (const struct TMH_RequestHandler *rh, { json_t *specs = json_object (); json_t *exchanges = json_array (); + json_t *mtc = json_array (); GNUNET_assert (NULL != specs); GNUNET_assert (NULL != exchanges); + GNUNET_assert (NULL != mtc); TMH_exchange_get_trusted (&add_exchange, exchanges); + if (0 != (TEH_TCS_SMS & TEH_mandatory_tan_channels)) + GNUNET_assert (0 == + json_array_append_new (mtc, + json_string ("sms"))); + if (0 != (TEH_TCS_EMAIL & TEH_mandatory_tan_channels)) + GNUNET_assert (0 == + json_array_append_new (mtc, + json_string ("email"))); for (unsigned int i = 0; i<TMH_num_cspecs; i++) { const struct TALER_CurrencySpecification *cspec = &TMH_cspecs[i]; @@ -110,10 +120,15 @@ MH_handler_config (const struct TMH_RequestHandler *rh, response = TALER_MHD_MAKE_JSON_PACK ( GNUNET_JSON_pack_string ("currency", TMH_currency), + GNUNET_JSON_pack_bool ("have_self_provisioning", + GNUNET_YES == + TMH_have_self_provisioning), GNUNET_JSON_pack_object_steal ("currencies", specs), GNUNET_JSON_pack_array_steal ("exchanges", exchanges), + GNUNET_JSON_pack_array_steal ("mandatory_tan_channels", + mtc), GNUNET_JSON_pack_string ( "implementation", "urn:net:taler:specs:taler-merchant:c-reference"), diff --git a/src/backend/taler-merchant-httpd_private-get-instances-ID.c b/src/backend/taler-merchant-httpd_private-get-instances-ID.c @@ -73,8 +73,8 @@ get_instances_ID (struct TMH_MerchantInstance *mi, auth = GNUNET_JSON_PACK ( GNUNET_JSON_pack_string ("method", GNUNET_is_zero (&mi->auth.auth_hash) - ? "external" - : "token")); + ? "external" + : "token")); return TALER_MHD_REPLY_JSON_PACK ( connection, MHD_HTTP_OK, @@ -82,9 +82,6 @@ get_instances_ID (struct TMH_MerchantInstance *mi, ja), GNUNET_JSON_pack_string ("name", mi->settings.name), - GNUNET_JSON_pack_string ( - "user_type", - "business"), GNUNET_JSON_pack_allow_null ( GNUNET_JSON_pack_string ("website", mi->settings.website)), @@ -92,6 +89,9 @@ get_instances_ID (struct TMH_MerchantInstance *mi, GNUNET_JSON_pack_string ("email", mi->settings.email)), GNUNET_JSON_pack_allow_null ( + GNUNET_JSON_pack_string ("phone_number", + mi->settings.phone)), + GNUNET_JSON_pack_allow_null ( GNUNET_JSON_pack_string ("logo", mi->settings.logo)), GNUNET_JSON_pack_data_auto ("merchant_pub", diff --git a/src/backend/taler-merchant-httpd_private-get-instances.c b/src/backend/taler-merchant-httpd_private-get-instances.c @@ -74,9 +74,6 @@ add_instance (void *cls, GNUNET_JSON_PACK ( GNUNET_JSON_pack_string ("name", mi->settings.name), - GNUNET_JSON_pack_string ( - "user_type", - "business"), GNUNET_JSON_pack_allow_null ( GNUNET_JSON_pack_string ("website", mi->settings.website)), diff --git a/src/backend/taler-merchant-httpd_private-patch-instances-ID.c b/src/backend/taler-merchant-httpd_private-patch-instances-ID.c @@ -78,6 +78,10 @@ patch_instances_ID (struct TMH_MerchantInstance *mi, (const char **) &is.email), NULL), GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_string ("phone_number", + (const char **) &is.phone), + NULL), + GNUNET_JSON_spec_mark_optional ( GNUNET_JSON_spec_string ("logo", (const char **) &is.logo), NULL), @@ -215,6 +219,7 @@ giveup: /* Update our 'settings' */ GNUNET_free (mi->settings.name); GNUNET_free (mi->settings.email); + GNUNET_free (mi->settings.phone); GNUNET_free (mi->settings.website); GNUNET_free (mi->settings.logo); json_decref (mi->settings.address); @@ -226,6 +231,8 @@ giveup: mi->settings.name = GNUNET_strdup (name); if (NULL != is.email) mi->settings.email = GNUNET_strdup (is.email); + if (NULL != is.phone) + mi->settings.email = GNUNET_strdup (is.phone); if (NULL != is.website) mi->settings.website = GNUNET_strdup (is.website); if (NULL != is.logo) diff --git a/src/backend/taler-merchant-httpd_private-post-instances.c b/src/backend/taler-merchant-httpd_private-post-instances.c @@ -52,7 +52,6 @@ TMH_private_post_instances (const struct TMH_RequestHandler *rh, struct TALER_MERCHANTDB_InstanceSettings is = { 0 }; struct TALER_MERCHANTDB_InstanceAuthSettings ias; const char *auth_password = NULL; - const char *uts = "business"; struct TMH_WireMethod *wm_head = NULL; struct TMH_WireMethod *wm_tail = NULL; const json_t *jauth; @@ -62,14 +61,14 @@ TMH_private_post_instances (const struct TMH_RequestHandler *rh, GNUNET_JSON_spec_string ("name", (const char **) &is.name), GNUNET_JSON_spec_mark_optional ( - GNUNET_JSON_spec_string ("user_type", - &uts), - NULL), - GNUNET_JSON_spec_mark_optional ( GNUNET_JSON_spec_string ("email", (const char **) &is.email), NULL), GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_string ("phone_number", + (const char **) &is.phone), + NULL), + GNUNET_JSON_spec_mark_optional ( GNUNET_JSON_spec_string ("website", (const char **) &is.website), NULL), @@ -276,6 +275,8 @@ TMH_private_post_instances (const struct TMH_RequestHandler *rh, mi->settings.name = GNUNET_strdup (is.name); if (NULL != is.email) mi->settings.email = GNUNET_strdup (is.email); + if (NULL != is.email) + mi->settings.phone = GNUNET_strdup (is.phone); if (NULL != is.website) mi->settings.website = GNUNET_strdup (is.website); if (NULL != is.logo) diff --git a/src/lib/merchant_api_get_instance.c b/src/lib/merchant_api_get_instance.c @@ -93,16 +93,12 @@ handle_get_instance_finished (void *cls, { case MHD_HTTP_OK: { - const char *uts; const json_t *address; const json_t *jurisdiction; struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_string ( "name", &igr.details.ok.details.name), - GNUNET_JSON_spec_string ( - "user_type", - &uts), GNUNET_JSON_spec_fixed_auto ( "merchant_pub", &igr.details.ok.details.merchant_pub), diff --git a/src/lib/merchant_api_get_instances.c b/src/lib/merchant_api_get_instances.c @@ -103,12 +103,9 @@ parse_instances (const json_t *json, json_array_foreach (ia, index, value) { struct TALER_MERCHANT_InstanceInformation *ii = &iis[index]; - const char *uts; struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_string ("name", &ii->name), - GNUNET_JSON_spec_string ("user_type", - &uts), GNUNET_JSON_spec_string ("id", &ii->id), GNUNET_JSON_spec_fixed_auto ("merchant_pub",