summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2023-01-31 15:37:53 +0100
committerChristian Grothoff <christian@grothoff.org>2023-01-31 15:37:53 +0100
commit9adfbe7a25478348c01d2e6cbc051bc6cd6f3001 (patch)
tree36de1b70a93c878ead3a2ea0aef745993cf89689 /src
parent0107fd64aad2dcbf5497e2b6ef751eb8ec95b934 (diff)
parent3645e148dd673d0f5b72226a9d9a6310cbe21be0 (diff)
downloadmerchant-9adfbe7a25478348c01d2e6cbc051bc6cd6f3001.tar.gz
merchant-9adfbe7a25478348c01d2e6cbc051bc6cd6f3001.tar.bz2
merchant-9adfbe7a25478348c01d2e6cbc051bc6cd6f3001.zip
Merge branch 'master' of git+ssh://git.taler.net/merchant
Diffstat (limited to 'src')
-rw-r--r--src/backend/taler-merchant-httpd_helper.c16
-rw-r--r--src/backend/taler-merchant-webhook.c107
-rw-r--r--src/backenddb/plugin_merchantdb_postgres.c6
-rw-r--r--src/backenddb/test.conf172
-rw-r--r--src/include/taler_merchantdb_plugin.h13
5 files changed, 280 insertions, 34 deletions
diff --git a/src/backend/taler-merchant-httpd_helper.c b/src/backend/taler-merchant-httpd_helper.c
index 2cffa20c..b875f6f3 100644
--- a/src/backend/taler-merchant-httpd_helper.c
+++ b/src/backend/taler-merchant-httpd_helper.c
@@ -20,11 +20,12 @@
*/
#include "platform.h"
#include <gnunet/gnunet_util_lib.h>
+#include <gnunet/gnunet_db_lib.h>
#include <taler/taler_util.h>
#include <taler/taler_json_lib.h>
#include "taler-merchant-httpd_helper.h"
#include <taler/taler_templating_lib.h>
-
+#include <taler/taler_dbevents.h>
/**
* check @a payto_uris for well-formedness
@@ -587,6 +588,19 @@ trigger_webhook_cb (void *cls,
http_method,
header,
body);
+ if (t->rv > 0)
+ {
+ struct GNUNET_DB_EventHeaderP es = {
+ .size = htons (sizeof(es)),
+ .type = htons (TALER_DBEVENT_MERCHANT_WEBHOOK_PENDING)
+ };
+ const void *extra = NULL;
+ size_t extra_size = 0;
+ TMH_db->event_notify (TMH_db->cls,
+ &es,
+ &extra,
+ extra_size);
+ }
free (header);
free (body);
}
diff --git a/src/backend/taler-merchant-webhook.c b/src/backend/taler-merchant-webhook.c
index a1a31558..1d258a18 100644
--- a/src/backend/taler-merchant-webhook.c
+++ b/src/backend/taler-merchant-webhook.c
@@ -16,7 +16,7 @@
/**
* @file taler-merchant-webhook.c
* @brief Process that runs webhooks triggered by the merchant backend
- * @author Christian Grothoff
+ * @author Priscilla HUANG
*/
#include "platform.h"
#include <gnunet/gnunet_util_lib.h>
@@ -24,6 +24,7 @@
#include <pthread.h>
#include "taler_merchantdb_lib.h"
#include "taler_merchantdb_plugin.h"
+#include <taler/taler_dbevents.h>
struct WorkResponse
@@ -31,7 +32,7 @@ struct WorkResponse
struct WorkResponse *next;
struct WorkResponse *prev;
struct GNUNET_CURL_Job *job;
- uint64_t webhook_serial;
+ uint64_t webhook_pending_serial;
char *body;
struct curl_slist *job_headers;
};
@@ -41,6 +42,8 @@ static struct WorkResponse *w_head;
static struct WorkResponse *w_tail;
+static struct GNUNET_DB_EventHandler *eh;
+
/**
* The exchange's configuration.
*/
@@ -90,6 +93,11 @@ shutdown_task (void *cls)
(void) cls;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Running shutdown\n");
+ if (NULL != eh)
+ {
+ db_plugin->event_listen_cancel (eh);
+ eh = NULL;
+ }
if (NULL != task)
{
GNUNET_SCHEDULER_cancel (task);
@@ -153,18 +161,30 @@ handle_webhook_response (void *cls,
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Webhook %llu returned with status %ld\n",
- (unsigned long long) w->webhook_serial,
+ (unsigned long long) w->webhook_pending_serial,
response_code);
if (2 == response_code / 100) /* any 2xx http status code is OK! */
{
- db_plugin->delete_pending_webhook (db_plugin->cls,
- w->webhook_serial);
+ enum GNUNET_DB_QueryStatus qs;
+
+ qs = db_plugin->delete_pending_webhook (db_plugin->cls,
+ w->webhook_pending_serial);
+
+ if ((GNUNET_DB_STATUS_HARD_ERROR == qs) ||(GNUNET_DB_STATUS_SOFT_ERROR==qs))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed!\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Delete returned: %d\n",
+ qs);
+ global_ret = EXIT_FAILURE;
+ GNUNET_SCHEDULER_shutdown ();
+ }
}
else
{
struct GNUNET_TIME_Relative next_attempt;
enum GNUNET_DB_QueryStatus qs;
-
switch (response_code)
{
case MHD_HTTP_BAD_REQUEST:
@@ -181,12 +201,19 @@ handle_webhook_response (void *cls,
break;
}
qs = db_plugin->update_pending_webhook (db_plugin->cls,
- w->webhook_serial,
+ w->webhook_pending_serial,
GNUNET_TIME_relative_to_absolute (next_attempt));
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Next in %s Rval: %d\n",
- GNUNET_TIME_relative2s (next_attempt, true),
- qs);
+ if ((GNUNET_DB_STATUS_HARD_ERROR == qs) ||(GNUNET_DB_STATUS_SOFT_ERROR==qs))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed!\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Next in %s Rval: %d\n",
+ GNUNET_TIME_relative2s (next_attempt, true),
+ qs);
+ global_ret = EXIT_FAILURE;
+ GNUNET_SCHEDULER_shutdown ();
+ }
}
GNUNET_CONTAINER_DLL_remove (w_head,
w_tail,
@@ -204,7 +231,7 @@ handle_webhook_response (void *cls,
* Typically called by `select_work`.
*
* @param cls a `json_t *` JSON array to build
- * @param webhook_serial reference to the configured webhook template.
+ * @param webhook_pending_serial reference to the configured webhook template.
* @param next_attempt is the time we should make the next request to the webhook.
* @param retries how often have we tried this request to the webhook.
* @param url to make request to
@@ -214,7 +241,7 @@ handle_webhook_response (void *cls,
*/
static void
pending_webhooks_cb (void *cls,
- uint64_t webhook_serial,
+ uint64_t webhook_pending_serial,
struct GNUNET_TIME_Absolute next_attempt,
uint32_t retries,
const char *url,
@@ -232,7 +259,7 @@ pending_webhooks_cb (void *cls,
GNUNET_CONTAINER_DLL_insert (w_head,
w_tail,
w);
- w->webhook_serial = webhook_serial;
+ w->webhook_pending_serial = webhook_pending_serial;
eh = curl_easy_init ();
GNUNET_assert (NULL != eh);
GNUNET_assert (CURLE_OK ==
@@ -246,7 +273,7 @@ pending_webhooks_cb (void *cls,
GNUNET_assert (CURLE_OK ==
curl_easy_setopt (eh,
CURLOPT_VERBOSE,
- 1L));
+ 0L));
/* conversion body data */
if (NULL != body)
@@ -263,8 +290,8 @@ pending_webhooks_cb (void *cls,
char *header_copy = GNUNET_strdup (header);
for (const char *tok = strtok (header_copy, "\n");
- tok = strtok (NULL, "\n");
- NULL != tok)
+ NULL != tok;
+ tok = strtok (NULL, "\n"))
{
// extract all Key: value from 'header_copy'!
job_headers = curl_slist_append (job_headers,
@@ -294,8 +321,8 @@ pending_webhooks_cb (void *cls,
if (NULL == w->job)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to start the curl job for webhook #%llu\n",
- (unsigned long long) webhook_serial);
+ "Failed to start the curl job for pending webhook #%llu\n",
+ (unsigned long long) webhook_pending_serial);
curl_slist_free_all (w->job_headers);
GNUNET_free (w->body);
GNUNET_CONTAINER_DLL_remove (w_head,
@@ -308,13 +335,34 @@ pending_webhooks_cb (void *cls,
}
+/**
+ * Function called on events received from Postgres.
+ *
+ * @param cls closure, NULL
+ * @param extra additional event data provided
+ * @param extra_size number of bytes in @a extra
+ */
+static void
+db_notify (void *cls,
+ const void *extra,
+ size_t extra_size)
+{
+ (void) cls;
+ (void) extra;
+ (void) extra_size;
+
+ GNUNET_assert (NULL != task);
+ GNUNET_SCHEDULER_cancel (task);
+ task = GNUNET_SCHEDULER_add_now (&select_work,
+ NULL);
+}
/**
* Typically called by `select_work`.
*
* @param cls a `json_t *` JSON array to build
- * @param webhook_serial reference to the configured webhook template.
+ * @param webhook_pending_serial reference to the configured webhook template.
* @param next_attempt is the time we should make the next request to the webhook.
* @param retries how often have we tried this request to the webhook.
* @param url to make request to
@@ -324,7 +372,7 @@ pending_webhooks_cb (void *cls,
*/
static void
future_webhook_cb (void *cls,
- uint64_t webhook_serial,
+ uint64_t webhook_pending_serial,
struct GNUNET_TIME_Absolute next_attempt,
uint32_t retries,
const char *url,
@@ -332,7 +380,7 @@ future_webhook_cb (void *cls,
const char *header,
const char *body)
{
- (void) webhook_serial;
+ (void) webhook_pending_serial;
(void) retries;
(void) url;
(void) http_method;
@@ -345,6 +393,8 @@ future_webhook_cb (void *cls,
}
+
+
static void
select_work (void *cls)
{
@@ -388,6 +438,19 @@ select_work (void *cls)
case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
/* wait 5 min */
rel = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5);
+ if (NULL == eh)
+ {
+ struct GNUNET_DB_EventHeaderP es = {
+ .size = htons (sizeof (es)),
+ .type = htons (TALER_DBEVENT_MERCHANT_WEBHOOK_PENDING)
+ };
+
+ eh = db_plugin->event_listen (db_plugin->cls,
+ &es,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ &db_notify,
+ NULL);
+ }
task = GNUNET_SCHEDULER_add_delayed (rel,
&select_work,
NULL);
diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c
index 798cc48d..373ffa97 100644
--- a/src/backenddb/plugin_merchantdb_postgres.c
+++ b/src/backenddb/plugin_merchantdb_postgres.c
@@ -7503,7 +7503,7 @@ postgres_lookup_webhook_by_event (void *cls,
static enum GNUNET_DB_QueryStatus
postgres_insert_pending_webhook (void *cls,
const char *instance_id,
- uint64_t webhook_pending_serial,
+ uint64_t webhook_serial,
const char *url,
const char *http_method,
const char *header,
@@ -7512,7 +7512,7 @@ postgres_insert_pending_webhook (void *cls,
struct PostgresClosure *pg = cls;
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_string (instance_id),
- GNUNET_PQ_query_param_uint64 (&webhook_pending_serial),
+ GNUNET_PQ_query_param_uint64 (&webhook_serial),
GNUNET_PQ_query_param_string (url),
GNUNET_PQ_query_param_string (http_method),
NULL == header
@@ -10447,7 +10447,7 @@ postgres_connect (void *cls)
GNUNET_PQ_make_prepare ("insert_pending_webhook",
"INSERT INTO merchant_pending_webhooks"
"(merchant_serial"
- ",webhook_pending_serial"
+ ",webhook_serial"
",url"
",http_method"
",header"
diff --git a/src/backenddb/test.conf b/src/backenddb/test.conf
new file mode 100644
index 00000000..502d807a
--- /dev/null
+++ b/src/backenddb/test.conf
@@ -0,0 +1,172 @@
+# This file is in the public domain.
+#
+[PATHS]
+# Persistent data storage for the testcase
+TALER_TEST_HOME = test_merchant_api_home/
+TALER_RUNTIME_DIR = ${TMPDIR:-${TMP:-/tmp}}/${USER:-}/taler-system-runtime/
+
+# Persistent data storage
+TALER_DATA_HOME = $TALER_HOME/.local/share/taler/
+
+# Configuration files
+TALER_CONFIG_HOME = $TALER_HOME/.config/taler/
+
+# Cached data, no big deal if lost
+TALER_CACHE_HOME = $TALER_HOME/.cache/taler/
+
+[taler]
+# What currency do we use?
+CURRENCY = EUR
+CURRENCY_ROUND_UNIT = EUR:0.01
+
+[taler-helper-crypto-rsa]
+# Reduce from 1 year to speed up test
+LOOKAHEAD_SIGN = 24 days
+
+[taler-helper-crypto-eddsa]
+# Reduce from 1 year to speed up test
+LOOKAHEAD_SIGN = 24 days
+# Reduce from 12 weeks to ensure we have multiple
+DURATION = 14 days
+
+[bank]
+HTTP_PORT = 8082
+
+##########################################
+# Configuration for the merchant backend #
+##########################################
+
+[merchant]
+
+# Which port do we run the backend on? (HTTP server)
+PORT = 8080
+
+# Which plugin (backend) do we use for the DB.
+DB = postgres
+
+# This specifies which database the postgres backend uses.
+[merchantdb-postgres]
+CONFIG = postgres:///talercheck
+
+# Sections starting with "merchant-exchange-" specify trusted exchanges
+# (by the merchant)
+[merchant-exchange-test]
+MASTER_KEY = T1VVFQZZARQ1CMF4BN58EE7SKTW5AV2BS18S87ZEGYS4S29J6DNG
+EXCHANGE_BASE_URL = http://localhost:8081/
+CURRENCY = EUR
+
+
+#######################################################
+# Configuration for the auditor for the testcase
+#######################################################
+[auditor]
+BASE_URL = http://the.auditor/
+
+
+#######################################################
+# Configuration for ??? Is this used?
+#######################################################
+
+# Auditors must be in sections "auditor-", the rest of the section
+# name could be anything.
+[auditor-ezb]
+# Informal name of the auditor. Just for the user.
+NAME = European Central Bank
+
+# URL of the auditor (especially for in the future, when the
+# auditor offers an automated issue reporting system).
+# Not really used today.
+URL = http://taler.ezb.eu/
+
+# This is the important bit: the signing key of the auditor.
+PUBLIC_KEY = 9QXF7XY7E9VPV47B5Z806NDFSX2VJ79SVHHD29QEQ3BG31ANHZ60
+
+# Which currency is this auditor trusted for?
+CURRENCY = EUR
+
+
+###################################################
+# Configuration for the exchange for the testcase #
+###################################################
+
+[exchange]
+# How to access our database
+DB = postgres
+
+# HTTP port the exchange listens to
+PORT = 8081
+
+# Our public key
+MASTER_PUBLIC_KEY = T1VVFQZZARQ1CMF4BN58EE7SKTW5AV2BS18S87ZEGYS4S29J6DNG
+
+# Base URL of the exchange.
+BASE_URL = "http://localhost:8081/"
+
+
+[exchangedb-postgres]
+CONFIG = "postgres:///talercheck"
+
+
+[auditordb-postgres]
+CONFIG = postgres:///talercheck
+
+
+# Account of the EXCHANGE
+[exchange-account-exchange]
+# What is the exchange's bank account (with the "Taler Bank" demo system)?
+PAYTO_URI = "payto://x-taler-bank/localhost/2?receiver-name=2"
+ENABLE_DEBIT = YES
+ENABLE_CREDIT = YES
+
+[exchange-accountcredentials-exchange]
+WIRE_GATEWAY_URL = "http://localhost:8082/2/"
+WIRE_GATEWAY_AUTH_METHOD = NONE
+
+
+[coin_eur_ct_1]
+value = EUR:0.01
+duration_withdraw = 7 days
+duration_spend = 2 years
+duration_legal = 3 years
+fee_withdraw = EUR:0.00
+fee_deposit = EUR:0.00
+fee_refresh = EUR:0.01
+fee_refund = EUR:0.01
+rsa_keysize = 1024
+CIPHER = CS
+
+[coin_eur_ct_10]
+value = EUR:0.10
+duration_withdraw = 7 days
+duration_spend = 2 years
+duration_legal = 3 years
+fee_withdraw = EUR:0.01
+fee_deposit = EUR:0.01
+fee_refresh = EUR:0.03
+fee_refund = EUR:0.01
+rsa_keysize = 1024
+CIPHER = CS
+
+[coin_eur_1]
+value = EUR:1
+duration_withdraw = 7 days
+duration_spend = 2 years
+duration_legal = 3 years
+fee_withdraw = EUR:0.01
+fee_deposit = EUR:0.01
+fee_refresh = EUR:0.03
+fee_refund = EUR:0.01
+rsa_keysize = 1024
+CIPHER = CS
+
+[coin_eur_5]
+value = EUR:5
+duration_withdraw = 7 days
+duration_spend = 2 years
+duration_legal = 3 years
+fee_withdraw = EUR:0.01
+fee_deposit = EUR:0.01
+fee_refresh = EUR:0.03
+fee_refund = EUR:0.01
+rsa_keysize = 1024
+CIPHER = CS
diff --git a/src/include/taler_merchantdb_plugin.h b/src/include/taler_merchantdb_plugin.h
index d9fe0d24..fe974ba4 100644
--- a/src/include/taler_merchantdb_plugin.h
+++ b/src/include/taler_merchantdb_plugin.h
@@ -409,7 +409,7 @@ typedef void
* Typically called by `lookup_pending_webhooks`.
*
* @param cls a `json_t *` JSON array to build
- * @param webhook_serial reference to the configured webhook template.
+ * @param webhook_pending_serial reference to the configured webhook template.
* @param next_attempt is the time we should make the next request to the webhook.
* @param retries how often have we tried this request to the webhook.
* @param url to make request to
@@ -419,9 +419,8 @@ typedef void
*/
typedef void
(*TALER_MERCHANTDB_PendingWebhooksCallback)(void *cls,
- uint64_t webhook_serial,
- struct GNUNET_TIME_Absolute
- next_attempt,
+ uint64_t webhook_pending_serial,
+ struct GNUNET_TIME_Absolute next_attempt,
uint32_t retries,
const char *url,
const char *http_method,
@@ -455,13 +454,11 @@ struct TALER_MERCHANTDB_PendingWebhookDetails
*/
char *http_method;
-
/**
* Header of the webhook.
*/
char *header;
-
/**
* Body of the webhook.
*/
@@ -2827,7 +2824,7 @@ struct TALER_MERCHANTDB_Plugin
*/
enum GNUNET_DB_QueryStatus
(*update_pending_webhook)(void *cls,
- uint64_t webhook_serial,
+ uint64_t webhook_pending_serial,
struct GNUNET_TIME_Absolute next_attempt);
// maybe add: http status of failure?
@@ -2842,7 +2839,7 @@ struct TALER_MERCHANTDB_Plugin
*/
enum GNUNET_DB_QueryStatus
(*delete_pending_webhook)(void *cls,
- uint64_t webhook_serial);
+ uint64_t webhook_pending_serial);
};