commit dcbac9e63f37f9a5dd8b47a2cfc068d73068d4fc
parent 6ca84e4121cf4bd1b8c66d2ef4bd58eeb7003ea3
Author: Christian Grothoff <christian@grothoff.org>
Date: Sun, 26 Apr 2020 12:04:24 +0200
fix fTBFS
Diffstat:
12 files changed, 797 insertions(+), 794 deletions(-)
diff --git a/src/include/taler_merchant_service.h b/src/include/taler_merchant_service.h
@@ -1104,7 +1104,7 @@ TALER_MERCHANT_product_delete_cancel (
/**
* Handle to a POST /orders operation
*/
-struct TALER_MERCHANT_PostOrderOperation;
+struct TALER_MERCHANT_PostOrdersOperation;
/**
* Callbacks of this type are used to serve the result of submitting a
@@ -1115,7 +1115,7 @@ struct TALER_MERCHANT_PostOrderOperation;
* @param order_id order id of the newly created order
*/
typedef void
-(*TALER_MERCHANT_PostOrderCallback) (
+(*TALER_MERCHANT_PostOrdersCallback) (
void *cls,
const struct TALER_MERCHANT_HttpResponse *hr,
const char *order_id);
@@ -1132,12 +1132,14 @@ typedef void
* @param cb_cls closure for @a cb
* @return a handle for this request, NULL on error
*/
-struct TALER_MERCHANT_PostOrderOperation *
-TALER_MERCHANT_order_post (struct GNUNET_CURL_Context *ctx,
- const char *backend_url,
- const json_t *order,
- TALER_MERCHANT_PostOrderCallback cb,
- void *cb_cls);
+struct TALER_MERCHANT_PostOrdersOperation *
+TALER_MERCHANT_orders_post (struct GNUNET_CURL_Context *ctx,
+ const char *backend_url,
+ const json_t *order,
+ TALER_MERCHANT_PostOrdersCallback cb,
+ void *cb_cls);
+
+// TODO: implement orders_post2 with the OPTIONAL arguments!
/**
@@ -1147,7 +1149,8 @@ TALER_MERCHANT_order_post (struct GNUNET_CURL_Context *ctx,
* @param po the proposal operation request handle
*/
void
-TALER_MERCHANT_order_post_cancel (struct TALER_MERCHANT_PostOrderOperation *po);
+TALER_MERCHANT_orders_post_cancel (
+ struct TALER_MERCHANT_PostOrdersOperation *po);
/**
diff --git a/src/include/taler_merchant_testing_lib.h b/src/include/taler_merchant_testing_lib.h
@@ -407,8 +407,6 @@ TALER_TESTING_cmd_merchant_delete_product (const char *label,
unsigned int http_status);
-/* ******************** OLD ******************* */
-
/**
* Make the "proposal" command.
*
@@ -421,10 +419,14 @@ TALER_TESTING_cmd_merchant_delete_product (const char *label,
* @return the command
*/
struct TALER_TESTING_Command
-TALER_TESTING_cmd_proposal (const char *label,
- const char *merchant_url,
- unsigned int http_status,
- const char *order);
+TALER_TESTING_cmd_merchant_post_orders (const char *label,
+ const char *merchant_url,
+ unsigned int http_status,
+ const char *order);
+
+
+/* ******************** OLD ******************* */
+
/**
* Make a "proposal lookup" command.
@@ -439,11 +441,11 @@ TALER_TESTING_cmd_proposal (const char *label,
* @return the command.
*/
struct TALER_TESTING_Command
-TALER_TESTING_cmd_proposal_lookup (const char *label,
- const char *merchant_url,
- unsigned int http_status,
- const char *proposal_reference,
- const char *order_id);
+TALER_TESTING_cmd_merchant_post_orders_lookup (const char *label,
+ const char *merchant_url,
+ unsigned int http_status,
+ const char *proposal_reference,
+ const char *order_id);
/**
* Make a "check payment" test command.
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
@@ -27,9 +27,9 @@ libtalermerchant_la_SOURCES = \
merchant_api_patch_product.c \
merchant_api_post_instances.c \
merchant_api_post_products.c \
+ merchant_api_post_orders.c \
merchant_api_check_payment.c \
merchant_api_history.c \
- merchant_api_proposal.c \
merchant_api_proposal_lookup.c \
merchant_api_pay.c \
merchant_api_poll_payment.c \
diff --git a/src/lib/merchant_api_post_orders.c b/src/lib/merchant_api_post_orders.c
@@ -0,0 +1,245 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2014-2020 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 Foundation; either version 2.1,
+ 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with TALER; see the file COPYING.LGPL. If not,
+ see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file lib/merchant_api_post_orders.c
+ * @brief Implementation of the POST /orders
+ * @author Christian Grothoff
+ * @author Marcello Stanisci
+ */
+#include "platform.h"
+#include <curl/curl.h>
+#include <jansson.h>
+#include <microhttpd.h> /* just for HTTP status codes */
+#include <gnunet/gnunet_util_lib.h>
+#include <gnunet/gnunet_curl_lib.h>
+#include "taler_merchant_service.h"
+#include <taler/taler_json_lib.h>
+#include <taler/taler_signatures.h>
+#include <taler/taler_curl_lib.h>
+
+
+/**
+ * @brief A POST /orders Handle
+ */
+struct TALER_MERCHANT_PostOrdersOperation
+{
+
+ /**
+ * The url for this request.
+ */
+ char *url;
+
+ /**
+ * Handle for the request.
+ */
+ struct GNUNET_CURL_Job *job;
+
+ /**
+ * Function to call with the result.
+ */
+ TALER_MERCHANT_PostOrdersCallback cb;
+
+ /**
+ * Closure for @a cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Reference to the execution context.
+ */
+ struct GNUNET_CURL_Context *ctx;
+
+ /**
+ * Minor context that holds body and headers.
+ */
+ struct TALER_CURL_PostContext post_ctx;
+};
+
+
+/**
+ * Function called when we're done processing the
+ * HTTP POST /orders request.
+ *
+ * @param cls the `struct TALER_MERCHANT_PostOrdersOperation`
+ * @param response_code HTTP response code, 0 on error
+ * @param json response body, NULL if not JSON
+ */
+static void
+handle_post_order_finished (void *cls,
+ long response_code,
+ const void *response)
+{
+ struct TALER_MERCHANT_PostOrdersOperation *po = cls;
+ const char *order_id = NULL;
+ const json_t *json = response;
+ struct TALER_MERCHANT_HttpResponse hr = {
+ .http_status = (unsigned int) response_code,
+ .reply = json
+ };
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_string ("order_id",
+ &order_id),
+ GNUNET_JSON_spec_end ()
+ };
+
+ po->job = NULL;
+ switch (response_code)
+ {
+ case 0:
+ hr.ec = TALER_EC_INVALID_RESPONSE;
+ break;
+ case MHD_HTTP_OK:
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (json,
+ spec,
+ NULL, NULL))
+ {
+ GNUNET_break_op (0);
+ hr.http_status = 0;
+ hr.ec = TALER_EC_PROPOSAL_REPLY_MALFORMED;
+ }
+ break;
+ case MHD_HTTP_BAD_REQUEST:
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
+ /* This should never happen, either us or
+ the merchant is buggy (or API version conflict);
+ just pass JSON reply to the application */
+ break;
+ case MHD_HTTP_CONFLICT:
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
+ break;
+ case MHD_HTTP_FORBIDDEN:
+ /* Nothing really to verify, merchant says one
+ of the signatures is invalid; as we checked them,
+ this should never happen, we should pass the JSON
+ reply to the application */
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
+ break;
+ case MHD_HTTP_NOT_FOUND:
+ /* Nothing really to verify, this should never
+ happen, we should pass the JSON reply to the application */
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
+ break;
+ case MHD_HTTP_INTERNAL_SERVER_ERROR:
+ /* Server had an internal issue; we should retry,
+ but this API leaves this to the application */
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
+ break;
+ default:
+ /* unexpected response code */
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unexpected response code %u/%d\n",
+ (unsigned int) response_code,
+ (int) hr.ec);
+ GNUNET_break_op (0);
+ break;
+ }
+ po->cb (po->cb_cls,
+ &hr,
+ order_id);
+ if (MHD_HTTP_OK == response_code)
+ GNUNET_JSON_parse_free (spec);
+ TALER_MERCHANT_orders_post_cancel (po);
+}
+
+
+/**
+ * POST an order to the backend and receives the related proposal.
+ *
+ * @param ctx execution context
+ * @param backend_url URL of the backend
+ * @param order basic information about this purchase,
+ * to be extended by the backend
+ * @param cb the callback to call when a reply
+ * for this request is available
+ * @param cb_cls closure for @a proposal_cb
+ * @return a handle for this request, NULL on error
+ */
+struct TALER_MERCHANT_PostOrdersOperation *
+TALER_MERCHANT_orders_post (struct GNUNET_CURL_Context *ctx,
+ const char *backend_url,
+ const json_t *order,
+ TALER_MERCHANT_PostOrdersCallback cb,
+ void *cb_cls)
+{
+ struct TALER_MERCHANT_PostOrdersOperation *po;
+ json_t *req;
+ CURL *eh;
+
+ po = GNUNET_new (struct TALER_MERCHANT_PostOrdersOperation);
+ po->ctx = ctx;
+ po->cb = cb;
+ po->cb_cls = cb_cls;
+ po->url = TALER_url_join (backend_url, "orders", NULL);
+ req = json_pack ("{s:O}",
+ "order", (json_t *) order);
+ eh = curl_easy_init ();
+ if (GNUNET_OK != TALER_curl_easy_post (&po->post_ctx,
+ eh,
+ req))
+ {
+ GNUNET_break (0);
+ json_decref (req);
+ GNUNET_free (po);
+ return NULL;
+ }
+ json_decref (req);
+
+ GNUNET_assert (CURLE_OK ==
+ curl_easy_setopt (eh,
+ CURLOPT_URL,
+ po->url));
+ po->job = GNUNET_CURL_job_add2 (ctx,
+ eh,
+ po->post_ctx.headers,
+ &handle_post_order_finished,
+ po);
+ return po;
+}
+
+
+/**
+ * Cancel a POST /proposal request. This function cannot be used
+ * on a request handle if a response is already served for it.
+ *
+ * @param po the proposal operation request handle
+ */
+void
+TALER_MERCHANT_orders_post_cancel (
+ struct TALER_MERCHANT_PostOrdersOperation *po)
+{
+ if (NULL != po->job)
+ {
+ GNUNET_CURL_job_cancel (po->job);
+ po->job = NULL;
+ }
+ GNUNET_free (po->url);
+ TALER_curl_easy_post_finished (&po->post_ctx);
+ GNUNET_free (po);
+}
+
+
+/* end of merchant_api_post_orders.c */
diff --git a/src/lib/merchant_api_proposal.c b/src/lib/merchant_api_proposal.c
@@ -1,244 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014-2020 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 Foundation; either version 2.1,
- 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 Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with TALER; see the file COPYING.LGPL. If not,
- see <http://www.gnu.org/licenses/>
-*/
-/**
- * @file lib/merchant_api_proposal.c
- * @brief Implementation of the /proposal POST
- * @author Christian Grothoff
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include <curl/curl.h>
-#include <jansson.h>
-#include <microhttpd.h> /* just for HTTP status codes */
-#include <gnunet/gnunet_util_lib.h>
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_merchant_service.h"
-#include <taler/taler_json_lib.h>
-#include <taler/taler_signatures.h>
-#include <taler/taler_curl_lib.h>
-
-
-/**
- * @brief A Contract Operation Handle
- */
-struct TALER_MERCHANT_ProposalOperation
-{
-
- /**
- * The url for this request.
- */
- char *url;
-
- /**
- * Handle for the request.
- */
- struct GNUNET_CURL_Job *job;
-
- /**
- * Function to call with the result.
- */
- TALER_MERCHANT_ProposalCallback cb;
-
- /**
- * Closure for @a cb.
- */
- void *cb_cls;
-
- /**
- * Reference to the execution context.
- */
- struct GNUNET_CURL_Context *ctx;
-
- /**
- * Minor context that holds body and headers.
- */
- struct TALER_CURL_PostContext post_ctx;
-};
-
-
-/**
- * Function called when we're done processing the
- * HTTP POST /proposal request.
- *
- * @param cls the `struct TALER_MERCHANT_ProposalOperation`
- * @param response_code HTTP response code, 0 on error
- * @param json response body, NULL if not JSON
- */
-static void
-handle_proposal_finished (void *cls,
- long response_code,
- const void *response)
-{
- struct TALER_MERCHANT_ProposalOperation *po = cls;
- const char *order_id = NULL;
- const json_t *json = response;
- struct TALER_MERCHANT_HttpResponse hr = {
- .http_status = (unsigned int) response_code,
- .reply = json
- };
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_string ("order_id",
- &order_id),
- GNUNET_JSON_spec_end ()
- };
-
- po->job = NULL;
- switch (response_code)
- {
- case 0:
- hr.ec = TALER_EC_INVALID_RESPONSE;
- break;
- case MHD_HTTP_OK:
- if (GNUNET_OK !=
- GNUNET_JSON_parse (json,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- hr.http_status = 0;
- hr.ec = TALER_EC_PROPOSAL_REPLY_MALFORMED;
- }
- break;
- case MHD_HTTP_BAD_REQUEST:
- hr.ec = TALER_JSON_get_error_code (json);
- hr.hint = TALER_JSON_get_error_hint (json);
- /* This should never happen, either us or
- the merchant is buggy (or API version conflict);
- just pass JSON reply to the application */
- break;
- case MHD_HTTP_CONFLICT:
- hr.ec = TALER_JSON_get_error_code (json);
- hr.hint = TALER_JSON_get_error_hint (json);
- break;
- case MHD_HTTP_FORBIDDEN:
- /* Nothing really to verify, merchant says one
- of the signatures is invalid; as we checked them,
- this should never happen, we should pass the JSON
- reply to the application */
- hr.ec = TALER_JSON_get_error_code (json);
- hr.hint = TALER_JSON_get_error_hint (json);
- break;
- case MHD_HTTP_NOT_FOUND:
- /* Nothing really to verify, this should never
- happen, we should pass the JSON reply to the application */
- hr.ec = TALER_JSON_get_error_code (json);
- hr.hint = TALER_JSON_get_error_hint (json);
- break;
- case MHD_HTTP_INTERNAL_SERVER_ERROR:
- /* Server had an internal issue; we should retry,
- but this API leaves this to the application */
- hr.ec = TALER_JSON_get_error_code (json);
- hr.hint = TALER_JSON_get_error_hint (json);
- break;
- default:
- /* unexpected response code */
- hr.ec = TALER_JSON_get_error_code (json);
- hr.hint = TALER_JSON_get_error_hint (json);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u/%d\n",
- (unsigned int) response_code,
- (int) hr.ec);
- GNUNET_break_op (0);
- break;
- }
- po->cb (po->cb_cls,
- &hr,
- order_id);
- if (MHD_HTTP_OK == response_code)
- GNUNET_JSON_parse_free (spec);
- TALER_MERCHANT_proposal_cancel (po);
-}
-
-
-/**
- * POST an order to the backend and receives the related proposal.
- *
- * @param ctx execution context
- * @param backend_url URL of the backend
- * @param order basic information about this purchase,
- * to be extended by the backend
- * @param proposal_cb the callback to call when a reply
- * for this request is available
- * @param proposal_cb_cls closure for @a proposal_cb
- * @return a handle for this request, NULL on error
- */
-struct TALER_MERCHANT_ProposalOperation *
-TALER_MERCHANT_order_put (struct GNUNET_CURL_Context *ctx,
- const char *backend_url,
- const json_t *order,
- TALER_MERCHANT_ProposalCallback proposal_cb,
- void *proposal_cb_cls)
-{
- struct TALER_MERCHANT_ProposalOperation *po;
- json_t *req;
- CURL *eh;
-
- po = GNUNET_new (struct TALER_MERCHANT_ProposalOperation);
- po->ctx = ctx;
- po->cb = proposal_cb;
- po->cb_cls = proposal_cb_cls;
- po->url = TALER_url_join (backend_url, "order", NULL);
- req = json_pack ("{s:O}",
- "order", (json_t *) order);
- eh = curl_easy_init ();
- if (GNUNET_OK != TALER_curl_easy_post (&po->post_ctx,
- eh,
- req))
- {
- GNUNET_break (0);
- json_decref (req);
- GNUNET_free (po);
- return NULL;
- }
- json_decref (req);
-
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_URL,
- po->url));
- po->job = GNUNET_CURL_job_add2 (ctx,
- eh,
- po->post_ctx.headers,
- &handle_proposal_finished,
- po);
- return po;
-}
-
-
-/**
- * Cancel a POST /proposal request. This function cannot be used
- * on a request handle if a response is already served for it.
- *
- * @param po the proposal operation request handle
- */
-void
-TALER_MERCHANT_proposal_cancel (struct TALER_MERCHANT_ProposalOperation *po)
-{
- if (NULL != po->job)
- {
- GNUNET_CURL_job_cancel (po->job);
- po->job = NULL;
- }
- GNUNET_free (po->url);
- TALER_curl_easy_post_finished (&po->post_ctx);
- GNUNET_free (po);
-}
-
-
-/* end of merchant_api_proposal.c */
diff --git a/src/merchant-tools/taler-merchant-benchmark.c b/src/merchant-tools/taler-merchant-benchmark.c
@@ -344,10 +344,10 @@ run (void *cls,
"create-reserve-1",
CURRENCY_5,
MHD_HTTP_OK),
- TALER_TESTING_cmd_proposal ("create-proposal-1",
- merchant_url,
- MHD_HTTP_OK,
- order_worth_5),
+ TALER_TESTING_cmd_merchant_post_orders ("create-proposal-1",
+ merchant_url,
+ MHD_HTTP_OK,
+ order_worth_5),
TALER_TESTING_cmd_pay ("deposit-simple",
merchant_url,
MHD_HTTP_OK,
@@ -362,10 +362,10 @@ run (void *cls,
/* Next proposal-pay cycle will be used by /track CMDs
* and so it will not have to be looped over, only /track
* CMDs will have to. */
- TALER_TESTING_cmd_proposal ("create-proposal-2",
- merchant_url,
- MHD_HTTP_OK,
- order_worth_5_track),
+ TALER_TESTING_cmd_merchant_post_orders ("create-proposal-2",
+ merchant_url,
+ MHD_HTTP_OK,
+ order_worth_5_track),
TALER_TESTING_cmd_pay ("deposit-simple-2",
merchant_url,
MHD_HTTP_OK,
@@ -410,7 +410,7 @@ run (void *cls,
CURRENCY_5,
MHD_HTTP_OK),
- TALER_TESTING_cmd_proposal
+ TALER_TESTING_cmd_merchant_post_orders
("create-unaggregated-proposal",
alt_instance_url,
MHD_HTTP_OK,
@@ -453,7 +453,7 @@ run (void *cls,
CURRENCY_5,
MHD_HTTP_OK),
- TALER_TESTING_cmd_proposal
+ TALER_TESTING_cmd_merchant_post_orders
("create-twocoins-proposal",
merchant_url,
MHD_HTTP_OK,
diff --git a/src/testing/Makefile.am b/src/testing/Makefile.am
@@ -24,6 +24,7 @@ libtalermerchanttesting_la_SOURCES = \
testing_api_cmd_lock_product.c \
testing_api_cmd_post_instances.c \
testing_api_cmd_post_products.c \
+ testing_api_cmd_post_orders.c \
testing_api_cmd_patch_instance.c \
testing_api_cmd_patch_product.c \
\
@@ -33,7 +34,6 @@ libtalermerchanttesting_la_SOURCES = \
testing_api_cmd_pay_abort.c \
testing_api_cmd_pay_abort_refund.c \
testing_api_cmd_poll_payment.c \
- testing_api_cmd_proposal.c \
testing_api_cmd_proposal_lookup.c \
testing_api_cmd_refund_increase.c \
testing_api_cmd_refund_lookup.c \
diff --git a/src/testing/test_merchant_api.c b/src/testing/test_merchant_api.c
@@ -261,10 +261,10 @@ run (void *cls,
"create-reserve-1",
"EUR:0",
MHD_HTTP_OK),
- TALER_TESTING_cmd_proposal ("create-proposal-1",
- merchant_url,
- MHD_HTTP_OK,
- "{\"max_fee\":\"EUR:0.5\",\
+ TALER_TESTING_cmd_merchant_post_orders ("create-proposal-1",
+ merchant_url,
+ MHD_HTTP_OK,
+ "{\"max_fee\":\"EUR:0.5\",\
\"order_id\":\"1\",\
\"refund_deadline\": {\"t_ms\": 0},\
\"pay_deadline\": {\"t_ms\": \"never\" },\
@@ -336,10 +336,10 @@ run (void *cls,
};
struct TALER_TESTING_Command double_spending[] = {
- TALER_TESTING_cmd_proposal ("create-proposal-2",
- merchant_url,
- MHD_HTTP_OK,
- "{\"max_fee\":\"EUR:0.5\",\
+ TALER_TESTING_cmd_merchant_post_orders ("create-proposal-2",
+ merchant_url,
+ MHD_HTTP_OK,
+ "{\"max_fee\":\"EUR:0.5\",\
\"order_id\":\"2\",\
\"refund_deadline\": {\"t_ms\": 0},\
\"pay_deadline\": {\"t_ms\": \"never\" },\
@@ -348,11 +348,11 @@ run (void *cls,
\"fulfillment_url\": \"https://example.com/\",\
\"products\": [ {\"description\":\"ice cream\",\
\"value\":\"{EUR:5}\"} ] }"),
- TALER_TESTING_cmd_proposal_lookup ("fetch-proposal-2",
- merchant_url,
- MHD_HTTP_OK,
- "create-proposal-2",
- NULL),
+ TALER_TESTING_cmd_merchant_post_orders_lookup ("fetch-proposal-2",
+ merchant_url,
+ MHD_HTTP_OK,
+ "create-proposal-2",
+ NULL),
TALER_TESTING_cmd_pay ("deposit-double-2",
merchant_url,
MHD_HTTP_CONFLICT,
@@ -481,10 +481,10 @@ run (void *cls,
"create-reserve-1r",
"EUR:0",
MHD_HTTP_OK),
- TALER_TESTING_cmd_proposal ("create-proposal-1r",
- merchant_url,
- MHD_HTTP_OK,
- "{\"max_fee\":\"EUR:0.5\",\
+ TALER_TESTING_cmd_merchant_post_orders ("create-proposal-1r",
+ merchant_url,
+ MHD_HTTP_OK,
+ "{\"max_fee\":\"EUR:0.5\",\
\"order_id\":\"1r\",\
\"refund_deadline\": {\"t_ms\": 0},\
\"pay_deadline\": {\"t_ms\": \"never\" },\
@@ -533,10 +533,10 @@ run (void *cls,
MHD_HTTP_NOT_FOUND),
/* Test /refund on a contract that was never paid. */
- TALER_TESTING_cmd_proposal ("create-proposal-not-to-be-paid",
- merchant_url,
- MHD_HTTP_OK,
- "{\"max_fee\":\"EUR:0.5\",\
+ TALER_TESTING_cmd_merchant_post_orders ("create-proposal-not-to-be-paid",
+ merchant_url,
+ MHD_HTTP_OK,
+ "{\"max_fee\":\"EUR:0.5\",\
\"order_id\":\"1-unpaid\",\
\"refund_deadline\":{\"t_ms\":0},\
\"pay_deadline\":{\"t_ms\":99999999999},\
@@ -581,10 +581,11 @@ run (void *cls,
"create-reserve-unincreased-refund",
"EUR:5",
MHD_HTTP_OK),
- TALER_TESTING_cmd_proposal ("create-proposal-unincreased-refund",
- merchant_url,
- MHD_HTTP_OK,
- "{\"max_fee\":\"EUR:0.5\",\
+ TALER_TESTING_cmd_merchant_post_orders (
+ "create-proposal-unincreased-refund",
+ merchant_url,
+ MHD_HTTP_OK,
+ "{\"max_fee\":\"EUR:0.5\",\
\"order_id\":\"unincreased-proposal\",\
\"refund_deadline\":{\"t_ms\":0},\
\"pay_deadline\":{\"t_ms\":\"never\"},\
@@ -745,10 +746,10 @@ run (void *cls,
"fake-tip-authorization",
pickup_amounts_1,
TALER_EC_TIP_PICKUP_TIP_ID_UNKNOWN),
- TALER_TESTING_cmd_proposal ("create-proposal-tip-1",
- merchant_url_internal ("tip"),
- MHD_HTTP_OK,
- "{\"max_fee\":\"EUR:0.5\",\
+ TALER_TESTING_cmd_merchant_post_orders ("create-proposal-tip-1",
+ merchant_url_internal ("tip"),
+ MHD_HTTP_OK,
+ "{\"max_fee\":\"EUR:0.5\",\
\"order_id\":\"1-tip\", \
\"refund_deadline\":{\"t_ms\":0},\
\"pay_deadline\":{\"t_ms\":99999999999999},\
@@ -796,10 +797,10 @@ run (void *cls,
"create-reserve-10",
"EUR:0",
MHD_HTTP_OK),
- TALER_TESTING_cmd_proposal ("create-proposal-10",
- merchant_url,
- MHD_HTTP_OK,
- "{\"max_fee\":\"EUR:0.5\",\
+ TALER_TESTING_cmd_merchant_post_orders ("create-proposal-10",
+ merchant_url,
+ MHD_HTTP_OK,
+ "{\"max_fee\":\"EUR:0.5\",\
\"order_id\":\"10\",\
\"refund_deadline\":{\"t_ms\":0},\
\"pay_deadline\":{\"t_ms\":99999999999999},\
@@ -853,10 +854,10 @@ run (void *cls,
"create-reserve-11",
"EUR:0",
MHD_HTTP_OK),
- TALER_TESTING_cmd_proposal ("create-proposal-11",
- merchant_url,
- MHD_HTTP_OK,
- "{\"max_fee\":\"EUR:0.5\",\
+ TALER_TESTING_cmd_merchant_post_orders ("create-proposal-11",
+ merchant_url,
+ MHD_HTTP_OK,
+ "{\"max_fee\":\"EUR:0.5\",\
\"order_id\":\"11\",\
\"refund_deadline\":{\"t_ms\":0},\
\"pay_deadline\":{\"t_ms\":99999999999999},\
diff --git a/src/testing/test_merchant_api_twisted.c b/src/testing/test_merchant_api_twisted.c
@@ -216,10 +216,10 @@ run (void *cls,
"5719-create-reserve",
"EUR:0",
MHD_HTTP_OK),
- TALER_TESTING_cmd_proposal ("5719-create-proposal",
- twister_merchant_url,
- MHD_HTTP_OK,
- "{\"max_fee\":\"EUR:0.5\",\
+ TALER_TESTING_cmd_merchant_post_orders ("5719-create-proposal",
+ twister_merchant_url,
+ MHD_HTTP_OK,
+ "{\"max_fee\":\"EUR:0.5\",\
\"order_id\":\"5719TRIGGER\",\
\"refund_deadline\":{\"t_ms\":0},\
\"pay_deadline\":{\"t_ms\":\"never\"},\
@@ -253,7 +253,7 @@ run (void *cls,
/**** Covering /check-payment ****/
struct TALER_TESTING_Command check_payment[] = {
- TALER_TESTING_cmd_proposal
+ TALER_TESTING_cmd_merchant_post_orders
("proposal-for-check-payment",
twister_merchant_url,
MHD_HTTP_OK,
@@ -305,23 +305,23 @@ run (void *cls,
*/
TALER_TESTING_cmd_malform_request ("malform-order",
PROXY_MERCHANT_CONFIG_FILE),
- TALER_TESTING_cmd_proposal ("create-proposal-0",
- twister_merchant_url,
- MHD_HTTP_BAD_REQUEST,
- /* giving a valid JSON to not make it fail before
- * data reaches the merchant. */
- "{\"not\": \"used\"}"),
+ TALER_TESTING_cmd_merchant_post_orders ("create-proposal-0",
+ twister_merchant_url,
+ MHD_HTTP_BAD_REQUEST,
+ /* giving a valid JSON to not make it fail before
+ * data reaches the merchant. */
+ "{\"not\": \"used\"}"),
TALER_TESTING_cmd_hack_response_code ("proposal-500",
PROXY_MERCHANT_CONFIG_FILE,
MHD_HTTP_INTERNAL_SERVER_ERROR),
- TALER_TESTING_cmd_proposal ("create-proposal-1",
- twister_merchant_url,
- /* This status code == 0 is gotten via a 500 Internal Server
- * Error handed to the library. */
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- /* giving a valid JSON to not make it fail before
- * data reaches the merchant. */
- "{\"not\": \"used\"}"),
+ TALER_TESTING_cmd_merchant_post_orders ("create-proposal-1",
+ twister_merchant_url,
+ /* This status code == 0 is gotten via a 500 Internal Server
+ * Error handed to the library. */
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ /* giving a valid JSON to not make it fail before
+ * data reaches the merchant. */
+ "{\"not\": \"used\"}"),
/**
* Cause the PUT /proposal callback to be called
@@ -331,10 +331,10 @@ run (void *cls,
TALER_TESTING_cmd_malform_response ("malform-proposal",
PROXY_MERCHANT_CONFIG_FILE),
- TALER_TESTING_cmd_proposal ("create-proposal-2",
- twister_merchant_url,
- 0,
- "{\"max_fee\":\"EUR:0.5\",\
+ TALER_TESTING_cmd_merchant_post_orders ("create-proposal-2",
+ twister_merchant_url,
+ 0,
+ "{\"max_fee\":\"EUR:0.5\",\
\"order_id\":\"1\",\
\"refund_deadline\":{\"t_ms\":0},\
\"pay_deadline\":{\"t_ms\":\"never\"},\
@@ -349,10 +349,10 @@ run (void *cls,
TALER_TESTING_cmd_delete_object ("remove-order-id",
PROXY_MERCHANT_CONFIG_FILE,
"order_id"),
- TALER_TESTING_cmd_proposal ("create-proposal-3",
- twister_merchant_url,
- 0,
- "{\"max_fee\":\"EUR:0.5\",\
+ TALER_TESTING_cmd_merchant_post_orders ("create-proposal-3",
+ twister_merchant_url,
+ 0,
+ "{\"max_fee\":\"EUR:0.5\",\
\"fulfillment_url\": \"https://example.com/\",\
\"order_id\":\"2\",\
\"refund_deadline\":{\"t_ms\":0},\
@@ -365,31 +365,31 @@ run (void *cls,
* Cause a 404 Not Found response code,
* due to a non existing merchant instance.
*/
- TALER_TESTING_cmd_proposal ("create-proposal-4",
- twister_merchant_url_instance_nonexistent,
- MHD_HTTP_NOT_FOUND,
- "{\"amount\":\"EUR:5\",\
+ TALER_TESTING_cmd_merchant_post_orders ("create-proposal-4",
+ twister_merchant_url_instance_nonexistent,
+ MHD_HTTP_NOT_FOUND,
+ "{\"amount\":\"EUR:5\",\
\"fulfillment_url\": \"https://example.com/\",\
\"summary\": \"merchant-lib testcase\"}"),
/* Cause a 404 Not Found from /proposal/lookup,
* due to a non existing order id being queried. */
- TALER_TESTING_cmd_proposal_lookup ("lookup-0",
- twister_merchant_url,
- MHD_HTTP_NOT_FOUND,
- NULL,
- "does-not-exist"),
+ TALER_TESTING_cmd_merchant_post_orders_lookup ("lookup-0",
+ twister_merchant_url,
+ MHD_HTTP_NOT_FOUND,
+ NULL,
+ "does-not-exist"),
/* Cause a unparsable response to be returned. */
TALER_TESTING_cmd_malform_response
("malform-proposal-lookup",
PROXY_MERCHANT_CONFIG_FILE),
/* To be short, we'll make a _error_ response to be
* unparsable. */
- TALER_TESTING_cmd_proposal_lookup ("lookup-1",
- twister_merchant_url,
- 0, // response code.
- NULL,
- "does-not-exist"),
+ TALER_TESTING_cmd_merchant_post_orders_lookup ("lookup-1",
+ twister_merchant_url,
+ 0, // response code.
+ NULL,
+ "does-not-exist"),
/* Generating a proposal-lookup response which doesn't pass
* validation, by removing a field that is expected by the
@@ -398,10 +398,10 @@ run (void *cls,
/* First step is to create a _valid_ proposal, so that
* we can lookup for it later. */
- TALER_TESTING_cmd_proposal ("create-proposal-5",
- twister_merchant_url,
- MHD_HTTP_OK,
- "{\"max_fee\":\"EUR:0.5\",\
+ TALER_TESTING_cmd_merchant_post_orders ("create-proposal-5",
+ twister_merchant_url,
+ MHD_HTTP_OK,
+ "{\"max_fee\":\"EUR:0.5\",\
\"order_id\":\"5\",\
\"refund_deadline\":{\"t_ms\":0},\
\"pay_deadline\":{\"t_ms\":\"never\"},\
@@ -417,12 +417,12 @@ run (void *cls,
"contract_terms"),
/* lookup! */
- TALER_TESTING_cmd_proposal_lookup ("lookup-5",
- twister_merchant_url,
- // expected response code.
- 0,
- "create-proposal-5",
- NULL),
+ TALER_TESTING_cmd_merchant_post_orders_lookup ("lookup-5",
+ twister_merchant_url,
+ // expected response code.
+ 0,
+ "create-proposal-5",
+ NULL),
TALER_TESTING_cmd_end ()
};
@@ -486,14 +486,14 @@ run (void *cls,
"create-reserve-unaggregation",
"EUR:5",
MHD_HTTP_OK),
- TALER_TESTING_cmd_proposal ("create-proposal-unaggregation",
- /* Need a fresh instance in order to associate this
- * proposal with a fresh h_wire; this way, this proposal
- * won't get hooked by the aggregator gathering same-h_wire'd
- * transactions. */
- twister_merchant_url_instance_tor,
- MHD_HTTP_OK,
- "{\"max_fee\":\"EUR:0.5\",\
+ TALER_TESTING_cmd_merchant_post_orders ("create-proposal-unaggregation",
+ /* Need a fresh instance in order to associate this
+ * proposal with a fresh h_wire; this way, this proposal
+ * won't get hooked by the aggregator gathering same-h_wire'd
+ * transactions. */
+ twister_merchant_url_instance_tor,
+ MHD_HTTP_OK,
+ "{\"max_fee\":\"EUR:0.5\",\
\"refund_deadline\":{\"t_ms\":2000},\
\"pay_deadline\":{\"t_ms\":2366841500000},\
\"wire_transfer_deadline\":{\"t_ms\":2366841600000},\
@@ -535,10 +535,10 @@ run (void *cls,
"create-reserve-5383",
"EUR:1",
MHD_HTTP_OK),
- TALER_TESTING_cmd_proposal ("create-proposal-5383",
- twister_merchant_url,
- MHD_HTTP_OK,
- "{\"max_fee\":\"EUR:0.5\",\
+ TALER_TESTING_cmd_merchant_post_orders ("create-proposal-5383",
+ twister_merchant_url,
+ MHD_HTTP_OK,
+ "{\"max_fee\":\"EUR:0.5\",\
\"order_id\":\"5383\",\
\"refund_deadline\":{\"t_ms\":0},\
\"pay_deadline\":{\"t_ms\":\"never\"},\
@@ -610,10 +610,10 @@ run (void *cls,
"create-reserve-1",
"EUR:0",
MHD_HTTP_OK),
- TALER_TESTING_cmd_proposal ("create-proposal-6",
- twister_merchant_url,
- MHD_HTTP_OK,
- "{\"max_fee\":\"EUR:0.5\",\
+ TALER_TESTING_cmd_merchant_post_orders ("create-proposal-6",
+ twister_merchant_url,
+ MHD_HTTP_OK,
+ "{\"max_fee\":\"EUR:0.5\",\
\"order_id\":\"11\",\
\"refund_deadline\":{\"t_ms\":0},\
\"pay_deadline\":{\"t_ms\":\"never\"},\
@@ -707,10 +707,10 @@ run (void *cls,
"create-reserve-abort-1",
"EUR:0",
MHD_HTTP_OK),
- TALER_TESTING_cmd_proposal ("create-proposal-abort-1",
- twister_merchant_url,
- MHD_HTTP_OK,
- "{\"max_fee\":\"EUR:0.5\",\
+ TALER_TESTING_cmd_merchant_post_orders ("create-proposal-abort-1",
+ twister_merchant_url,
+ MHD_HTTP_OK,
+ "{\"max_fee\":\"EUR:0.5\",\
\"order_id\":\"abort-one\",\
\"refund_deadline\":{\"t_ms\":0},\
\"pay_deadline\":{\"t_ms\":\"never\"},\
@@ -769,10 +769,10 @@ run (void *cls,
CMD_TRANSFER_TO_EXCHANGE ("create-reserve-double-spend",
"EUR:1.01"),
CMD_EXEC_WIREWATCH ("wirewatch-double-spend"),
- TALER_TESTING_cmd_proposal ("create-proposal-double-spend",
- twister_merchant_url,
- MHD_HTTP_OK,
- "{\"max_fee\":\"EUR:0.5\",\
+ TALER_TESTING_cmd_merchant_post_orders ("create-proposal-double-spend",
+ twister_merchant_url,
+ MHD_HTTP_OK,
+ "{\"max_fee\":\"EUR:0.5\",\
\"order_id\":\"DS-1\",\
\"refund_deadline\":{\"t_ms\":0},\
\"pay_deadline\":{\"t_ms\":\"never\"},\
@@ -780,10 +780,10 @@ run (void *cls,
\"amount\":\"EUR:1.0\",\
\"summary\": \"merchant-lib testcase\",\
\"products\": [ {\"description\": \"will succeed\"}] }"),
- TALER_TESTING_cmd_proposal ("create-proposal-double-spend-1",
- twister_merchant_url,
- MHD_HTTP_OK,
- "{\"max_fee\":\"EUR:0.5\",\
+ TALER_TESTING_cmd_merchant_post_orders ("create-proposal-double-spend-1",
+ twister_merchant_url,
+ MHD_HTTP_OK,
+ "{\"max_fee\":\"EUR:0.5\",\
\"order_id\":\"DS-2\",\
\"refund_deadline\":{\"t_ms\":0},\
\"pay_deadline\":{\"t_ms\":\"never\"},\
diff --git a/src/testing/testing_api_cmd_post_orders.c b/src/testing/testing_api_cmd_post_orders.c
@@ -0,0 +1,397 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2014-2018 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 testing_api_cmd_post_orders.c
+ * @brief command to run POST /orders
+ * @author Marcello Stanisci
+ */
+
+#include "platform.h"
+#include <taler/taler_exchange_service.h>
+#include <taler/taler_testing_lib.h>
+#include "taler_merchant_service.h"
+#include "taler_merchant_testing_lib.h"
+
+/**
+ * State for a "POST /orders" CMD.
+ */
+struct OrdersState
+{
+
+ /**
+ * The order.
+ */
+ const char *order;
+
+ /**
+ * Expected status code.
+ */
+ unsigned int http_status;
+
+ /**
+ * Order id.
+ */
+ const char *order_id;
+
+ /**
+ * Contract terms obtained from the backend.
+ */
+ json_t *contract_terms;
+
+ /**
+ * Contract terms hash code.
+ */
+ struct GNUNET_HashCode h_contract_terms;
+
+ /**
+ * The /orders operation handle.
+ */
+ struct TALER_MERCHANT_PostOrdersOperation *po;
+
+ /**
+ * The (initial) GET /orders/$ID operation handle.
+ * The logic is such that after a orders creation,
+ * it soon makes a orders lookup in order to check
+ * if the merchant backend is actually aware.
+ */
+ struct TALER_MERCHANT_ProposalLookupOperation *plo;
+
+ /**
+ * The nonce.
+ */
+ struct GNUNET_CRYPTO_EddsaPublicKey nonce;
+
+ /**
+ * URL of the merchant backend.
+ */
+ const char *merchant_url;
+
+ /**
+ * The interpreter state.
+ */
+ struct TALER_TESTING_Interpreter *is;
+
+ /**
+ * Merchant signature over the orders.
+ */
+ struct TALER_MerchantSignatureP merchant_sig;
+
+ /**
+ * Merchant public key.
+ */
+ struct TALER_MerchantPublicKeyP merchant_pub;
+};
+
+
+/**
+ * Offer internal data to other commands.
+ *
+ * @param cls closure
+ * @param ret[out] result (could be anything)
+ * @param trait name of the trait
+ * @param index index number of the object to extract.
+ * @return #GNUNET_OK on success
+ */
+static int
+orders_traits (void *cls,
+ const void **ret,
+ const char *trait,
+ unsigned int index)
+{
+ struct OrdersState *ps = cls;
+ // FIXME: wtf is this?
+#define MAKE_TRAIT_NONCE(ptr) \
+ TALER_TESTING_make_trait_merchant_pub ( \
+ 1, (struct TALER_MerchantPublicKeyP *) (ptr))
+ struct TALER_TESTING_Trait traits[] = {
+ TALER_TESTING_make_trait_order_id (0, ps->order_id),
+ TALER_TESTING_make_trait_contract_terms (0, ps->contract_terms),
+ TALER_TESTING_make_trait_h_contract_terms (0, &ps->h_contract_terms),
+ TALER_TESTING_make_trait_merchant_sig (0, &ps->merchant_sig),
+ TALER_TESTING_make_trait_merchant_pub (0, &ps->merchant_pub),
+ MAKE_TRAIT_NONCE (&ps->nonce),
+ TALER_TESTING_trait_end ()
+ };
+
+ return TALER_TESTING_get_trait (traits,
+ ret,
+ trait,
+ index);
+}
+
+
+/**
+ * Used to fill the "orders" CMD state with backend-provided
+ * values. Also double-checks that the orders was correctly
+ * created.
+ *
+ * @param cls closure
+ * @param hr HTTP response we got
+ * @param sig merchant's signature
+ * @param hash hash over the contract
+ */
+static void
+orders_lookup_initial_cb (void *cls,
+ const struct TALER_MERCHANT_HttpResponse *hr,
+ const json_t *contract_terms,
+ const struct TALER_MerchantSignatureP *sig,
+ const struct GNUNET_HashCode *hash)
+{
+ struct OrdersState *ps = cls;
+ struct TALER_MerchantPublicKeyP merchant_pub;
+ const char *error_name;
+ unsigned int error_line;
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_fixed_auto ("merchant_pub",
+ &merchant_pub),
+ GNUNET_JSON_spec_end ()
+ };
+
+ ps->plo = NULL;
+ if (ps->http_status != hr->http_status)
+ TALER_TESTING_FAIL (ps->is);
+
+ ps->contract_terms = json_deep_copy (contract_terms);
+ ps->h_contract_terms = *hash;
+ ps->merchant_sig = *sig;
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (contract_terms,
+ spec,
+ &error_name,
+ &error_line))
+ {
+ char *log;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Parser failed on %s:%u\n",
+ error_name,
+ error_line);
+ log = json_dumps (ps->contract_terms,
+ JSON_INDENT (1));
+ fprintf (stderr,
+ "%s\n",
+ log);
+ free (log);
+ TALER_TESTING_FAIL (ps->is);
+ }
+ ps->merchant_pub = merchant_pub;
+ TALER_TESTING_interpreter_next (ps->is);
+}
+
+
+/**
+ * Callback that processes the response following a
+ * POST /orders. NOTE: no contract terms are included
+ * here; they need to be taken via the "orders lookup"
+ * method.
+ *
+ * @param cls closure.
+ * @param hr HTTP response
+ * @param order_id order id of the orders.
+ */
+static void
+order_cb (void *cls,
+ const struct TALER_MERCHANT_HttpResponse *hr,
+ const char *order_id)
+{
+ struct OrdersState *ps = cls;
+
+ ps->po = NULL;
+ if (ps->http_status != hr->http_status)
+ {
+ TALER_LOG_ERROR ("Given vs expected: %u(%d) vs %u\n",
+ hr->http_status,
+ (int) hr->ec,
+ ps->http_status);
+ TALER_TESTING_FAIL (ps->is);
+ }
+ if (0 == ps->http_status)
+ {
+ TALER_LOG_DEBUG ("/orders, expected 0 status code\n");
+ TALER_TESTING_interpreter_next (ps->is);
+ return;
+ }
+ switch (hr->http_status)
+ {
+ case MHD_HTTP_OK:
+ ps->order_id = GNUNET_strdup (order_id);
+ break;
+ default:
+ {
+ char *s = json_dumps (hr->reply,
+ JSON_COMPACT);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unexpected status code from /orders: %u (%d) at %s; JSON: %s\n",
+ hr->http_status,
+ hr->ec,
+ TALER_TESTING_interpreter_get_current_label (ps->is),
+ s);
+ GNUNET_free_non_null (s);
+ /**
+ * Not failing, as test cases are _supposed_
+ * to create non 200 OK situations.
+ */
+ TALER_TESTING_interpreter_next (ps->is);
+ }
+ return;
+ }
+
+ if (NULL ==
+ (ps->plo = TALER_MERCHANT_proposal_lookup (ps->is->ctx,
+ ps->merchant_url,
+ ps->order_id,
+ &ps->nonce,
+ &orders_lookup_initial_cb,
+ ps)))
+ TALER_TESTING_FAIL (ps->is);
+}
+
+
+/**
+ * Run a "orders" CMD.
+ *
+ * @param cls closure.
+ * @param cmd command currently being run.
+ * @param is interpreter state.
+ */
+static void
+orders_run (void *cls,
+ const struct TALER_TESTING_Command *cmd,
+ struct TALER_TESTING_Interpreter *is)
+{
+ struct OrdersState *ps = cls;
+ json_t *order;
+ json_error_t error;
+
+ ps->is = is;
+ order = json_loads (ps->order,
+ JSON_REJECT_DUPLICATES,
+ &error);
+ if (NULL == order)
+ {
+ // human error here.
+ GNUNET_break (0);
+ fprintf (stderr, "%s\n", error.text);
+ TALER_TESTING_interpreter_fail (is);
+ return;
+ }
+
+ if (NULL == json_object_get (order,
+ "order_id"))
+ {
+ struct GNUNET_TIME_Absolute now;
+ char *order_id;
+
+ // FIXME: should probably use get_monotone() to ensure uniqueness!
+ now = GNUNET_TIME_absolute_get ();
+ order_id = GNUNET_STRINGS_data_to_string_alloc
+ (&now.abs_value_us,
+ sizeof (now.abs_value_us));
+ json_object_set_new (order,
+ "order_id",
+ json_string (order_id));
+ GNUNET_free (order_id);
+ }
+ GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
+ &ps->nonce,
+ sizeof (struct GNUNET_CRYPTO_EddsaPublicKey));
+ ps->po = TALER_MERCHANT_orders_post (is->ctx,
+ ps->merchant_url,
+ order,
+ &order_cb,
+ ps);
+ json_decref (order);
+ GNUNET_assert (NULL != ps->po);
+}
+
+
+/**
+ * Free the state of a "orders" CMD, and possibly
+ * cancel it if it did not complete.
+ *
+ * @param cls closure.
+ * @param cmd command being freed.
+ */
+static void
+orders_cleanup (void *cls,
+ const struct TALER_TESTING_Command *cmd)
+{
+ struct OrdersState *ps = cls;
+
+ if (NULL != ps->po)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Command '%s' did not complete (orders put)\n",
+ cmd->label);
+ TALER_MERCHANT_orders_post_cancel (ps->po);
+ ps->po = NULL;
+ }
+
+ if (NULL != ps->plo)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Command '%s' did not complete"
+ " (orders lookup)\n",
+ cmd->label);
+ TALER_MERCHANT_proposal_lookup_cancel (ps->plo);
+ ps->plo = NULL;
+ }
+
+ json_decref (ps->contract_terms);
+ GNUNET_free_non_null ((void *) ps->order_id);
+ GNUNET_free (ps);
+}
+
+
+/**
+ * Make the "orders" command.
+ *
+ * @param label command label
+ * @param merchant_url base URL of the merchant serving
+ * the orders request.
+ * @param http_status expected HTTP status.
+ * @param order the order to PUT to the merchant.
+ *
+ * @return the command
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_merchant_post_orders (const char *label,
+ const char *merchant_url,
+ unsigned int http_status,
+ const char *order)
+{
+ struct OrdersState *ps;
+
+ ps = GNUNET_new (struct OrdersState);
+ ps->order = order;
+ ps->http_status = http_status;
+ ps->merchant_url = merchant_url;
+ {
+ struct TALER_TESTING_Command cmd = {
+ .cls = ps,
+ .label = label,
+ .run = &orders_run,
+ .cleanup = &orders_cleanup,
+ .traits = &orders_traits
+ };
+
+ return cmd;
+ }
+}
diff --git a/src/testing/testing_api_cmd_proposal.c b/src/testing/testing_api_cmd_proposal.c
@@ -1,401 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014-2018 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 exchange/testing_api_cmd_proposal.c
- * @brief command to run /proposal
- * @author Marcello Stanisci
- */
-
-#include "platform.h"
-#include <taler/taler_exchange_service.h>
-#include <taler/taler_testing_lib.h>
-#include "taler_merchant_service.h"
-#include "taler_merchant_testing_lib.h"
-
-/**
- * State for a "proposal" CMD.
- */
-struct ProposalState
-{
-
- /**
- * The order.
- */
- const char *order;
-
- /**
- * Expected status code.
- */
- unsigned int http_status;
-
- /**
- * Order id.
- */
- const char *order_id;
-
- /**
- * Contract terms obtained from the backend.
- */
- json_t *contract_terms;
-
- /**
- * Contract terms hash code.
- */
- struct GNUNET_HashCode h_contract_terms;
-
- /**
- * The /proposal operation handle.
- */
- struct TALER_MERCHANT_ProposalOperation *po;
-
- /**
- * The (initial) /proposal/lookup operation handle.
- * The logic is such that after a proposal creation,
- * it soon makes a proposal lookup in order to check
- * if the merchant backend is actually aware.
- */
- struct TALER_MERCHANT_ProposalLookupOperation *plo;
-
- /**
- * The nonce.
- */
- struct GNUNET_CRYPTO_EddsaPublicKey nonce;
-
- /**
- * URL of the merchant backend.
- */
- const char *merchant_url;
-
- /**
- * The interpreter state.
- */
- struct TALER_TESTING_Interpreter *is;
-
- /**
- * Merchant signature over the proposal.
- */
- struct TALER_MerchantSignatureP merchant_sig;
-
- /**
- * Merchant public key.
- */
- struct TALER_MerchantPublicKeyP merchant_pub;
-};
-
-
-/**
- * Offer internal data to other commands.
- *
- * @param cls closure
- * @param ret[out] result (could be anything)
- * @param trait name of the trait
- * @param index index number of the object to extract.
- * @return #GNUNET_OK on success
- */
-static int
-proposal_traits (void *cls,
- const void **ret,
- const char *trait,
- unsigned int index)
-{
- struct ProposalState *ps = cls;
-#define MAKE_TRAIT_NONCE(ptr) \
- TALER_TESTING_make_trait_merchant_pub (1, (struct \
- TALER_MerchantPublicKeyP *) (ptr))
- struct TALER_TESTING_Trait traits[] = {
- TALER_TESTING_make_trait_order_id (0, ps->order_id),
- TALER_TESTING_make_trait_contract_terms (0, ps->contract_terms),
- TALER_TESTING_make_trait_h_contract_terms (0, &ps->h_contract_terms),
- TALER_TESTING_make_trait_merchant_sig (0, &ps->merchant_sig),
- TALER_TESTING_make_trait_merchant_pub (0, &ps->merchant_pub),
- MAKE_TRAIT_NONCE (&ps->nonce),
- TALER_TESTING_trait_end ()
- };
-
- return TALER_TESTING_get_trait (traits,
- ret,
- trait,
- index);
-}
-
-
-/**
- * Used to fill the "proposal" CMD state with backend-provided
- * values. Also double-checks that the proposal was correctly
- * created.
- *
- * @param cls closure
- * @param hr HTTP response we got
- * @param sig merchant's signature
- * @param hash hash over the contract
- */
-static void
-proposal_lookup_initial_cb (void *cls,
- const struct TALER_MERCHANT_HttpResponse *hr,
- const json_t *contract_terms,
- const struct TALER_MerchantSignatureP *sig,
- const struct GNUNET_HashCode *hash)
-{
- struct ProposalState *ps = cls;
- struct TALER_MerchantPublicKeyP merchant_pub;
- const char *error_name;
- unsigned int error_line;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("merchant_pub",
- &merchant_pub),
- GNUNET_JSON_spec_end ()
- };
-
- ps->plo = NULL;
- if (ps->http_status != hr->http_status)
- TALER_TESTING_FAIL (ps->is);
-
- ps->contract_terms = json_deep_copy (contract_terms);
- ps->h_contract_terms = *hash;
- ps->merchant_sig = *sig;
- if (GNUNET_OK !=
- GNUNET_JSON_parse (contract_terms,
- spec,
- &error_name,
- &error_line))
- {
- char *log;
-
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Parser failed on %s:%u\n",
- error_name,
- error_line);
- log = json_dumps (ps->contract_terms,
- JSON_INDENT (1));
- fprintf (stderr,
- "%s\n",
- log);
- free (log);
- TALER_TESTING_FAIL (ps->is);
- }
- ps->merchant_pub = merchant_pub;
- TALER_TESTING_interpreter_next (ps->is);
-}
-
-
-/**
- * Callback that processes the response following a
- * proposal's put. NOTE: no contract terms are included
- * here; they need to be taken via the "proposal lookup"
- * method.
- *
- * @param cls closure.
- * @param hr HTTP response
- * @param order_id order id of the proposal.
- */
-static void
-proposal_cb (void *cls,
- const struct TALER_MERCHANT_HttpResponse *hr,
- const char *order_id)
-{
- struct ProposalState *ps = cls;
-
- ps->po = NULL;
- if (ps->http_status != hr->http_status)
- {
- TALER_LOG_ERROR ("Given vs expected: %u(%d) vs %u\n",
- hr->http_status,
- (int) hr->ec,
- ps->http_status);
- TALER_TESTING_FAIL (ps->is);
- }
-
- if (0 == ps->http_status)
- {
- TALER_LOG_DEBUG ("/proposal, expected 0 status code\n");
- TALER_TESTING_interpreter_next (ps->is);
- return;
- }
-
- switch (hr->http_status)
- {
- case MHD_HTTP_OK:
- ps->order_id = GNUNET_strdup (order_id);
- break;
- default:
- {
- char *s = json_dumps (hr->reply,
- JSON_COMPACT);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected status code from /proposal: %u (%d) at %s; JSON: %s\n",
- hr->http_status,
- hr->ec,
- TALER_TESTING_interpreter_get_current_label (ps->is),
- s);
- GNUNET_free_non_null (s);
- /**
- * Not failing, as test cases are _supposed_
- * to create non 200 OK situations.
- */
- TALER_TESTING_interpreter_next (ps->is);
- }
- return;
- }
-
- if (NULL ==
- (ps->plo = TALER_MERCHANT_proposal_lookup (ps->is->ctx,
- ps->merchant_url,
- ps->order_id,
- &ps->nonce,
- &proposal_lookup_initial_cb,
- ps)))
- TALER_TESTING_FAIL (ps->is);
-}
-
-
-/**
- * Run a "proposal" CMD.
- *
- * @param cls closure.
- * @param cmd command currently being run.
- * @param is interpreter state.
- */
-static void
-proposal_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is)
-{
- struct ProposalState *ps = cls;
- json_t *order;
- json_error_t error;
-
- ps->is = is;
- order = json_loads (ps->order,
- JSON_REJECT_DUPLICATES,
- &error);
- if (NULL == order)
- {
- // human error here.
- GNUNET_break (0);
- fprintf (stderr, "%s\n", error.text);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
- if (NULL == json_object_get (order,
- "order_id"))
- {
- struct GNUNET_TIME_Absolute now;
- char *order_id;
-
- // FIXME: should probably use get_monotone() to ensure uniqueness!
- now = GNUNET_TIME_absolute_get ();
- order_id = GNUNET_STRINGS_data_to_string_alloc
- (&now.abs_value_us,
- sizeof (now.abs_value_us));
- json_object_set_new (order,
- "order_id",
- json_string (order_id));
- GNUNET_free (order_id);
- }
-
- GNUNET_CRYPTO_random_block
- (GNUNET_CRYPTO_QUALITY_WEAK,
- &ps->nonce,
- sizeof (struct GNUNET_CRYPTO_EddsaPublicKey));
-
- ps->po = TALER_MERCHANT_order_put (is->ctx,
- ps->merchant_url,
- order,
- &proposal_cb,
- ps);
- json_decref (order);
- GNUNET_assert (NULL != ps->po);
-}
-
-
-/**
- * Free the state of a "proposal" CMD, and possibly
- * cancel it if it did not complete.
- *
- * @param cls closure.
- * @param cmd command being freed.
- */
-static void
-proposal_cleanup (void *cls,
- const struct TALER_TESTING_Command *cmd)
-{
- struct ProposalState *ps = cls;
-
- if (NULL != ps->po)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Command '%s' did not complete (proposal put)\n",
- cmd->label);
- TALER_MERCHANT_proposal_cancel (ps->po);
- ps->po = NULL;
- }
-
- if (NULL != ps->plo)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Command '%s' did not complete"
- " (proposal lookup)\n",
- cmd->label);
- TALER_MERCHANT_proposal_lookup_cancel (ps->plo);
- ps->plo = NULL;
- }
-
- json_decref (ps->contract_terms);
- GNUNET_free_non_null ((void *) ps->order_id);
- GNUNET_free (ps);
-}
-
-
-/**
- * Make the "proposal" command.
- *
- * @param label command label
- * @param merchant_url base URL of the merchant serving
- * the proposal request.
- * @param http_status expected HTTP status.
- * @param order the order to PUT to the merchant.
- *
- * @return the command
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_proposal (const char *label,
- const char *merchant_url,
- unsigned int http_status,
- const char *order)
-{
- struct ProposalState *ps;
-
- ps = GNUNET_new (struct ProposalState);
- ps->order = order;
- ps->http_status = http_status;
- ps->merchant_url = merchant_url;
- {
- struct TALER_TESTING_Command cmd = {
- .cls = ps,
- .label = label,
- .run = &proposal_run,
- .cleanup = &proposal_cleanup,
- .traits = &proposal_traits
- };
-
- return cmd;
- }
-}
diff --git a/src/testing/testing_api_cmd_proposal_lookup.c b/src/testing/testing_api_cmd_proposal_lookup.c
@@ -283,7 +283,7 @@ proposal_lookup_traits (void *cls,
* @return the command.
*/
struct TALER_TESTING_Command
-TALER_TESTING_cmd_proposal_lookup
+TALER_TESTING_cmd_merchant_post_orders_lookup
(const char *label,
const char *merchant_url,
unsigned int http_status,