summaryrefslogtreecommitdiff
path: root/src/backend/taler-merchant-httpd_post-using-templates.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/taler-merchant-httpd_post-using-templates.c')
-rw-r--r--src/backend/taler-merchant-httpd_post-using-templates.c322
1 files changed, 194 insertions, 128 deletions
diff --git a/src/backend/taler-merchant-httpd_post-using-templates.c b/src/backend/taler-merchant-httpd_post-using-templates.c
index 9252afc8..cdaf917e 100644
--- a/src/backend/taler-merchant-httpd_post-using-templates.c
+++ b/src/backend/taler-merchant-httpd_post-using-templates.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- (C) 2022 Taler Systems SA
+ (C) 2022-2023 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
@@ -21,6 +21,7 @@
* @file taler-merchant-httpd_post-using-templates.c
* @brief implementing POST /using-templates request handling
* @author Priscilla HUANG
+ * @author Christian Grothoff
*/
#include "platform.h"
#include "taler-merchant-httpd_post-using-templates.h"
@@ -29,13 +30,49 @@
#include <taler/taler_json_lib.h>
+/**
+ * Our context.
+ */
+struct UseContext
+{
+ /**
+ * Internal handler context we are passing into the
+ * POST /private/orders handler.
+ */
+ struct TMH_HandlerContext ihc;
+
+ /**
+ * Our template details from the DB.
+ */
+ struct TALER_MERCHANTDB_TemplateDetails etp;
+
+};
+
+
+/**
+ * Clean up a `struct UseContext *`
+ *
+ * @param cls a `struct UseContext *`
+ */
+static void
+cleanup_use_context (void *cls)
+{
+ struct UseContext *uc = cls;
+
+ TALER_MERCHANTDB_template_details_free (&uc->etp);
+ if (NULL != uc->ihc.cc)
+ uc->ihc.cc (uc->ihc.ctx);
+ json_decref (uc->ihc.request_body);
+ GNUNET_free (uc);
+}
+
+
MHD_RESULT
TMH_post_using_templates_ID (const struct TMH_RequestHandler *rh,
struct MHD_Connection *connection,
struct TMH_HandlerContext *hc)
{
struct TMH_MerchantInstance *mi = hc->instance;
- MHD_RESULT mret;
const char *template_id = hc->infix;
const char *summary = NULL;
const char *fulfillment_url = NULL;
@@ -44,20 +81,26 @@ TMH_post_using_templates_ID (const struct TMH_RequestHandler *rh,
bool no_amount;
json_t *fake_body;
bool no_summary;
- struct TALER_MERCHANTDB_TemplateDetails etp;
-
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_string ("summary",
&summary),
NULL),
GNUNET_JSON_spec_mark_optional (
- TALER_JSON_spec_amount ("amount",
- TMH_currency,
- &amount),
+ TALER_JSON_spec_amount_any ("amount",
+ &amount),
&no_amount),
GNUNET_JSON_spec_end ()
};
+ struct UseContext *uc = hc->ctx;
+
+ if (NULL == uc)
+ {
+ uc = GNUNET_new (struct UseContext);
+ hc->ctx = uc;
+ hc->cc = &cleanup_use_context;
+ uc->ihc.instance = hc->instance;
+ }
{
enum GNUNET_GenericReturnValue res;
@@ -80,156 +123,179 @@ TMH_post_using_templates_ID (const struct TMH_RequestHandler *rh,
qs = TMH_db->lookup_template (TMH_db->cls,
mi->settings.id,
template_id,
- &etp);
+ &uc->etp);
switch (qs)
{
case GNUNET_DB_STATUS_HARD_ERROR:
/* Clean up and fail hard */
GNUNET_break (0);
GNUNET_JSON_parse_free (spec);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- NULL);
+ return TALER_MHD_reply_with_error (
+ connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ NULL);
case GNUNET_DB_STATUS_SOFT_ERROR:
/* this should be impossible (single select) */
GNUNET_break (0);
GNUNET_JSON_parse_free (spec);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- NULL);
+ return TALER_MHD_reply_with_error (
+ connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ NULL);
case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
/* template not found! */
GNUNET_JSON_parse_free (spec);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_NOT_FOUND,
- TALER_EC_MERCHANT_GENERIC_TEMPLATE_UNKNOWN,
- template_id);
+ return TALER_MHD_reply_with_error (
+ connection,
+ MHD_HTTP_NOT_FOUND,
+ TALER_EC_MERCHANT_GENERIC_TEMPLATE_UNKNOWN,
+ template_id);
case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
/* all good */
break;
} /* End of the switch */
}
- const char *tsummary;
- uint32_t min_age;
- struct GNUNET_TIME_Relative pay_duration;
- struct TALER_Amount tamount;
- bool no_tamount;
+ {
+ /* template */
+ const char *tsummary = NULL;
+ const char *tcurrency = NULL;
+ uint32_t min_age;
+ struct GNUNET_TIME_Relative pay_duration;
+ struct TALER_Amount tamount;
+ bool no_tamount;
+ struct GNUNET_JSON_Specification tspec[] = {
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_string ("summary",
+ &tsummary),
+ NULL),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_string ("currency",
+ &tcurrency),
+ NULL),
+ GNUNET_JSON_spec_mark_optional (
+ TALER_JSON_spec_amount_any ("amount",
+ &tamount),
+ &no_tamount),
+ GNUNET_JSON_spec_uint32 ("minimum_age",
+ &min_age),
+ GNUNET_JSON_spec_relative_time ("pay_duration",
+ &pay_duration),
+ GNUNET_JSON_spec_end ()
+ };
- struct GNUNET_JSON_Specification tspec[] = {
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_string ("summary",
- &tsummary),
- NULL),
- GNUNET_JSON_spec_mark_optional (
- TALER_JSON_spec_amount ("amount",
- TMH_currency,
- &tamount),
- &no_tamount),
- GNUNET_JSON_spec_uint32 ("minimum_age",
- &min_age),
- GNUNET_JSON_spec_relative_time ("pay_duration",
- &pay_duration),
- GNUNET_JSON_spec_end ()
- };
+ {
+ enum GNUNET_GenericReturnValue res;
+ const char *err_name;
+ unsigned int err_line;
- {
- enum GNUNET_GenericReturnValue res;
- const char *err_name;
- unsigned int err_line;
+ res = GNUNET_JSON_parse (uc->etp.template_contract,
+ tspec,
+ &err_name,
+ &err_line);
+ if (GNUNET_OK != res)
+ {
+ GNUNET_break (0);
+ json_dumpf (uc->etp.template_contract,
+ stderr,
+ JSON_INDENT (2));
+ GNUNET_JSON_parse_free (spec);
+ return TALER_MHD_reply_with_error (
+ connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ err_name);
+ }
+ }
- res = GNUNET_JSON_parse (etp.template_contract,
- tspec,
- &err_name,
- &err_line);
- if (GNUNET_OK != res)
+ if ( (! no_amount) &&
+ (! no_tamount) )
{
- GNUNET_break (0);
- json_dumpf (etp.template_contract,
- stderr,
- JSON_INDENT (2));
GNUNET_JSON_parse_free (spec);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- err_name);
+ return TALER_MHD_reply_with_error (
+ connection,
+ MHD_HTTP_CONFLICT,
+ TALER_EC_MERCHANT_POST_USING_TEMPLATES_AMOUNT_CONFLICT_TEMPLATES_CONTRACT_AMOUNT,
+ NULL);
}
- }
- // if amount given in template AND request
- if ((! no_amount) && (! no_tamount))
- {
- GNUNET_JSON_parse_free (spec);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_CONFLICT,
- TALER_EC_MERCHANT_POST_USING_TEMPLATES_AMOUNT_CONFLICT_TEMPLATES_CONTRACT_AMOUNT,
- NULL);
- }
-
- // if there is no amount in template and request
- if (no_amount && no_tamount)
- {
- GNUNET_JSON_parse_free (spec);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_CONFLICT,
- TALER_EC_MERCHANT_POST_USING_TEMPLATES_NO_AMOUNT,
- NULL);
- }
+ if ( (! no_amount) &&
+ (NULL != tcurrency) &&
+ (0 != strcmp (tcurrency,
+ amount.currency)) )
+ {
+ GNUNET_JSON_parse_free (spec);
+ return TALER_MHD_reply_with_error (
+ connection,
+ MHD_HTTP_CONFLICT,
+ TALER_EC_MERCHANT_GENERIC_CURRENCY_MISMATCH,
+ tcurrency);
+ }
- if ( (NULL!=summary) && (NULL != tsummary))
- {
+ if (no_amount && no_tamount)
+ {
+ GNUNET_JSON_parse_free (spec);
+ return TALER_MHD_reply_with_error (
+ connection,
+ MHD_HTTP_CONFLICT,
+ TALER_EC_MERCHANT_POST_USING_TEMPLATES_NO_AMOUNT,
+ NULL);
+ }
- GNUNET_JSON_parse_free (spec);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_CONFLICT,
- TALER_EC_MERCHANT_POST_USING_TEMPLATES_SUMMARY_CONFLICT_TEMPLATES_CONTRACT_SUBJECT,
- NULL);
- }
+ if ( (NULL != summary) &&
+ (NULL != tsummary) )
+ {
+ GNUNET_JSON_parse_free (spec);
+ return TALER_MHD_reply_with_error (
+ connection,
+ MHD_HTTP_CONFLICT,
+ TALER_EC_MERCHANT_POST_USING_TEMPLATES_SUMMARY_CONFLICT_TEMPLATES_CONTRACT_SUBJECT,
+ NULL);
+ }
- // if there is no summary in template and request
- if ( (NULL == summary) && (NULL == tsummary) )
- {
- GNUNET_JSON_parse_free (spec);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_CONFLICT,
- TALER_EC_MERCHANT_POST_USING_TEMPLATES_NO_SUMMARY,
- NULL);
+ if ( (NULL == summary) &&
+ (NULL == tsummary) )
+ {
+ GNUNET_JSON_parse_free (spec);
+ return TALER_MHD_reply_with_error (
+ connection,
+ MHD_HTTP_CONFLICT,
+ TALER_EC_MERCHANT_POST_USING_TEMPLATES_NO_SUMMARY,
+ NULL);
+ }
+ no_summary = (NULL == summary);
+ fake_body = GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_allow_null (
+ GNUNET_JSON_pack_string ("otp_id",
+ uc->etp.otp_id)),
+ GNUNET_JSON_pack_object_steal (
+ "order",
+ GNUNET_JSON_PACK (
+ TALER_JSON_pack_amount ("amount",
+ no_amount ?
+ &tamount :
+ &amount),
+ GNUNET_JSON_pack_string ("summary",
+ no_summary ?
+ tsummary :
+ summary),
+ GNUNET_JSON_pack_allow_null (
+ GNUNET_JSON_pack_string (
+ "fulfillment_url",
+ fulfillment_url)),
+ GNUNET_JSON_pack_allow_null (
+ GNUNET_JSON_pack_string (
+ "fulfillment_message",
+ fulfillment_message))
+ ))
+ );
}
- no_summary = (NULL == summary);
- fake_body = GNUNET_JSON_PACK (
- GNUNET_JSON_pack_object_steal ("order",
- GNUNET_JSON_PACK (
- TALER_JSON_pack_amount ("amount",
- no_amount ?
- &tamount :
- &amount),
- GNUNET_JSON_pack_string ("summary",
- no_summary ?
- tsummary :
- summary),
- GNUNET_JSON_pack_allow_null (
- GNUNET_JSON_pack_string (
- "fulfillment_url",
- fulfillment_url)),
- GNUNET_JSON_pack_allow_null (
- GNUNET_JSON_pack_string (
- "fulfillment_message",
- fulfillment_message))
- ))
- );
- TALER_MERCHANTDB_template_details_free (&etp);
- {
- struct TMH_HandlerContext fake_hc = {
- .request_body = fake_body,
- .instance = hc->instance
- };
- mret = TMH_private_post_orders (NULL, /* not even used */
- connection,
- &fake_hc);
- }
- json_decref (fake_body);
- return mret;
+ uc->ihc.request_body = fake_body;
+ return TMH_private_post_orders (
+ NULL, /* not even used */
+ connection,
+ &uc->ihc);
}