/* This file is part of TALER (C) 2022 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 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 */ /** * @file taler-merchant-httpd_post-using-templates.c * @brief implementing POST /using-templates request handling * @author Priscilla HUANG */ #include "platform.h" #include "taler-merchant-httpd_post-using-templates.h" #include "taler-merchant-httpd_private-post-orders.h" #include "taler-merchant-httpd_helper.h" #include 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; const char *fulfillment_message = NULL; struct TALER_Amount amount; 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), &no_amount), GNUNET_JSON_spec_end () }; { enum GNUNET_GenericReturnValue res; res = TALER_MHD_parse_json_data (connection, hc->request_body, spec); if (GNUNET_OK != res) { GNUNET_break_op (0); return (GNUNET_NO == res) ? MHD_YES : MHD_NO; } } { enum GNUNET_DB_QueryStatus qs; qs = TMH_db->lookup_template (TMH_db->cls, mi->settings.id, template_id, &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); 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); 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); 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; 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; res = GNUNET_JSON_parse (etp.template_contract, tspec, &err_name, &err_line); if (GNUNET_OK != res) { 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); } } // 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 ( (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); } 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; }