summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2020-04-11 18:38:55 +0200
committerChristian Grothoff <christian@grothoff.org>2020-04-11 18:38:55 +0200
commit6ff02bc7ea9ca1b39cebf7ac381dfce46f267627 (patch)
treef4bfc429206aa95c05fe3ef4b8cb638c4895e9f8
parent19c56c7eb81efc272d864d6765d7d61943141ce2 (diff)
downloadmerchant-6ff02bc7ea9ca1b39cebf7ac381dfce46f267627.tar.gz
merchant-6ff02bc7ea9ca1b39cebf7ac381dfce46f267627.tar.bz2
merchant-6ff02bc7ea9ca1b39cebf7ac381dfce46f267627.zip
finish #4939 implementation: allow client to indicate preference for payment target
-rw-r--r--src/backend/taler-merchant-httpd.c30
-rw-r--r--src/backend/taler-merchant-httpd.h29
-rw-r--r--src/backend/taler-merchant-httpd_order.c163
3 files changed, 122 insertions, 100 deletions
diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c
index b86fde71..6c7eaf5e 100644
--- a/src/backend/taler-merchant-httpd.c
+++ b/src/backend/taler-merchant-httpd.c
@@ -56,6 +56,34 @@
*/
#define UNIX_BACKLOG 500
+
+/**
+ * Used by the iterator of the various merchant's instances given
+ * in configuration
+ */
+struct IterateInstancesCls
+{
+
+ /**
+ * Current index in the global array of #MerchantInstance
+ * types. Used by the callback in order to know which index
+ * is associated to the element being processed.
+ */
+ unsigned int current_index;
+
+ /**
+ * Flag indicating whether config contains a default instance
+ */
+ unsigned int default_instance;
+
+ /**
+ * Tells if the parsing encountered any error. We need this
+ * field since the iterator must return void
+ */
+ unsigned int ret;
+};
+
+
/**
* Hashmap pointing at merchant instances by 'id'. An 'id' is
* just a string that identifies a merchant instance. When a frontend
@@ -982,7 +1010,6 @@ wireformat_iterator_cb (void *cls,
return;
}
-
wm = GNUNET_new (struct WireMethod);
wm->wire_method = TALER_payto_get_method (payto);
GNUNET_free (payto);
@@ -1001,7 +1028,6 @@ wireformat_iterator_cb (void *cls,
GNUNET_CONTAINER_DLL_insert_tail (mi->wm_head,
mi->wm_tail,
wm);
-
wm->j_wire = j;
wm->h_wire = jh_wire;
}
diff --git a/src/backend/taler-merchant-httpd.h b/src/backend/taler-merchant-httpd.h
index ad83a669..28a0f2ea 100644
--- a/src/backend/taler-merchant-httpd.h
+++ b/src/backend/taler-merchant-httpd.h
@@ -37,33 +37,6 @@
/**
- * Used by the iterator of the various merchant's instances given
- * in configuration
- */
-struct IterateInstancesCls
-{
-
- /**
- * Current index in the global array of #MerchantInstance
- * types. Used by the callback in order to know which index
- * is associated to the element being processed.
- */
- unsigned int current_index;
-
- /**
- * Flag indicating whether config contains a default instance
- */
- unsigned int default_instance;
-
- /**
- * Tells if the parsing encountered any error. We need this
- * field since the iterator must return void
- */
- unsigned int ret;
-};
-
-
-/**
* Supported wire method. Kept in a DLL.
*/
struct WireMethod
@@ -79,7 +52,7 @@ struct WireMethod
struct WireMethod *prev;
/**
- * Which wire method is @e j_wire using? Points into @e j_wire.
+ * Which wire method / payment target identifier is @e j_wire using?
*/
char *wire_method;
diff --git a/src/backend/taler-merchant-httpd_order.c b/src/backend/taler-merchant-httpd_order.c
index 1cf34632..317e451b 100644
--- a/src/backend/taler-merchant-httpd_order.c
+++ b/src/backend/taler-merchant-httpd_order.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- (C) 2014, 2015, 2016, 2018 Taler Systems SA
+ (C) 2014, 2015, 2016, 2018, 2020 Taler Systems SA
TALER is free software; you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
@@ -144,8 +144,8 @@ json_parse_cleanup (struct TM_HandlerContext *hc)
* @returns the merchant instance's base URL
*/
static char *
-make_merchant_base_url (struct MHD_Connection *connection, const
- char *instance_id)
+make_merchant_base_url (struct MHD_Connection *connection,
+ const char *instance_id)
{
const char *host;
const char *forwarded_host;
@@ -210,7 +210,6 @@ proposal_put (struct MHD_Connection *connection,
json_t *order,
const struct MerchantInstance *mi)
{
- enum GNUNET_GenericReturnValue res;
struct TALER_Amount total;
const char *order_id;
const char *summary;
@@ -455,22 +454,25 @@ proposal_put (struct MHD_Connection *connection,
} /* needed to synthesize merchant info */
/* extract fields we need to sign separately */
- res = TALER_MHD_parse_json_data (connection,
- order,
- spec);
- /* json is malformed */
- if (GNUNET_NO == res)
{
- return MHD_YES;
- }
- /* other internal errors might have occurred */
- if (GNUNET_SYSERR == res)
- {
- return TALER_MHD_reply_with_error
- (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_PROPOSAL_ORDER_PARSE_ERROR,
- "Impossible to parse the order");
+ enum GNUNET_GenericReturnValue res;
+
+ res = TALER_MHD_parse_json_data (connection,
+ order,
+ spec);
+ /* json is malformed */
+ if (GNUNET_NO == res)
+ {
+ return MHD_YES;
+ }
+ /* other internal errors might have occurred */
+ if (GNUNET_SYSERR == res)
+ {
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_PROPOSAL_ORDER_PARSE_ERROR,
+ "Impossible to parse the order");
+ }
}
if (0 !=
strcasecmp (total.currency,
@@ -509,11 +511,10 @@ proposal_put (struct MHD_Connection *connection,
if (GNUNET_OK != check_products (products))
{
GNUNET_JSON_parse_free (spec);
- return TALER_MHD_reply_with_error
- (connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_PARAMETER_MALFORMED,
- "order:products");
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_PARAMETER_MALFORMED,
+ "order:products");
}
/* add fields to the contract that the backend should provide */
@@ -524,14 +525,30 @@ proposal_put (struct MHD_Connection *connection,
json_object_set (order,
"auditors",
j_auditors);
- /* TODO (#4939-12806): add proper mechanism for
- selection of wire method(s) by merchant! */
- wm = mi->wm_head;
+ {
+ const char *target;
+
+ target = MHD_lookup_connection_value (connection,
+ MHD_GET_ARGUMENT_KIND,
+ "payment_target");
+ wm = mi->wm_head;
+ if (NULL != target)
+ {
+ while ( (NULL != wm) &&
+ (GNUNET_YES == wm->active) &&
+ (0 != strcasecmp (target,
+ wm->wire_method) ) )
+ wm = wm->next;
+ }
+ if (GNUNET_YES != wm->active)
+ wm = NULL;
+ }
if (NULL == wm)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "No wire method available for instance '%s'\n", mi->id);
+ "No wire method available for instance '%s'\n",
+ mi->id);
GNUNET_JSON_parse_free (spec);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_NOT_FOUND,
@@ -570,12 +587,11 @@ proposal_put (struct MHD_Connection *connection,
if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
{
GNUNET_break (0);
- return TALER_MHD_reply_with_error
- (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_PROPOSAL_STORE_DB_ERROR_SOFT,
- "db error: could not check for existing order"
- " due to repeated soft transaction failure");
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_PROPOSAL_STORE_DB_ERROR_SOFT,
+ "db error: could not check for existing order"
+ " due to repeated soft transaction failure");
}
{
@@ -604,22 +620,20 @@ proposal_put (struct MHD_Connection *connection,
js = json_dumps (contract_terms,
JSON_COMPACT);
- GNUNET_log
- (GNUNET_ERROR_TYPE_ERROR,
- _ ("Order ID `%s' already exists with proposal `%s'\n"),
- order_id,
- js);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _ ("Order ID `%s' already exists with proposal `%s'\n"),
+ order_id,
+ js);
free (js);
}
json_decref (contract_terms);
/* contract_terms may be private, only expose
* duplicate order_id to the network */
- rv = TALER_MHD_reply_with_error
- (connection,
- MHD_HTTP_BAD_REQUEST, /* or conflict? */
- TALER_EC_PROPOSAL_STORE_DB_ERROR_ALREADY_EXISTS,
- msg);
+ rv = TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_BAD_REQUEST, /* or conflict? */
+ TALER_EC_PROPOSAL_STORE_DB_ERROR_ALREADY_EXISTS,
+ msg);
GNUNET_free (msg);
return rv;
}
@@ -635,13 +649,17 @@ proposal_put (struct MHD_Connection *connection,
}
/* DB transaction succeeded, generate positive response */
- res = TALER_MHD_reply_json_pack (connection,
- MHD_HTTP_OK,
- "{s:s}",
- "order_id",
- order_id);
- GNUNET_JSON_parse_free (spec);
- return res;
+ {
+ MHD_RESULT ret;
+
+ ret = TALER_MHD_reply_json_pack (connection,
+ MHD_HTTP_OK,
+ "{s:s}",
+ "order_id",
+ order_id);
+ GNUNET_JSON_parse_free (spec);
+ return ret;
+ }
}
@@ -668,7 +686,6 @@ MH_handler_order_post (struct TMH_RequestHandler *rh,
size_t *upload_data_size,
struct MerchantInstance *mi)
{
- int res;
struct TMH_JsonParseContext *ctx;
json_t *root;
json_t *order;
@@ -684,20 +701,24 @@ MH_handler_order_post (struct TMH_RequestHandler *rh,
ctx = *connection_cls;
}
- res = TALER_MHD_parse_post_json (connection,
- &ctx->json_parse_context,
- upload_data,
- upload_data_size,
- &root);
+ {
+ int res;
- if (GNUNET_SYSERR == res)
- return MHD_NO;
+ res = TALER_MHD_parse_post_json (connection,
+ &ctx->json_parse_context,
+ upload_data,
+ upload_data_size,
+ &root);
- /* A error response was already generated */
- if ( (GNUNET_NO == res) ||
- /* or, need more data to accomplish parsing */
- (NULL == root) )
- return MHD_YES;
+ if (GNUNET_SYSERR == res)
+ return MHD_NO;
+
+ /* A error response was already generated */
+ if ( (GNUNET_NO == res) ||
+ /* or, need more data to accomplish parsing */
+ (NULL == root) )
+ return MHD_YES;
+ }
order = json_object_get (root,
"order");
{
@@ -705,15 +726,17 @@ MH_handler_order_post (struct TMH_RequestHandler *rh,
if (NULL == order)
{
- ret = TALER_MHD_reply_with_error
- (connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_PARAMETER_MISSING,
- "order");
+ ret = TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_PARAMETER_MISSING,
+ "order");
}
else
{
- ret = proposal_put (connection, root, order, mi);
+ ret = proposal_put (connection,
+ root,
+ order,
+ mi);
}
json_decref (root);
return ret;