summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2023-04-23 22:57:55 +0200
committerChristian Grothoff <christian@grothoff.org>2023-04-23 22:57:55 +0200
commit154f964aab5df00cbadaa015474c2b323161aa96 (patch)
tree084f300e664fb96d0693baf73434ed245ef56641
parent889595f986d922ffbcdcd746fdfad7f1a0e53595 (diff)
downloadmerchant-154f964aab5df00cbadaa015474c2b323161aa96.tar.gz
merchant-154f964aab5df00cbadaa015474c2b323161aa96.tar.bz2
merchant-154f964aab5df00cbadaa015474c2b323161aa96.zip
API change for #6363
-rw-r--r--src/backend/Makefile.am1
-rw-r--r--src/backend/taler-merchant-httpd.c2
-rw-r--r--src/backend/taler-merchant-httpd.h12
-rw-r--r--src/backend/taler-merchant-httpd_helper.c223
-rw-r--r--src/backend/taler-merchant-httpd_helper.h44
-rw-r--r--src/backend/taler-merchant-httpd_private-delete-instances-ID.c12
-rw-r--r--src/backend/taler-merchant-httpd_private-get-instances-ID.c3
-rw-r--r--src/backend/taler-merchant-httpd_private-patch-instances-ID.c197
-rw-r--r--src/backend/taler-merchant-httpd_private-post-instances.c169
-rw-r--r--src/backend/taler-merchant-wirewatch.c45
-rw-r--r--src/backenddb/Makefile.am2
-rw-r--r--src/backenddb/pg_insert_account.c68
-rw-r--r--src/backenddb/pg_insert_account.h43
-rw-r--r--src/backenddb/pg_update_account.c64
-rw-r--r--src/backenddb/pg_update_account.h44
-rw-r--r--src/backenddb/plugin_merchantdb_postgres.c49
-rw-r--r--src/backenddb/test_merchantdb.c3
-rw-r--r--src/bank/mb_parse.c5
-rw-r--r--src/include/taler_merchant_service.h28
-rw-r--r--src/include/taler_merchantdb_plugin.h16
-rw-r--r--src/lib/merchant_api_patch_instance.c36
-rw-r--r--src/lib/merchant_api_post_instances.c34
-rwxr-xr-xsrc/testing/test_key_rotation.sh2
-rwxr-xr-xsrc/testing/test_merchant_instance_auth.sh8
-rwxr-xr-xsrc/testing/test_merchant_instance_creation.sh6
-rwxr-xr-xsrc/testing/test_merchant_instance_purge.sh4
-rwxr-xr-xsrc/testing/test_merchant_instance_response.sh2
-rwxr-xr-xsrc/testing/test_merchant_kyc.sh2
-rwxr-xr-xsrc/testing/test_merchant_order_autocleanup.sh4
-rwxr-xr-xsrc/testing/test_merchant_order_creation.sh4
-rwxr-xr-xsrc/testing/test_merchant_product_creation.sh2
-rwxr-xr-xsrc/testing/test_merchant_reserve_creation.sh2
-rwxr-xr-xsrc/testing/test_merchant_transfer_tracking.sh4
-rwxr-xr-xsrc/testing/test_merchant_wirewatch.sh2
-rw-r--r--src/testing/testing_api_cmd_patch_instance.c11
-rw-r--r--src/testing/testing_api_cmd_post_instances.c11
36 files changed, 881 insertions, 283 deletions
diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am
index 89fab12c..d5bcda16 100644
--- a/src/backend/Makefile.am
+++ b/src/backend/Makefile.am
@@ -135,6 +135,7 @@ taler_merchant_httpd_SOURCES = \
taler_merchant_httpd_LDADD = \
$(top_builddir)/src/backenddb/libtalermerchantdb.la \
+ $(top_builddir)/src/bank/libtalermerchantbank.la \
-ltalerexchange \
-ltalertemplating \
-ltalermhd \
diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c
index bebe9f32..8f455f58 100644
--- a/src/backend/taler-merchant-httpd.c
+++ b/src/backend/taler-merchant-httpd.c
@@ -240,6 +240,8 @@ TMH_instance_decref (struct TMH_MerchantInstance *mi)
wm);
GNUNET_free (wm->payto_uri);
GNUNET_free (wm->wire_method);
+ GNUNET_free (wm->credit_facade_url);
+ json_decref (wm->credit_facade_credentials);
GNUNET_free (wm);
}
diff --git a/src/backend/taler-merchant-httpd.h b/src/backend/taler-merchant-httpd.h
index 391987ab..6f637934 100644
--- a/src/backend/taler-merchant-httpd.h
+++ b/src/backend/taler-merchant-httpd.h
@@ -25,6 +25,7 @@
#include "taler_merchantdb_lib.h"
#include <taler/taler_mhd_lib.h>
#include <gnunet/gnunet_mhd_compat.h>
+#include "taler_merchant_bank_lib.h"
/**
* Shorthand for exit jumps.
@@ -71,6 +72,17 @@ struct TMH_WireMethod
struct TALER_MerchantWireHashP h_wire;
/**
+ * Base URL of the credit facade.
+ */
+ char *credit_facade_url;
+
+ /**
+ * Authentication data to access the credit facade.
+ * May be uninitialized if not provided by the client.
+ */
+ json_t *credit_facade_credentials;
+
+ /**
* Is this wire method active (should it be included in new contracts)?
*/
bool active;
diff --git a/src/backend/taler-merchant-httpd_helper.c b/src/backend/taler-merchant-httpd_helper.c
index 149ff3c3..981f5937 100644
--- a/src/backend/taler-merchant-httpd_helper.c
+++ b/src/backend/taler-merchant-httpd_helper.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- (C) 2014--2021 Taler Systems SA
+ (C) 2014--2023 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Lesser General Public License as published by the Free Software
@@ -27,68 +27,177 @@
#include <taler/taler_templating_lib.h>
#include <taler/taler_dbevents.h>
-/**
- * check @a payto_uris for well-formedness
- *
- * @param payto_uris JSON array of payto URIs (presumably)
- * @return true if they are all valid URIs (and this is an array of strings)
- */
+
+enum GNUNET_GenericReturnValue
+TMH_cmp_wire_account (
+ const json_t *account,
+ const struct TMH_WireMethod *wm)
+{
+ const char *credit_facade_url = NULL;
+ json_t *credit_facade_credentials = NULL;
+ const char *uri;
+ struct GNUNET_JSON_Specification ispec[] = {
+ GNUNET_JSON_spec_string ("payto_uri",
+ &uri),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_string ("credit_facade_url",
+ &credit_facade_url),
+ NULL),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_json ("credit_facade_credentials",
+ &credit_facade_credentials),
+ NULL),
+ GNUNET_JSON_spec_end ()
+ };
+ enum GNUNET_GenericReturnValue res;
+ const char *ename;
+ unsigned int eline;
+
+ res = GNUNET_JSON_parse (account,
+ ispec,
+ &ename,
+ &eline);
+ if (GNUNET_OK != res)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Failed to parse account spec: %s (%u)\n",
+ ename,
+ eline);
+ return GNUNET_SYSERR;
+ }
+ if (0 !=
+ strcmp (wm->payto_uri,
+ uri))
+ {
+ GNUNET_JSON_parse_free (ispec);
+ return GNUNET_SYSERR;
+ }
+ if ( (NULL == credit_facade_url) !=
+ (NULL == wm->credit_facade_url) ||
+ (NULL == credit_facade_credentials) !=
+ (NULL == wm->credit_facade_credentials) )
+ {
+ GNUNET_JSON_parse_free (ispec);
+ return GNUNET_NO;
+ }
+ if ( (NULL != credit_facade_url) &&
+ (0 != strcmp (credit_facade_url,
+ wm->credit_facade_url)) )
+ {
+ GNUNET_JSON_parse_free (ispec);
+ return GNUNET_NO;
+ }
+ if ( (NULL != credit_facade_credentials) &&
+ (0 != json_equal (credit_facade_credentials,
+ wm->credit_facade_credentials)) )
+ {
+ GNUNET_JSON_parse_free (ispec);
+ return GNUNET_NO;
+ }
+ GNUNET_JSON_parse_free (ispec);
+ return GNUNET_YES;
+}
+
+
bool
-TMH_payto_uri_array_valid (const json_t *payto_uris)
+TMH_accounts_array_valid (const json_t *accounts)
{
- bool payto_ok = true;
+ unsigned int len;
- if (! json_is_array (payto_uris))
+ if (! json_is_array (accounts))
{
GNUNET_break_op (0);
- payto_ok = false;
+ return false;
}
- else
+ len = json_array_size (accounts);
+ for (unsigned int i = 0; i<len; i++)
{
- unsigned int len = json_array_size (payto_uris);
+ json_t *payto_uri = json_array_get (accounts,
+ i);
+ const char *credit_facade_url = NULL;
+ json_t *credit_facade_credentials = NULL;
+ const char *uri;
+ struct GNUNET_JSON_Specification ispec[] = {
+ GNUNET_JSON_spec_string ("payto_uri",
+ &uri),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_string ("credit_facade_url",
+ &credit_facade_url),
+ NULL),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_json ("credit_facade_credentials",
+ &credit_facade_credentials),
+ NULL),
+ GNUNET_JSON_spec_end ()
+ };
+ enum GNUNET_GenericReturnValue res;
+ const char *ename;
+ unsigned int eline;
+
+ res = GNUNET_JSON_parse (payto_uri,
+ ispec,
+ &ename,
+ &eline);
+ if (GNUNET_OK != res)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Failed to parse account spec: %s (%u)\n",
+ ename,
+ eline);
+ return false;
+ }
- for (unsigned int i = 0; i<len; i++)
+ /* Test for the same payto:// URI being given twice */
+ for (unsigned int j = 0; j<i; j++)
{
- json_t *payto_uri = json_array_get (payto_uris,
- i);
- const char *uri;
-
- if (! json_is_string (payto_uri))
- payto_ok = false;
- uri = json_string_value (payto_uri);
- /* Test for the same payto:// URI being given twice */
- for (unsigned int j = 0; j<i; j++)
+ json_t *old_uri = json_array_get (accounts,
+ j);
+ if (0 == strcmp (uri,
+ json_string_value (
+ json_object_get (old_uri,
+ "payto_uri"))))
{
- json_t *old_uri = json_array_get (payto_uris,
- j);
- if (json_equal (payto_uri,
- old_uri))
- {
- GNUNET_break_op (0);
- payto_ok = false;
- break;
- }
+ GNUNET_break_op (0);
+ GNUNET_JSON_parse_free (ispec);
+ return false;
}
- if (! payto_ok)
- break;
+ }
+ {
+ char *err;
+
+ if (NULL !=
+ (err = TALER_payto_validate (uri)))
{
- char *err;
-
- if (NULL !=
- (err = TALER_payto_validate (uri)))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Encountered invalid payto://-URI `%s': %s\n",
- uri,
- err);
- GNUNET_free (err);
- payto_ok = false;
- break;
- }
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Encountered invalid payto://-URI `%s': %s\n",
+ uri,
+ err);
+ GNUNET_free (err);
+ GNUNET_JSON_parse_free (ispec);
+ return false;
}
}
+ if ( (NULL != credit_facade_url) ||
+ (NULL != credit_facade_credentials) )
+ {
+ struct TALER_MERCHANT_BANK_AuthenticationData auth;
+
+ if (GNUNET_OK !=
+ TALER_MERCHANT_BANK_auth_parse_json (credit_facade_credentials,
+ credit_facade_url,
+ &auth))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Invalid credit facade URL or credentials `%s'\n",
+ credit_facade_url);
+ GNUNET_JSON_parse_free (ispec);
+ return false;
+ }
+ TALER_MERCHANT_BANK_auth_free (&auth);
+ }
+ GNUNET_JSON_parse_free (ispec);
}
- return payto_ok;
+ return true;
}
@@ -396,14 +505,17 @@ TMH_taxes_array_valid (const json_t *taxes)
struct TMH_WireMethod *
-TMH_setup_wire_account (const char *payto_uri)
+TMH_setup_wire_account (
+ const char *payto_uri,
+ const char *credit_facade_url,
+ const json_t *credit_facade_credentials)
{
struct TMH_WireMethod *wm;
char *emsg;
if (NULL != (emsg = TALER_payto_validate (payto_uri)))
{
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Invalid URI `%s': %s\n",
payto_uri,
emsg);
@@ -412,6 +524,12 @@ TMH_setup_wire_account (const char *payto_uri)
}
wm = GNUNET_new (struct TMH_WireMethod);
+ if (NULL != credit_facade_url)
+ wm->credit_facade_url
+ = GNUNET_strdup (credit_facade_url);
+ if (NULL != credit_facade_credentials)
+ wm->credit_facade_credentials
+ = json_incref ((json_t*) credit_facade_credentials);
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
&wm->wire_salt,
sizeof (wm->wire_salt));
@@ -472,8 +590,9 @@ TMH_check_auth_config (struct MHD_Connection *connection,
TALER_MHD_reply_with_error (connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_MERCHANT_PRIVATE_POST_INSTANCES_BAD_AUTH,
- "bad authentication config")) ?
- GNUNET_NO : GNUNET_SYSERR;
+ "bad authentication config"))
+ ? GNUNET_NO
+ : GNUNET_SYSERR;
}
return GNUNET_OK;
}
diff --git a/src/backend/taler-merchant-httpd_helper.h b/src/backend/taler-merchant-httpd_helper.h
index 5cee97cc..14156fce 100644
--- a/src/backend/taler-merchant-httpd_helper.h
+++ b/src/backend/taler-merchant-httpd_helper.h
@@ -28,13 +28,13 @@
#include "taler-merchant-httpd.h"
/**
- * check @a payto_uris for well-formedness
+ * check @a accounts for well-formedness
*
- * @param payto_uris JSON array of payto URIs (presumably)
- * @return true if they are all valid URIs (and this is an array of strings)
+ * @param accounts JSON array of merchant accounts (presumably)
+ * @return true if they are all valid accounts
*/
bool
-TMH_payto_uri_array_valid (const json_t *payto_uris);
+TMH_accounts_array_valid (const json_t *accounts);
/**
@@ -103,15 +103,45 @@ TMH_template_contract_valid (const json_t *template_contract);
* Setup new wire method for the given @ payto_uri.
*
* @param payto_uri already validated payto URI
+ * @param credit_facade_url where to download credit information for this account (can be NULL)
+ * @param credit_facade_credentials credentials for the @a credit_facade_url
* @return new wire method object, never fails
*/
struct TMH_WireMethod *
-TMH_setup_wire_account (const char *payto_uri);
+TMH_setup_wire_account (
+ const char *payto_uri,
+ const char *credit_facade_url,
+ const json_t *credit_facade_credentials);
+
/**
- * FIXME: document
+ * Test if JSON spec @a account for a wire method is equal to the given @a wm.
+ *
+ * @param account JSON spec for a merchant account
+ * @param wm known wire method
+ * @return #GNUNET_YES if both specifications are equal
+ * #GNUNET_NO if the specifications are for
+ * the same account but differ in the credit facade
+ * #GNUNET_SYSERR if the specs are for different accounts
+ * or if @a account is malformed
*/
+enum GNUNET_GenericReturnValue
+TMH_cmp_wire_account (
+ const json_t *account,
+ const struct TMH_WireMethod *wm);
+
+/**
+ * Check that the provided authentication configuration
+ * is valid.
+ *
+ * @param connection connection to use for returning errors
+ * @param jauth JSON with authentication data
+ * @param[out] auth_token set to the authentication token
+ * @return #GNUNET_OK on success,
+ * #GNUNET_NO if an error was returned on @a connection
+ * #GNUNET_SYSERR if we failed to return an error on @a connection
+ */
enum GNUNET_GenericReturnValue
TMH_check_auth_config (struct MHD_Connection *connection,
const json_t *jauth,
@@ -144,7 +174,6 @@ TMH_uuid_from_string (const char *uuids,
GNUNET_JSON_pack_object_incref ("exchange_reply", (json_t *) (hr)->reply))
-
/**
* TMH_trigger_webhook is a function that need to be use when someone
* pay. Merchant need to have a notification.
@@ -159,5 +188,4 @@ TMH_trigger_webhook (const char *instance,
const json_t *args);
-
#endif
diff --git a/src/backend/taler-merchant-httpd_private-delete-instances-ID.c b/src/backend/taler-merchant-httpd_private-delete-instances-ID.c
index 2791d6d7..8862eadd 100644
--- a/src/backend/taler-merchant-httpd_private-delete-instances-ID.c
+++ b/src/backend/taler-merchant-httpd_private-delete-instances-ID.c
@@ -21,6 +21,7 @@
#include "platform.h"
#include "taler-merchant-httpd_private-delete-instances-ID.h"
#include <taler/taler_json_lib.h>
+#include <taler/taler_dbevents.h>
/**
@@ -52,6 +53,17 @@ delete_instances_ID (struct TMH_MerchantInstance *mi,
else
qs = TMH_db->delete_instance_private_key (TMH_db->cls,
mi->settings.id);
+ {
+ struct GNUNET_DB_EventHeaderP es = {
+ .size = htons (sizeof (es)),
+ .type = htons (TALER_DBEVENT_MERCHANT_ACCOUNTS_CHANGED)
+ };
+
+ TMH_db->event_notify (TMH_db->cls,
+ &es,
+ NULL,
+ 0);
+ }
switch (qs)
{
case GNUNET_DB_STATUS_HARD_ERROR:
diff --git a/src/backend/taler-merchant-httpd_private-get-instances-ID.c b/src/backend/taler-merchant-httpd_private-get-instances-ID.c
index c51d3de0..d2e3d937 100644
--- a/src/backend/taler-merchant-httpd_private-get-instances-ID.c
+++ b/src/backend/taler-merchant-httpd_private-get-instances-ID.c
@@ -52,6 +52,9 @@ get_instances_ID (struct TMH_MerchantInstance *mi,
GNUNET_JSON_pack_string (
"payto_uri",
wm->payto_uri),
+ GNUNET_JSON_pack_string (
+ "credit_facade_url",
+ wm->credit_facade_url),
GNUNET_JSON_pack_data_auto ("h_wire",
&wm->h_wire),
GNUNET_JSON_pack_data_auto (
diff --git a/src/backend/taler-merchant-httpd_private-patch-instances-ID.c b/src/backend/taler-merchant-httpd_private-patch-instances-ID.c
index 77a75da4..9241d069 100644
--- a/src/backend/taler-merchant-httpd_private-patch-instances-ID.c
+++ b/src/backend/taler-merchant-httpd_private-patch-instances-ID.c
@@ -26,6 +26,7 @@
#include "taler-merchant-httpd_private-patch-instances-ID.h"
#include "taler-merchant-httpd_helper.h"
#include <taler/taler_json_lib.h>
+#include <taler/taler_dbevents.h>
/**
@@ -62,14 +63,14 @@ patch_instances_ID (struct TMH_MerchantInstance *mi,
struct TMH_HandlerContext *hc)
{
struct TALER_MERCHANTDB_InstanceSettings is;
- json_t *payto_uris;
+ json_t *accounts;
const char *name;
const char *uts = "business";
struct TMH_WireMethod *wm_head = NULL;
struct TMH_WireMethod *wm_tail = NULL;
struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_json ("payto_uris",
- &payto_uris),
+ GNUNET_JSON_spec_json ("accounts",
+ &accounts),
GNUNET_JSON_spec_string ("name",
&name),
GNUNET_JSON_spec_mark_optional (
@@ -167,7 +168,7 @@ patch_instances_ID (struct TMH_MerchantInstance *mi,
"jurisdiction");
}
- if (! TMH_payto_uri_array_valid (payto_uris))
+ if (! TMH_accounts_array_valid (accounts))
{
GNUNET_JSON_parse_free (spec);
return TALER_MHD_reply_with_error (connection,
@@ -175,7 +176,7 @@ patch_instances_ID (struct TMH_MerchantInstance *mi,
TALER_EC_GENERIC_PAYTO_URI_MALFORMED,
NULL);
}
- for (unsigned int i = 0; i<MAX_RETRIES; i++)
+ for (unsigned int retry = 0; retry<MAX_RETRIES; retry++)
{
/* Cleanup after earlier loops */
{
@@ -255,44 +256,59 @@ patch_instances_ID (struct TMH_MerchantInstance *mi,
/* Check for changes in accounts */
{
- unsigned int len = json_array_size (payto_uris);
+ unsigned int len = json_array_size (accounts);
struct TMH_WireMethod *matches[GNUNET_NZL (len)];
- bool matched;
+ bool updated[GNUNET_NZL (len)];
memset (matches,
0,
sizeof (matches));
+ memset (updated,
+ 0,
+ sizeof (updated));
for (struct TMH_WireMethod *wm = mi->wm_head;
NULL != wm;
wm = wm->next)
{
- const char *uri = wm->payto_uri;
-
- GNUNET_assert (NULL != uri);
- matched = false;
+ bool matched = false;
for (unsigned int i = 0; i<len; i++)
{
- const char *str = json_string_value (json_array_get (payto_uris,
- i));
- if (0 == strcasecmp (uri,
- str))
+ json_t *account = json_array_get (accounts,
+ i);
+ enum GNUNET_GenericReturnValue ret;
+
+ ret = TMH_cmp_wire_account (account,
+ wm);
+ switch (ret)
{
+ case GNUNET_SYSERR:
+ continue;
+ case GNUNET_NO:
+ matched = true;
/* our own existing payto URIs should be unique, that is no
duplicates in the list, so we cannot match twice */
GNUNET_assert (NULL == matches[i]);
matches[i] = wm;
+ updated[i] = true;
+ break;
+ case GNUNET_YES:
matched = true;
+ /* our own existing payto URIs should be unique, that is no
+ duplicates in the list, so we cannot match twice */
+ GNUNET_assert (NULL == matches[i]);
+ matches[i] = wm;
break;
}
}
+
/* delete unmatched (= removed) accounts */
if ( (! matched) &&
(wm->active) )
{
/* Account was REMOVED */
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Existing account `%s' not found, inactivating it.\n",
- uri);
+ "Existing account `%s' not found, deactivating it.\n",
+ wm->payto_uri);
wm->deleting = true;
qs = TMH_db->inactivate_account (TMH_db->cls,
mi->settings.id,
@@ -306,16 +322,51 @@ patch_instances_ID (struct TMH_MerchantInstance *mi,
goto giveup;
}
}
- }
- /* Find _new_ accounts */
+ } /* for (wm) */
+
+ /* handle updates */
for (unsigned int i = 0; i<len; i++)
{
- struct TALER_MERCHANTDB_AccountDetails ad;
- struct TMH_WireMethod *wm;
+ struct TMH_WireMethod *wm = matches[i];
- if (NULL != matches[i])
+ if (! updated[i])
+ continue;
+ GNUNET_assert (NULL != wm);
{
- wm = matches[i];
+ struct TALER_MERCHANTDB_AccountDetails ad = {
+ .payto_uri = wm->payto_uri,
+ .h_wire = wm->h_wire,
+ .salt = wm->wire_salt,
+ .credit_facade_url = wm->credit_facade_url,
+ .credit_facade_credentials = wm->credit_facade_credentials,
+ .active = true
+ };
+
+ qs = TMH_db->update_account (TMH_db->cls,
+ mi->settings.id,
+ &ad);
+ if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
+ {
+ TMH_db->rollback (TMH_db->cls);
+ if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+ goto retry;
+ else
+ goto giveup;
+ }
+ } /* ad scope */
+ } /* for possible updates */
+
+ /* Find _new_ accounts or accounts to only enable */
+ for (unsigned int i = 0; i<len; i++)
+ {
+ json_t *account = json_array_get (accounts,
+ i);
+ struct TMH_WireMethod *wm = matches[i];
+
+ if (NULL != wm)
+ {
+ if (updated[i])
+ continue; /* handled above */
if (! wm->active)
{
qs = TMH_db->activate_account (TMH_db->cls,
@@ -333,34 +384,82 @@ patch_instances_ID (struct TMH_MerchantInstance *mi,
wm->enabling = true;
continue;
}
- ad.payto_uri = json_string_value (json_array_get (payto_uris,
- i));
- GNUNET_assert (NULL != ad.payto_uri);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Adding NEW account `%s'\n",
- ad.payto_uri);
- wm = TMH_setup_wire_account (ad.payto_uri);
- GNUNET_assert (NULL != wm); /* checked payto_uri validity earlier */
- GNUNET_CONTAINER_DLL_insert (wm_head,
- wm_tail,
- wm);
- ad.h_wire = wm->h_wire;
- ad.salt = wm->wire_salt;
- ad.active = true;
- qs = TMH_db->insert_account (TMH_db->cls,
- mi->settings.id,
- &ad);
- if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
+
{
- TMH_db->rollback (TMH_db->cls);
- if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
- goto retry;
- else
- goto giveup;
- }
- }
- }
+ const char *credit_facade_url = NULL;
+ json_t *credit_facade_credentials = NULL;
+ const char *uri;
+ struct GNUNET_JSON_Specification ispec[] = {
+ GNUNET_JSON_spec_string ("payto_uri",
+ &uri),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_string ("credit_facade_url",
+ &credit_facade_url),
+ NULL),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_json ("credit_facade_credentials",
+ &credit_facade_credentials),
+ NULL),
+ GNUNET_JSON_spec_end ()
+ };
+ enum GNUNET_GenericReturnValue res;
+
+ res = TALER_MHD_parse_json_data (connection,
+ account,
+ ispec);
+ if (GNUNET_OK != res)
+ return (GNUNET_NO == res)
+ ? MHD_YES
+ : MHD_NO;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Adding NEW account `%s'\n",
+ uri);
+ wm = TMH_setup_wire_account (uri,
+ credit_facade_url,
+ credit_facade_credentials);
+ GNUNET_assert (NULL != wm); /* checked payto_uri validity earlier */
+ GNUNET_CONTAINER_DLL_insert (wm_head,
+ wm_tail,
+ wm);
+ GNUNET_JSON_parse_free (ispec);
+ } /* ispec scope */
+ {
+ struct TALER_MERCHANTDB_AccountDetails ad = {
+ .payto_uri = wm->payto_uri,
+ .h_wire = wm->h_wire,
+ .salt = wm->wire_salt,
+ .credit_facade_url = wm->credit_facade_url,
+ .credit_facade_credentials = wm->credit_facade_credentials,
+ .active = true
+ };
+
+ qs = TMH_db->insert_account (TMH_db->cls,
+ mi->settings.id,
+ &ad);
+ if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
+ {
+ TMH_db->rollback (TMH_db->cls);
+ if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+ goto retry;
+ else
+ goto giveup;
+ }
+ } /* ad variable scope */
+ } /* for (i) to find new accounts */
+ } /* scope for checking for account changes */
+
+ {
+ struct GNUNET_DB_EventHeaderP es = {
+ .size = htons (sizeof (es)),
+ .type = htons (TALER_DBEVENT_MERCHANT_ACCOUNTS_CHANGED)
+ };
+
+ TMH_db->event_notify (TMH_db->cls,
+ &es,
+ NULL,
+ 0);
+ }
qs = TMH_db->commit (TMH_db->cls);
retry:
if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
diff --git a/src/backend/taler-merchant-httpd_private-post-instances.c b/src/backend/taler-merchant-httpd_private-post-instances.c
index 4d9320ba..c8f443cd 100644
--- a/src/backend/taler-merchant-httpd_private-post-instances.c
+++ b/src/backend/taler-merchant-httpd_private-post-instances.c
@@ -25,6 +25,8 @@
#include "platform.h"
#include "taler-merchant-httpd_private-post-instances.h"
#include "taler-merchant-httpd_helper.h"
+#include "taler_merchant_bank_lib.h"
+#include <taler/taler_dbevents.h>
#include <taler/taler_json_lib.h>
#include <regex.h>
@@ -39,51 +41,45 @@
* URIs as those already in @a mi (possibly in a different order).
*
* @param mi a merchant instance with accounts
- * @param payto_uris a JSON array with accounts (presumably)
+ * @param accounts a JSON array with accounts (presumably)
* @return true if they are 'equal', false if not or of payto_uris is not an array
*/
static bool
accounts_equal (const struct TMH_MerchantInstance *mi,
- json_t *payto_uris)
+ const json_t *accounts)
{
- if (! json_is_array (payto_uris))
+ if (! json_is_array (accounts))
return false;
{
- unsigned int len = json_array_size (payto_uris);
- bool matches[GNUNET_NZL (len)];
- struct TMH_WireMethod *wm;
+ unsigned int len = json_array_size (accounts);
+ enum GNUNET_GenericReturnValue matches[GNUNET_NZL (len)];
- memset (matches,
- 0,
- sizeof (matches));
- for (wm = mi->wm_head;
+ for (unsigned int i = 0; i<len; i++)
+ matches[i] = GNUNET_SYSERR;
+ for (struct TMH_WireMethod *wm = mi->wm_head;
NULL != wm;
wm = wm->next)
{
- const char *uri = wm->payto_uri;
-
- GNUNET_assert (NULL != uri);
for (unsigned int i = 0; i<len; i++)
{
- const char *str = json_string_value (json_array_get (payto_uris,
- i));
+ json_t *account = json_array_get (accounts,
+ i);
+ enum GNUNET_GenericReturnValue ret;
- GNUNET_assert (NULL != str);
- if (0 == strcasecmp (uri,
- str))
+ ret = TMH_cmp_wire_account (account,
+ wm);
+ if (GNUNET_SYSERR == ret)
+ continue;
+ if (GNUNET_SYSERR != matches[i])
{
- if (matches[i])
- {
- GNUNET_break (0);
- return false; /* duplicate entry!? */
- }
- matches[i] = true;
- break;
+ GNUNET_break (0);
+ return false; /* duplicate entry!? */
}
+ matches[i] = ret;
}
}
for (unsigned int i = 0; i<len; i++)
- if (! matches[i])
+ if (GNUNET_YES != matches[i])
return false;
}
return true;
@@ -91,48 +87,6 @@ accounts_equal (const struct TMH_MerchantInstance *mi,
/**
- * Free memory used by @a wm
- *
- * @param wm wire method to free
- */
-static void
-free_wm (struct TMH_WireMethod *wm)
-{
- GNUNET_free (wm->payto_uri);
- GNUNET_free (wm->wire_method);
- GNUNET_free (wm);
-}
-
-
-/**
- * Free memory used by @a mi.
- *
- * @param mi instance to free
- */
-static void
-free_mi (struct TMH_MerchantInstance *mi)
-{
- struct TMH_WireMethod *wm;
-
- while (NULL != (wm = mi->wm_head))
- {
- GNUNET_CONTAINER_DLL_remove (mi->wm_head,
- mi->wm_tail,
- wm);
- free_wm (wm);
- }
- GNUNET_free (mi->settings.id);
- GNUNET_free (mi->settings.name);
- GNUNET_free (mi->settings.website);
- GNUNET_free (mi->settings.email);
- GNUNET_free (mi->settings.logo);
- json_decref (mi->settings.address);
- json_decref (mi->settings.jurisdiction);
- GNUNET_free (mi);
-}
-
-
-/**
* Generate an instance, given its configuration.
*
* @param rh context of the handler
@@ -147,15 +101,15 @@ TMH_private_post_instances (const struct TMH_RequestHandler *rh,
{
struct TALER_MERCHANTDB_InstanceSettings is;
struct TALER_MERCHANTDB_InstanceAuthSettings ias;
- json_t *payto_uris;
+ json_t *accounts;
const char *auth_token = NULL;
const char *uts = "business";
struct TMH_WireMethod *wm_head = NULL;
struct TMH_WireMethod *wm_tail = NULL;
json_t *jauth;
struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_json ("payto_uris",
- &payto_uris),
+ GNUNET_JSON_spec_json ("accounts",
+ &accounts),
GNUNET_JSON_spec_string ("id",
(const char **) &is.id),
GNUNET_JSON_spec_string ("name",
@@ -208,7 +162,6 @@ TMH_private_post_instances (const struct TMH_RequestHandler *rh,
? MHD_YES
: MHD_NO;
}
-
if (NULL == uts)
uts = "business";
if (GNUNET_OK !=
@@ -233,8 +186,8 @@ TMH_private_post_instances (const struct TMH_RequestHandler *rh,
return (GNUNET_NO == ret) ? MHD_YES : MHD_NO;
}
- /* check payto_uris for well-formedness */
- if (! TMH_payto_uri_array_valid (payto_uris))
+ /* check accounts for well-formedness */
+ if (! TMH_accounts_array_valid (accounts))
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_PAYTO_URI_MALFORMED,
@@ -341,12 +294,14 @@ TMH_private_post_instances (const struct TMH_RequestHandler *rh,
is.address)) &&
(1 == json_equal (mi->settings.jurisdiction,
is.jurisdiction)) &&
- (GNUNET_OK == TALER_amount_cmp_currency (
+ (GNUNET_OK ==
+ TALER_amount_cmp_currency (
&mi->settings.default_max_deposit_fee,
&is.default_max_deposit_fee)) &&
(0 == TALER_amount_cmp (&mi->settings.default_max_deposit_fee,
&is.default_max_deposit_fee)) &&
- (GNUNET_OK == TALER_amount_cmp_currency (
+ (GNUNET_OK ==
+ TALER_amount_cmp_currency (
&mi->settings.default_max_wire_fee,
&is.default_max_wire_fee)) &&
(0 == TALER_amount_cmp (&mi->settings.default_max_wire_fee,
@@ -360,7 +315,7 @@ TMH_private_post_instances (const struct TMH_RequestHandler *rh,
==,
is.default_pay_delay)) &&
(accounts_equal (mi,
- payto_uris)) )
+ accounts)) )
{
GNUNET_JSON_parse_free (spec);
return TALER_MHD_reply_static (connection,
@@ -382,18 +337,46 @@ TMH_private_post_instances (const struct TMH_RequestHandler *rh,
/* convert provided payto URIs into internal data structure with salts */
{
- unsigned int len = json_array_size (payto_uris);
+ unsigned int len = json_array_size (accounts);
for (unsigned int i = 0; i<len; i++)
{
- json_t *payto_uri = json_array_get (payto_uris,
- i);
+ json_t *account = json_array_get (accounts,
+ i);
+ const char *credit_facade_url = NULL;
+ json_t *credit_facade_credentials = NULL;
+ const char *uri;
struct TMH_WireMethod *wm;
-
- wm = TMH_setup_wire_account (json_string_value (payto_uri));
+ struct GNUNET_JSON_Specification ispec[] = {
+ GNUNET_JSON_spec_string ("payto_uri",
+ &uri),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_string ("credit_facade_url",
+ &credit_facade_url),
+ NULL),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_json ("credit_facade_credentials",
+ &credit_facade_credentials),
+ NULL),
+ GNUNET_JSON_spec_end ()
+ };
+ enum GNUNET_GenericReturnValue res;
+
+ res = TALER_MHD_parse_json_data (connection,
+ account,
+ ispec);
+ if (GNUNET_OK != res)
+ return (GNUNET_NO == res)
+ ? MHD_YES
+ : MHD_NO;
+ wm = TMH_setup_wire_account (uri,
+ credit_facade_url,
+ credit_facade_credentials);
+ GNUNET_assert (NULL != wm);
GNUNET_CONTAINER_DLL_insert (wm_head,
wm_tail,
wm);
+ GNUNET_JSON_parse_free (ispec);
}
}
@@ -446,7 +429,8 @@ TMH_private_post_instances (const struct TMH_RequestHandler *rh,
"post /instances"))
{
GNUNET_JSON_parse_free (spec);
- free_mi (mi);
+ mi->rc = 1;
+ TMH_instance_decref (mi);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_GENERIC_DB_START_FAILED,
@@ -469,7 +453,8 @@ TMH_private_post_instances (const struct TMH_RequestHandler *rh,
TALER_EC_MERCHANT_PRIVATE_POST_INSTANCES_ALREADY_EXISTS,
is.id);
GNUNET_JSON_parse_free (spec);
- free_mi (mi);
+ mi->rc = 1;
+ TMH_instance_decref (mi);
return ret;
}
for (struct TMH_WireMethod *wm = wm_head;
@@ -480,6 +465,8 @@ TMH_private_post_instances (const struct TMH_RequestHandler *rh,
.payto_uri = wm->payto_uri,
.salt = wm->wire_salt,
.h_wire = wm->h_wire,
+ .credit_facade_url = wm->credit_facade_url,
+ .credit_facade_credentials = wm->credit_facade_credentials,
.active = wm->active
};
@@ -497,6 +484,17 @@ TMH_private_post_instances (const struct TMH_RequestHandler *rh,
break;
goto retry;
}
+ {
+ struct GNUNET_DB_EventHeaderP es = {
+ .size = htons (sizeof (es)),
+ .type = htons (TALER_DBEVENT_MERCHANT_ACCOUNTS_CHANGED)
+ };
+
+ TMH_db->event_notify (TMH_db->cls,
+ &es,
+ NULL,
+ 0);
+ }
qs = TMH_db->commit (TMH_db->cls);
if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
qs = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
@@ -507,7 +505,8 @@ retry:
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
{
GNUNET_JSON_parse_free (spec);
- free_mi (mi);
+ mi->rc = 1;
+ TMH_instance_decref (mi);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_GENERIC_DB_COMMIT_FAILED,
diff --git a/src/backend/taler-merchant-wirewatch.c b/src/backend/taler-merchant-wirewatch.c
index 380bcc11..03e317b0 100644
--- a/src/backend/taler-merchant-wirewatch.c
+++ b/src/backend/taler-merchant-wirewatch.c
@@ -22,6 +22,7 @@
#include <gnunet/gnunet_util_lib.h>
#include <jansson.h>
#include <pthread.h>
+#include <taler/taler_dbevents.h>
#include "taler_merchant_bank_lib.h"
#include "taler_merchantdb_lib.h"
#include "taler_merchantdb_plugin.h"
@@ -123,6 +124,12 @@ static struct GNUNET_CURL_Context *ctx;
static struct GNUNET_CURL_RescheduleContext *rc;
/**
+ * Event handler to learn that the configuration changed
+ * and we should shutdown (to be restarted).
+ */
+static struct GNUNET_DB_EventHandler *eh;
+
+/**
* Value to return from main(). 0 on success, non-zero on errors.
*/
static int global_ret;
@@ -209,6 +216,11 @@ shutdown_task (void *cls)
save (w);
end_watch (w);
}
+ if (NULL != eh)
+ {
+ db_plugin->event_listen_cancel (eh);
+ eh = NULL;
+ }
TALER_MERCHANTDB_plugin_unload (db_plugin);
db_plugin = NULL;
cfg = NULL;
@@ -457,6 +469,26 @@ start_watch (
/**
+ * Function called on configuration change events received from Postgres. We
+ * shutdown (and systemd should restart us).
+ *
+ * @param cls closure (NULL)
+ * @param extra additional event data provided
+ * @param extra_size number of bytes in @a extra
+ */
+static void
+config_changed (void *cls,
+ const void *extra,
+ size_t extra_size)
+{
+ (void) cls;
+ (void) extra;
+ (void) extra_size;
+ GNUNET_SCHEDULER_shutdown ();
+}
+
+
+/**
* First task.
*
* @param cls closure, NULL
@@ -501,7 +533,18 @@ run (void *cls,
GNUNET_SCHEDULER_shutdown ();
return;
}
- // FIXME: also add notification job!
+ {
+ struct GNUNET_DB_EventHeaderP es = {
+ .size = htons (sizeof (es)),
+ .type = htons (TALER_DBEVENT_MERCHANT_ACCOUNTS_CHANGED)
+ };
+
+ eh = db_plugin->event_listen (db_plugin->cls,
+ &es,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ &config_changed,
+ NULL);
+ }
{
enum GNUNET_DB_QueryStatus qs;
diff --git a/src/backenddb/Makefile.am b/src/backenddb/Makefile.am
index 189b7a32..020b3f7b 100644
--- a/src/backenddb/Makefile.am
+++ b/src/backenddb/Makefile.am
@@ -54,6 +54,8 @@ libtalermerchantdb_la_LDFLAGS = \
libtaler_plugin_merchantdb_postgres_la_SOURCES = \
pg_update_wirewatch_progress.h pg_update_wirewatch_progress.c \
pg_select_wirewatch_accounts.h pg_select_wirewatch_accounts.c \
+ pg_insert_account.h pg_insert_account.c \
+ pg_update_account.h pg_update_account.c \
pg_lookup_instances.h pg_lookup_instances.c \
pg_lookup_transfers.h pg_lookup_transfers.c \
plugin_merchantdb_postgres.c pg_helper.h
diff --git a/src/backenddb/pg_insert_account.c b/src/backenddb/pg_insert_account.c
new file mode 100644
index 00000000..3b57b0ba
--- /dev/null
+++ b/src/backenddb/pg_insert_account.c
@@ -0,0 +1,68 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022, 2023 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 backenddb/pg_insert_account.c
+ * @brief Implementation of the insert_account function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_insert_account.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TMH_PG_insert_account (
+ void *cls,
+ const char *id,
+ const struct TALER_MERCHANTDB_AccountDetails *account_details)
+{
+ struct PostgresClosure *pg = cls;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (id),
+ GNUNET_PQ_query_param_auto_from_type (&account_details->h_wire),
+ GNUNET_PQ_query_param_auto_from_type (&account_details->salt),
+ GNUNET_PQ_query_param_string (account_details->payto_uri),
+ NULL ==account_details->credit_facade_url
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_string (account_details->credit_facade_url),
+ NULL == account_details->credit_facade_credentials
+ ? GNUNET_PQ_query_param_null ()
+ : TALER_PQ_query_param_json (account_details->credit_facade_credentials),
+ GNUNET_PQ_query_param_bool (account_details->active),
+ GNUNET_PQ_query_param_end
+ };
+
+ check_connection (pg);
+ PREPARE (pg,
+ "insert_account",
+ "INSERT INTO merchant_accounts"
+ "(merchant_serial"
+ ",h_wire"
+ ",salt"
+ ",payto_uri"
+ ",credit_facade_url"
+ ",credit_facade_credentials"
+ ",active)"
+ " SELECT merchant_serial, $2, $3, $4, $5, $6, $7"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_account",
+ params);
+}
diff --git a/src/backenddb/pg_insert_account.h b/src/backenddb/pg_insert_account.h
new file mode 100644
index 00000000..463bc527
--- /dev/null
+++ b/src/backenddb/pg_insert_account.h
@@ -0,0 +1,43 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 backenddb/pg_insert_account.h
+ * @brief implementation of the insert_account function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_INSERT_ACCOUNT_H
+#define PG_INSERT_ACCOUNT_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "taler_merchantdb_plugin.h"
+
+/**
+ * Insert information about an instance's account into our database.
+ *
+ * @param cls closure
+ * @param id identifier of the instance
+ * @param account_details details about the account
+ * @return database result code
+ */
+enum GNUNET_DB_QueryStatus
+TMH_PG_insert_account (
+ void *cls,
+ const char *id,
+ const struct TALER_MERCHANTDB_AccountDetails *account_details);
+
+
+#endif
diff --git a/src/backenddb/pg_update_account.c b/src/backenddb/pg_update_account.c
new file mode 100644
index 00000000..0a95a94c
--- /dev/null
+++ b/src/backenddb/pg_update_account.c
@@ -0,0 +1,64 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2023 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 backenddb/pg_update_account.c
+ * @brief Implementation of the update_account function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_update_account.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TMH_PG_update_account (
+ void *cls,
+ const char *id,
+ const struct TALER_MERCHANTDB_AccountDetails *account_details)
+{
+ struct PostgresClosure *pg = cls;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (id),
+ GNUNET_PQ_query_param_auto_from_type (&account_details->h_wire),
+ NULL ==account_details->credit_facade_url
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_string (account_details->credit_facade_url),
+ NULL == account_details->credit_facade_credentials
+ ? GNUNET_PQ_query_param_null ()
+ : TALER_PQ_query_param_json (account_details->credit_facade_credentials),
+ GNUNET_PQ_query_param_bool (account_details->active),
+ GNUNET_PQ_query_param_end
+ };
+
+ check_connection (pg);
+ PREPARE (pg,
+ "update_account",
+ "UPDATE merchant_accounts SET"
+ " credit_facade_url=$3"
+ ",credit_facade_credentials=$4"
+ ",active=$5"
+ " WHERE h_wire=$2"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "update_account",
+ params);
+}
diff --git a/src/backenddb/pg_update_account.h b/src/backenddb/pg_update_account.h
new file mode 100644
index 00000000..52b476d9
--- /dev/null
+++ b/src/backenddb/pg_update_account.h
@@ -0,0 +1,44 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2023 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 backenddb/pg_update_account.h
+ * @brief implementation of the update_account function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_UPDATE_ACCOUNT_H
+#define PG_UPDATE_ACCOUNT_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "taler_merchantdb_plugin.h"
+
+
+/**
+ * Update information about an instance's account in our database.
+ *
+ * @param cls closure
+ * @param id identifier of the instance
+ * @param account_details details about the account
+ * @return database result code
+ */
+enum GNUNET_DB_QueryStatus
+TMH_PG_update_account (
+ void *cls,
+ const char *id,
+ const struct TALER_MERCHANTDB_AccountDetails *account_details);
+
+
+#endif
diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c
index 19bd022a..e70d8639 100644
--- a/src/backenddb/plugin_merchantdb_postgres.c
+++ b/src/backenddb/plugin_merchantdb_postgres.c
@@ -30,6 +30,8 @@
#include <taler/taler_mhd_lib.h>
#include "taler_merchantdb_plugin.h"
#include "pg_helper.h"
+#include "pg_insert_account.h"
+#include "pg_update_account.h"
#include "pg_lookup_instances.h"
#include "pg_lookup_transfers.h"
#include "pg_update_wirewatch_progress.h"
@@ -410,37 +412,6 @@ postgres_insert_instance (
/**
- * Insert information about an instance's account into our database.
- *
- * @param cls closure
- * @param id identifier of the instance
- * @param account_details details about the account
- * @return database result code
- */
-static enum GNUNET_DB_QueryStatus
-postgres_insert_account (
- void *cls,
- const char *id,
- const struct TALER_MERCHANTDB_AccountDetails *account_details)
-{
- struct PostgresClosure *pg = cls;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (id),
- GNUNET_PQ_query_param_auto_from_type (&account_details->h_wire),
- GNUNET_PQ_query_param_auto_from_type (&account_details->salt),
- GNUNET_PQ_query_param_string (account_details->payto_uri),
- GNUNET_PQ_query_param_bool (account_details->active),
- GNUNET_PQ_query_param_end
- };
-
- check_connection (pg);
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_account",
- params);
-}
-
-
-/**
* Closure for kyc_status_cb().
*/
struct KycStatusContext
@@ -7342,17 +7313,6 @@ postgres_connect (void *cls)
" JOIN merchant_kyc"
" USING (account_serial)"
" WHERE merchant_instances.merchant_id=$1"),
- /* for postgres_insert_account() */
- GNUNET_PQ_make_prepare ("insert_account",
- "INSERT INTO merchant_accounts"
- "(merchant_serial"
- ",h_wire"
- ",salt"
- ",payto_uri"
- ",active)"
- " SELECT merchant_serial, $2, $3, $4, $5"
- " FROM merchant_instances"
- " WHERE merchant_id=$1"),
/* for postgres_delete_instance_private_key() */
GNUNET_PQ_make_prepare ("delete_key",
"DELETE FROM merchant_keys"
@@ -9732,7 +9692,10 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
plugin->commit = &postgres_commit;
plugin->lookup_instance_auth = &postgres_lookup_instance_auth;
plugin->insert_instance = &postgres_insert_instance;
- plugin->insert_account = &postgres_insert_account;
+ plugin->insert_account
+ = &TMH_PG_insert_account;
+ plugin->update_account
+ = &TMH_PG_update_account;
plugin->account_kyc_set_status
= &postgres_account_kyc_set_status;
plugin->account_kyc_get_status
diff --git a/src/backenddb/test_merchantdb.c b/src/backenddb/test_merchantdb.c
index 3d7d6b8c..708d8c01 100644
--- a/src/backenddb/test_merchantdb.c
+++ b/src/backenddb/test_merchantdb.c
@@ -153,6 +153,9 @@ free_instance_data (struct InstanceData *instance)
static void
make_account (struct TALER_MERCHANTDB_AccountDetails *account)
{
+ memset (account,
+ 0,
+ sizeof (*account));
GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_STRONG,
&account->h_wire.hash);
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
diff --git a/src/bank/mb_parse.c b/src/bank/mb_parse.c
index bb668e48..c92dead4 100644
--- a/src/bank/mb_parse.c
+++ b/src/bank/mb_parse.c
@@ -129,6 +129,11 @@ TALER_MERCHANT_BANK_auth_parse_json (
{
const char *method;
+ if (NULL == backend_url)
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
auth->wire_gateway_url = GNUNET_strdup (backend_url);
method = json_string_value (json_object_get (cred,
"type"));
diff --git a/src/include/taler_merchant_service.h b/src/include/taler_merchant_service.h
index 92e18335..723f1b07 100644
--- a/src/include/taler_merchant_service.h
+++ b/src/include/taler_merchant_service.h
@@ -492,6 +492,30 @@ typedef void
/**
+ * Information about an account of the merchant.
+ */
+struct TALER_MERCHANT_AccountConfig
+{
+ /**
+ * Payto URI of the account.
+ */
+ const char *payto_uri;
+
+ /**
+ * Optional credit facade for the account.
+ * Can be NULL.
+ */
+ const char *credit_facade_url;
+
+ /**
+ * Credit facade credentials for the account.
+ * Can be NULL.
+ */
+ json_t *credit_facade_credentials;
+
+};
+
+/**
* Setup an new instance in the backend.
*
* @param ctx the context
@@ -520,7 +544,7 @@ TALER_MERCHANT_instances_post (
const char *backend_url,
const char *instance_id,
unsigned int accounts_length,
- const char *payto_uris[],
+ const struct TALER_MERCHANT_AccountConfig accounts[],
const char *name,
enum TALER_KYCLOGIC_KycUserType ut,
const json_t *address,
@@ -594,7 +618,7 @@ TALER_MERCHANT_instance_patch (
const char *backend_url,
const char *instance_id,
unsigned int accounts_length,
- const char *payto_uris[],
+ const struct TALER_MERCHANT_AccountConfig accounts[],
const char *name,
enum TALER_KYCLOGIC_KycUserType ut,
const json_t *address,
diff --git a/src/include/taler_merchantdb_plugin.h b/src/include/taler_merchantdb_plugin.h
index cffb9acd..f0ae6589 100644
--- a/src/include/taler_merchantdb_plugin.h
+++ b/src/include/taler_merchantdb_plugin.h
@@ -1184,6 +1184,22 @@ struct TALER_MERCHANTDB_Plugin
const char *id,
const struct TALER_MERCHANTDB_AccountDetails *account_details);
+
+ /**
+ * Update information about an instance's account into our database.
+ *
+ * @param cls closure
+ * @param id identifier of the instance
+ * @param account_details details about the account to update
+ * @return database result code
+ */
+ enum GNUNET_DB_QueryStatus
+ (*update_account)(
+ void *cls,
+ const char *id,
+ const struct TALER_MERCHANTDB_AccountDetails *account_details);
+
+
/**
* Delete private key of an instance from our database.
*
diff --git a/src/lib/merchant_api_patch_instance.c b/src/lib/merchant_api_patch_instance.c
index 9d4cea84..240cafd0 100644
--- a/src/lib/merchant_api_patch_instance.c
+++ b/src/lib/merchant_api_patch_instance.c
@@ -159,7 +159,7 @@ TALER_MERCHANT_instance_patch (
const char *backend_url,
const char *instance_id,
unsigned int accounts_length,
- const char *payto_uris[],
+ const struct TALER_MERCHANT_AccountConfig accounts[],
const char *name,
enum TALER_KYCLOGIC_KycUserType ut,
const json_t *address,
@@ -173,7 +173,7 @@ TALER_MERCHANT_instance_patch (
void *cb_cls)
{
struct TALER_MERCHANT_InstancePatchHandle *iph;
- json_t *jpayto_uris;
+ json_t *jaccounts;
json_t *req_obj;
const char *uts;
@@ -183,26 +183,44 @@ TALER_MERCHANT_instance_patch (
GNUNET_break (0);
return NULL;
}
- jpayto_uris = json_array ();
- if (NULL == jpayto_uris)
+ jaccounts = json_array ();
+ if (NULL == jaccounts)
{
GNUNET_break (0);
return NULL;
}
for (unsigned int i = 0; i<accounts_length; i++)
{
+ const struct TALER_MERCHANT_AccountConfig *account = &accounts[i];
+ json_t *jaccount;
+
+ jaccount =
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string (
+ "payto_uri",
+ account->payto_uri),
+ GNUNET_JSON_pack_allow_null (
+ GNUNET_JSON_pack_string (
+ "credit_facade_url",
+ account->credit_facade_url)),
+ GNUNET_JSON_pack_allow_null (
+ GNUNET_JSON_pack_object_incref (
+ "credit_facade_credentials",
+ accounts->credit_facade_credentials))
+ );
+
if (0 !=
- json_array_append_new (jpayto_uris,
- json_string (payto_uris[i])))
+ json_array_append_new (jaccounts,
+ jaccount))
{
GNUNET_break (0);
- json_decref (jpayto_uris);
+ json_decref (jaccounts);
return NULL;
}
}
req_obj = GNUNET_JSON_PACK (
- GNUNET_JSON_pack_array_steal ("payto_uris",
- jpayto_uris),
+ GNUNET_JSON_pack_array_steal ("accounts",
+ jaccounts),
GNUNET_JSON_pack_string ("name",
name),
GNUNET_JSON_pack_string ("user_type",
diff --git a/src/lib/merchant_api_post_instances.c b/src/lib/merchant_api_post_instances.c
index 85069dc3..88ef3a06 100644
--- a/src/lib/merchant_api_post_instances.c
+++ b/src/lib/merchant_api_post_instances.c
@@ -165,7 +165,7 @@ TALER_MERCHANT_instances_post (
const char *backend_url,
const char *instance_id,
unsigned int accounts_length,
- const char *payto_uris[],
+ const struct TALER_MERCHANT_AccountConfig accounts[],
const char *name,
enum TALER_KYCLOGIC_KycUserType ut,
const json_t *address,
@@ -180,7 +180,7 @@ TALER_MERCHANT_instances_post (
void *cb_cls)
{
struct TALER_MERCHANT_InstancesPostHandle *iph;
- json_t *jpayto_uris;
+ json_t *jaccounts;
json_t *req_obj;
json_t *auth_obj;
const char *uts;
@@ -219,8 +219,8 @@ TALER_MERCHANT_instances_post (
GNUNET_break (0);
return NULL;
}
- jpayto_uris = json_array ();
- if (NULL == jpayto_uris)
+ jaccounts = json_array ();
+ if (NULL == jaccounts)
{
json_decref (auth_obj);
GNUNET_break (0);
@@ -228,19 +228,35 @@ TALER_MERCHANT_instances_post (
}
for (unsigned int i = 0; i<accounts_length; i++)
{
+ const struct TALER_MERCHANT_AccountConfig *account = &accounts[i];
+ json_t *jaccount =
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string (
+ "payto_uri",
+ account->payto_uri),
+ GNUNET_JSON_pack_allow_null (
+ GNUNET_JSON_pack_string (
+ "credit_facade_url",
+ account->credit_facade_url)),
+ GNUNET_JSON_pack_allow_null (
+ GNUNET_JSON_pack_object_incref (
+ "credit_facade_credentials",
+ accounts->credit_facade_credentials))
+ );
+
if (0 !=
- json_array_append_new (jpayto_uris,
- json_string (payto_uris[i])))
+ json_array_append_new (jaccounts,
+ jaccount))
{
GNUNET_break (0);
json_decref (auth_obj);
- json_decref (jpayto_uris);
+ json_decref (jaccounts);
return NULL;
}
}
req_obj = GNUNET_JSON_PACK (
- GNUNET_JSON_pack_array_steal ("payto_uris",
- jpayto_uris),
+ GNUNET_JSON_pack_array_steal ("accounts",
+ jaccounts),
GNUNET_JSON_pack_string ("id",
instance_id),
GNUNET_JSON_pack_string ("name",
diff --git a/src/testing/test_key_rotation.sh b/src/testing/test_key_rotation.sh
index 645ceaf2..2cd5569f 100755
--- a/src/testing/test_key_rotation.sh
+++ b/src/testing/test_key_rotation.sh
@@ -190,7 +190,7 @@ echo "OK"
echo -n "Setting up merchant instance"
STATUS=$(curl -H "Content-Type: application/json" -X POST \
http://localhost:9966/management/instances \
- -d '{"auth":{"method":"external"},"payto_uris":["payto://x-taler-bank/localhost/43"],"id":"default","name":"default","user_type":"business","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 3600000000},"default_pay_delay":{"d_us": 3600000000}}' \
+ -d '{"auth":{"method":"external"},"accounts":[{"payto_uri":"payto://x-taler-bank/localhost/43"}],"id":"default","name":"default","user_type":"business","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 3600000000},"default_pay_delay":{"d_us": 3600000000}}' \
-w "%{http_code}" -s -o /dev/null)
if [ "$STATUS" != "204" ]
diff --git a/src/testing/test_merchant_instance_auth.sh b/src/testing/test_merchant_instance_auth.sh
index 4c3bf0a0..16ab1f09 100755
--- a/src/testing/test_merchant_instance_auth.sh
+++ b/src/testing/test_merchant_instance_auth.sh
@@ -30,7 +30,7 @@ echo -n "Configuring 'default' instance ..."
STATUS=$(curl -H "Content-Type: application/json" -X POST \
http://localhost:9966/management/instances \
- -d '{"auth":{"method":"token","token":"secret-token:new_value"},"payto_uris":["payto://x-taler-bank/localhost/43"],"id":"default","name":"default","user_type":"business","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 3600000000},"default_pay_delay":{"d_us": 3600000000}}' \
+ -d '{"auth":{"method":"token","token":"secret-token:new_value"},"accounts":[{"payto_uri":"payto://x-taler-bank/localhost/43"}],"id":"default","name":"default","user_type":"business","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 3600000000},"default_pay_delay":{"d_us": 3600000000}}' \
-w "%{http_code}" -s -o /dev/null)
if [ "$STATUS" != "204" ]
@@ -65,7 +65,7 @@ do
done
if [ "x$OK" != "x1" ]
-then
+then
exit_skip "Failed to start merchant backend"
fi
@@ -97,14 +97,14 @@ fi
PAY_URL=`jq -e -r .taler_pay_uri < $LAST_RESPONSE`
-echo OK order $ORDER_ID with $TOKEN
+echo OK order $ORDER_ID with $TOKEN
echo -n "Configuring 'second' instance ..."
STATUS=$(curl -H "Content-Type: application/json" -X POST \
-H 'Authorization: Bearer '$NEW_SECRET \
http://localhost:9966/management/instances \
- -d '{"auth":{"method":"token","token":"secret-token:second"},"payto_uris":["payto://x-taler-bank/localhost/43"],"id":"second","name":"second","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 3600000000},"default_pay_delay":{"d_us": 3600000000}}' \
+ -d '{"auth":{"method":"token","token":"secret-token:second"},"accounts":[{"payto_uri":"payto://x-taler-bank/localhost/43"}],"id":"second","name":"second","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 3600000000},"default_pay_delay":{"d_us": 3600000000}}' \
-w "%{http_code}" -s -o /dev/null)
if [ "$STATUS" != "204" ]
diff --git a/src/testing/test_merchant_instance_creation.sh b/src/testing/test_merchant_instance_creation.sh
index 27d35365..1fc65ff5 100755
--- a/src/testing/test_merchant_instance_creation.sh
+++ b/src/testing/test_merchant_instance_creation.sh
@@ -24,7 +24,7 @@ echo -n "Configuring a merchant instance before configuring the default instance
STATUS=$(curl -H "Content-Type: application/json" -X POST \
http://localhost:9966/management/instances \
- -d '{"auth":{"method":"token","token":"secret-token:other_secret"},"payto_uris":["payto://x-taler-bank/localhost/43"],"id":"first","name":"test","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 3600000000},"default_pay_delay":{"d_us": 3600000000}}' \
+ -d '{"auth":{"method":"token","token":"secret-token:other_secret"},"accounts":[{"payto_uri":"payto://x-taler-bank/localhost/43"}],"id":"first","name":"test","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 3600000000},"default_pay_delay":{"d_us": 3600000000}}' \
-w "%{http_code}" -s -o /dev/null)
if [ "$STATUS" != "204" ]
@@ -40,7 +40,7 @@ echo -n "Configuring default instance ..."
STATUS=$(curl -H "Content-Type: application/json" -X POST \
-H 'Authorization: Bearer secret-token:super_secret' \
http://localhost:9966/management/instances \
- -d '{"auth":{"method":"external"},"payto_uris":["payto://x-taler-bank/localhost/43"],"id":"default","name":"default","user_type":"business","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 3600000000},"default_pay_delay":{"d_us": 3600000000}}' \
+ -d '{"auth":{"method":"external"},"accounts":[{"payto_uri":"payto://x-taler-bank/localhost/43"}],"id":"default","name":"default","user_type":"business","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 3600000000},"default_pay_delay":{"d_us": 3600000000}}' \
-w "%{http_code}" -s -o /dev/null)
if [ "$STATUS" != "204" ]
@@ -55,7 +55,7 @@ echo -n "Configuring a second merchant instance ..."
STATUS=$(curl -H "Content-Type: application/json" -X POST \
http://localhost:9966/management/instances \
- -d '{"auth":{"method":"token","token":"secret-token:other_secret"},"payto_uris":["payto://x-taler-bank/localhost/43"],"id":"second","name":"test","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 3600000000},"default_pay_delay":{"d_us": 3600000000}}' \
+ -d '{"auth":{"method":"token","token":"secret-token:other_secret"},"accounts":[{"payto_uri":"payto://x-taler-bank/localhost/43"}],"id":"second","name":"test","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 3600000000},"default_pay_delay":{"d_us": 3600000000}}' \
-w "%{http_code}" -s -o /dev/null)
if [ "$STATUS" != "204" ]
diff --git a/src/testing/test_merchant_instance_purge.sh b/src/testing/test_merchant_instance_purge.sh
index 01653415..1c3fab2b 100755
--- a/src/testing/test_merchant_instance_purge.sh
+++ b/src/testing/test_merchant_instance_purge.sh
@@ -24,7 +24,7 @@ echo -n "Configuring default instance ..."
STATUS=$(curl -H "Content-Type: application/json" -X POST \
-H 'Authorization: Bearer secret-token:super_secret' \
http://localhost:9966/management/instances \
- -d '{"auth":{"method":"external"},"payto_uris":["payto://x-taler-bank/localhost/43"],"id":"default","name":"default","user_type":"business","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 3600000000},"default_pay_delay":{"d_us": 3600000000}}' \
+ -d '{"auth":{"method":"external"},"accounts":[{"payto_uri":"payto://x-taler-bank/localhost/43"}],"id":"default","name":"default","user_type":"business","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 3600000000},"default_pay_delay":{"d_us": 3600000000}}' \
-w "%{http_code}" -s -o /dev/null)
if [ "$STATUS" != "204" ]
@@ -39,7 +39,7 @@ echo -n "Configuring merchant instance ..."
STATUS=$(curl -H "Content-Type: application/json" -X POST \
http://localhost:9966/management/instances \
- -d '{"auth":{"method":"token","token":"secret-token:other_secret"},"payto_uris":["payto://x-taler-bank/localhost/43"],"id":"test","name":"test","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 3600000000},"default_pay_delay":{"d_us": 3600000000}}' \
+ -d '{"auth":{"method":"token","token":"secret-token:other_secret"},"accounts":[{"payto_uri":"payto://x-taler-bank/localhost/43"}],"id":"test","name":"test","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 3600000000},"default_pay_delay":{"d_us": 3600000000}}' \
-w "%{http_code}" -s -o /dev/null)
if [ "$STATUS" != "204" ]
diff --git a/src/testing/test_merchant_instance_response.sh b/src/testing/test_merchant_instance_response.sh
index c05b000f..5f175b0b 100755
--- a/src/testing/test_merchant_instance_response.sh
+++ b/src/testing/test_merchant_instance_response.sh
@@ -45,7 +45,7 @@ fi
STATUS=$(curl -H "Content-Type: application/json" -X POST \
-H 'Authorization: Bearer secret-token:super_secret' \
http://localhost:9966/management/instances \
- -d '{"auth":{"method":"token","token":"secret-token:other_secret"},"payto_uris":["payto://x-taler-bank/localhost/43"],"id":"default","name":"default","user_type":"business","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 3600000000},"default_pay_delay":{"d_us": 3600000000}}' \
+ -d '{"auth":{"method":"token","token":"secret-token:other_secret"},"accounts":[{"payto_uri":"payto://x-taler-bank/localhost/43"}],"id":"default","name":"default","user_type":"business","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 3600000000},"default_pay_delay":{"d_us": 3600000000}}' \
-w "%{http_code}" -s -o /dev/null)
if [ "$STATUS" != "204" ]
diff --git a/src/testing/test_merchant_kyc.sh b/src/testing/test_merchant_kyc.sh
index fabcef87..996a8895 100755
--- a/src/testing/test_merchant_kyc.sh
+++ b/src/testing/test_merchant_kyc.sh
@@ -25,7 +25,7 @@ echo -n "Configuring a merchant instance before configuring the default instance
STATUS=$(curl -H "Content-Type: application/json" -X POST \
-H 'Authorization: Bearer secret-token:super_secret' \
http://localhost:9966/management/instances \
- -d '{"auth":{"method":"external"},"payto_uris":["payto://x-taler-bank/localhost:8082/43","payto://x-taler-bank/localhost:8082/44"],"id":"default","name":"default","user_type":"business","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 50000000},"default_pay_delay":{"d_us": 60000000}}' \
+ -d '{"auth":{"method":"external"},"accounts":[{"payto_uri":"payto://x-taler-bank/localhost:8082/43"},{"payto_uri":"payto://x-taler-bank/localhost:8082/44"}],"id":"default","name":"default","user_type":"business","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 50000000},"default_pay_delay":{"d_us": 60000000}}' \
-w "%{http_code}" -s -o /dev/null)
if [ "$STATUS" != "204" ]
diff --git a/src/testing/test_merchant_order_autocleanup.sh b/src/testing/test_merchant_order_autocleanup.sh
index 9d2c9879..c6266a33 100755
--- a/src/testing/test_merchant_order_autocleanup.sh
+++ b/src/testing/test_merchant_order_autocleanup.sh
@@ -28,7 +28,7 @@ echo -n "Configuring merchant instance ..."
STATUS=$(curl -H "Content-Type: application/json" -X POST \
-H 'Authorization: Bearer secret-token:super_secret' \
http://localhost:9966/management/instances \
- -d '{"auth":{"method":"external"},"payto_uris":["payto://x-taler-bank/localhost:8082/43","payto://x-taler-bank/localhost:8082/44"],"id":"default","name":"default","user_type":"business","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 50000000},"default_pay_delay":{"d_us": 60000000}}' \
+ -d '{"auth":{"method":"external"},"accounts":[{"payto_uri":"payto://x-taler-bank/localhost:8082/43"},{"payto_uri":"payto://x-taler-bank/localhost:8082/44"}],"id":"default","name":"default","user_type":"business","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 50000000},"default_pay_delay":{"d_us": 60000000}}' \
-w "%{http_code}" -s -o /dev/null)
if [ "$STATUS" != "204" ]
@@ -41,7 +41,7 @@ fi
STATUS=$(curl -H "Content-Type: application/json" -X PATCH \
-H 'Authorization: Bearer secret-token:super_secret' \
http://localhost:9966/instances/default/private/ \
- -d '{"auth":{"method":"external"},"payto_uris":["payto://x-taler-bank/localhost:8082/43"],"id":"default","name":"default","user_type":"business","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 50000000},"default_pay_delay":{"d_us": 60000000}}' \
+ -d '{"auth":{"method":"external"},"accounts":[{"payto_uri":"payto://x-taler-bank/localhost:8082/43"}],"id":"default","name":"default","user_type":"business","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 50000000},"default_pay_delay":{"d_us": 60000000}}' \
-w "%{http_code}" -s -o /dev/null)
if [ "$STATUS" != "204" ]
diff --git a/src/testing/test_merchant_order_creation.sh b/src/testing/test_merchant_order_creation.sh
index 8226514f..754cdc25 100755
--- a/src/testing/test_merchant_order_creation.sh
+++ b/src/testing/test_merchant_order_creation.sh
@@ -46,7 +46,7 @@ FORTYTHREE=`get_payto_uri fortythree x`
STATUS=$(curl -H "Content-Type: application/json" -X POST \
-H 'Authorization: Bearer secret-token:super_secret' \
http://localhost:9966/management/instances \
- -d '{"auth":{"method":"external"},"payto_uris":["'$FORTYTHREE'","payto://iban/SANDBOXX/DE270744?receiver-name=Forty+Four"],"id":"default","name":"default","user_type":"business","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 50000000000},"default_pay_delay":{"d_us": 60000000000}}' \
+ -d '{"auth":{"method":"external"},"accounts":[{"payto_uri":"'$FORTYTHREE'"},{"payto_uri":"payto://iban/SANDBOXX/DE270744?receiver-name=Forty+Four"}],"id":"default","name":"default","user_type":"business","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 50000000000},"default_pay_delay":{"d_us": 60000000000}}' \
-w "%{http_code}" -s -o /dev/null)
if [ "$STATUS" != "204" ]
@@ -60,7 +60,7 @@ fi
STATUS=$(curl -H "Content-Type: application/json" -X PATCH \
-H 'Authorization: Bearer secret-token:super_secret' \
http://localhost:9966/instances/default/private/ \
- -d '{"auth":{"method":"external"},"payto_uris":["'$FORTYTHREE'"],"id":"default","name":"default","user_type":"business","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 50000000000},"default_pay_delay":{"d_us": 60000000000}}' \
+ -d '{"auth":{"method":"external"},"accounts":[{"payto_uri":"'$FORTYTHREE'"}],"id":"default","name":"default","user_type":"business","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 50000000000},"default_pay_delay":{"d_us": 60000000000}}' \
-w "%{http_code}" -s -o /dev/null)
if [ "$STATUS" != "204" ]
diff --git a/src/testing/test_merchant_product_creation.sh b/src/testing/test_merchant_product_creation.sh
index a69fed3e..738b7d5e 100755
--- a/src/testing/test_merchant_product_creation.sh
+++ b/src/testing/test_merchant_product_creation.sh
@@ -24,7 +24,7 @@ echo -n "Configuring merchant instance ..."
STATUS=$(curl -H "Content-Type: application/json" -X POST \
-H 'Authorization: Bearer secret-token:super_secret' \
http://localhost:9966/management/instances \
- -d '{"auth":{"method":"external"},"payto_uris":["'$FORTYTHREE'"],"id":"default","name":"default","user_type":"business","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 50000000},"default_pay_delay":{"d_us": 60000000}}' \
+ -d '{"auth":{"method":"external"},"accounts":[{"payto_uri":"'$FORTYTHREE'"}],"id":"default","name":"default","user_type":"business","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 50000000},"default_pay_delay":{"d_us": 60000000}}' \
-w "%{http_code}" -s -o /dev/null)
if [ "$STATUS" != "204" ]
diff --git a/src/testing/test_merchant_reserve_creation.sh b/src/testing/test_merchant_reserve_creation.sh
index 58b6611a..cf231dd5 100755
--- a/src/testing/test_merchant_reserve_creation.sh
+++ b/src/testing/test_merchant_reserve_creation.sh
@@ -28,7 +28,7 @@ FORTYTHREE=`get_payto_uri fortythree x`
STATUS=$(curl -H "Content-Type: application/json" -X POST \
-H 'Authorization: Bearer secret-token:super_secret' \
http://localhost:9966/management/instances \
- -d '{"auth":{"method":"external"},"payto_uris":["payto://x-taler-bank/localhost:1'$NEXUS_PORT'/43"],"id":"default","name":"default","user_type":"business","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 50000000},"default_pay_delay":{"d_us": 60000000}}' \
+ -d '{"auth":{"method":"external"},"accounts":[{"payto_uri":"payto://x-taler-bank/localhost:1'$NEXUS_PORT'/43"}],"id":"default","name":"default","user_type":"business","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 50000000},"default_pay_delay":{"d_us": 60000000}}' \
-w "%{http_code}" -s -o /dev/null)
if [ "$STATUS" != "204" ]
diff --git a/src/testing/test_merchant_transfer_tracking.sh b/src/testing/test_merchant_transfer_tracking.sh
index 5205a495..91832e52 100755
--- a/src/testing/test_merchant_transfer_tracking.sh
+++ b/src/testing/test_merchant_transfer_tracking.sh
@@ -47,7 +47,7 @@ GNUNET_PAYTO=`get_payto_uri gnunet x`
STATUS=$(curl -H "Content-Type: application/json" -X POST \
-H 'Authorization: Bearer secret-token:super_secret' \
http://localhost:9966/management/instances \
- -d '{"auth":{"method":"external"},"payto_uris":["'$TOR_PAYTO'","'$GNUNET_PAYTO'"],"id":"default","name":"default","user_type":"business","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 50000000},"default_pay_delay":{"d_us": 60000000}}' \
+ -d '{"auth":{"method":"external"},"accounts":[{"payto_uri":"'$TOR_PAYTO'"},{"payto_uri":"'$GNUNET_PAYTO'"}],"id":"default","name":"default","user_type":"business","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 50000000},"default_pay_delay":{"d_us": 60000000}}' \
-w "%{http_code}" -s -o /dev/null)
if [ "$STATUS" != "204" ]
@@ -67,7 +67,7 @@ TUTORIAL_PAYTO=`get_payto_uri tutorial x`
STATUS=$(curl -H "Content-Type: application/json" -X POST \
-H 'Authorization: Bearer secret-token:super_secret' \
http://localhost:9966/management/instances \
- -d '{"auth":{"method":"external"},"payto_uris":["'$SURVEY_PAYTO'","'$TUTORIAL_PAYTO'"],"id":"test","name":"default","user_type":"business","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 50000000},"default_pay_delay":{"d_us": 60000000}}' \
+ -d '{"auth":{"method":"external"},"accounts":[{"payto_uri":"'$SURVEY_PAYTO'"},{"payto_uri":"'$TUTORIAL_PAYTO'"}],"id":"test","name":"default","user_type":"business","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 50000000},"default_pay_delay":{"d_us": 60000000}}' \
-w "%{http_code}" -s -o /dev/null)
if [ "$STATUS" != "204" ]
diff --git a/src/testing/test_merchant_wirewatch.sh b/src/testing/test_merchant_wirewatch.sh
index a7508110..1c078291 100755
--- a/src/testing/test_merchant_wirewatch.sh
+++ b/src/testing/test_merchant_wirewatch.sh
@@ -158,7 +158,7 @@ GNUNET_PAYTO=$(get_payto_uri gnunet x)
STATUS=$(curl -H "Content-Type: application/json" -X POST \
-H 'Authorization: Bearer secret-token:super_secret' \
http://localhost:9966/management/instances \
- -d '{"auth":{"method":"external"},"payto_uris":["'"$GNUNET_PAYTO"'"],"id":"default","name":"default","user_type":"business","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 50000000},"default_pay_delay":{"d_us": 60000000}}' \
+ -d '{"auth":{"method":"external"},"accounts":[{"payto_uri":"'"$GNUNET_PAYTO"'"}],"id":"default","name":"default","user_type":"business","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_us" : 50000000},"default_pay_delay":{"d_us": 60000000}}' \
-w "%{http_code}" -s -o /dev/null)
if [ "$STATUS" != "204" ]
diff --git a/src/testing/testing_api_cmd_patch_instance.c b/src/testing/testing_api_cmd_patch_instance.c
index 4ea0fba1..7ff966e0 100644
--- a/src/testing/testing_api_cmd_patch_instance.c
+++ b/src/testing/testing_api_cmd_patch_instance.c
@@ -171,13 +171,20 @@ patch_instance_run (void *cls,
struct TALER_TESTING_Interpreter *is)
{
struct PatchInstanceState *pis = cls;
-
+ struct TALER_MERCHANT_AccountConfig accounts[GNUNET_NZL (
+ pis->payto_uris_length)];
+
+ memset (accounts,
+ 0,
+ sizeof (accounts));
+ for (unsigned int i = 0; i<pis->payto_uris_length; i++)
+ accounts[i].payto_uri = pis->payto_uris[i];
pis->is = is;
pis->iph = TALER_MERCHANT_instance_patch (is->ctx,
pis->merchant_url,
pis->instance_id,
pis->payto_uris_length,
- pis->payto_uris,
+ accounts,
pis->name,
TALER_KYCLOGIC_KYC_UT_BUSINESS,
pis->address,
diff --git a/src/testing/testing_api_cmd_post_instances.c b/src/testing/testing_api_cmd_post_instances.c
index 61e54e53..4938f6c0 100644
--- a/src/testing/testing_api_cmd_post_instances.c
+++ b/src/testing/testing_api_cmd_post_instances.c
@@ -178,13 +178,20 @@ post_instances_run (void *cls,
struct TALER_TESTING_Interpreter *is)
{
struct PostInstancesState *pis = cls;
-
+ struct TALER_MERCHANT_AccountConfig accounts[GNUNET_NZL (
+ pis->payto_uris_length)];
+
+ memset (accounts,
+ 0,
+ sizeof (accounts));
+ for (unsigned int i = 0; i<pis->payto_uris_length; i++)
+ accounts[i].payto_uri = pis->payto_uris[i];
pis->is = is;
pis->iph = TALER_MERCHANT_instances_post (is->ctx,
pis->merchant_url,
pis->instance_id,
pis->payto_uris_length,
- pis->payto_uris,
+ accounts,
pis->name,
TALER_KYCLOGIC_KYC_UT_BUSINESS,
pis->address,