merchant

Merchant backend to process payments, run by merchants
Log | Files | Refs | Submodules | README | LICENSE

commit 73fdf47728e26d8625a85441b8523bca0176868f
parent 2c19f6a6fb180f059fcaeb193dd387c4d6af21b1
Author: priscilla <priscilla.huang@efrei.net>
Date:   Fri, 30 Dec 2022 08:50:16 -0500

testing using templates

Diffstat:
Msrc/backenddb/plugin_merchantdb_postgres.c | 6++++--
Msrc/include/taler_merchant_service.h | 30++++++++++++++++--------------
Msrc/lib/merchant_api_common.c | 145++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/lib/merchant_api_post_orders.c | 130+------------------------------------------------------------------------------
Msrc/lib/merchant_api_post_using_templates.c | 75++++-----------------------------------------------------------------------
Msrc/testing/test_merchant_api.c | 10+++++-----
6 files changed, 174 insertions(+), 222 deletions(-)

diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c @@ -6864,7 +6864,7 @@ postgres_insert_template (void *cls, GNUNET_PQ_query_param_string (instance_id), GNUNET_PQ_query_param_string (template_id), GNUNET_PQ_query_param_string (td->template_description), - NULL == td->image + (NULL == td->image) ? GNUNET_PQ_query_param_null () : GNUNET_PQ_query_param_string (td->image), TALER_PQ_query_param_json (td->template_contract), @@ -6900,7 +6900,9 @@ postgres_update_template (void *cls, GNUNET_PQ_query_param_string (instance_id), GNUNET_PQ_query_param_string (template_id), GNUNET_PQ_query_param_string (td->template_description), - GNUNET_PQ_query_param_string (td->image), + (NULL == td->image) + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string (td->image), TALER_PQ_query_param_json (td->template_contract), GNUNET_PQ_query_param_end }; diff --git a/src/include/taler_merchant_service.h b/src/include/taler_merchant_service.h @@ -1365,7 +1365,7 @@ struct TALER_MERCHANT_PostOrdersReply /** * Callbacks of this type are used to serve the result of submitting a - * POST /orders request to a merchant. + * POST /using-templates and POST /orders request to a merchant. * * @param cls closure * @param por response details @@ -4371,18 +4371,6 @@ TALER_MERCHANT_template_delete_cancel ( struct TALER_MERCHANT_TemplateDeleteHandle *tdh); /** - * Function called with the result of the POST /using-templates operation. - * - * @param cls closure - * @param hr HTTP response details - */ -typedef void -(*TALER_MERCHANT_UsingTemplatesPostCallback)( - void *cls, - const struct TALER_MERCHANT_HttpResponse *hr); -// FIXME: should be: const struct TALER_MERCHANT_PostOrdersReply *por); - -/** * Make a POST /using-templates request to add an using template * * @param ctx the context @@ -4400,7 +4388,7 @@ TALER_MERCHANT_using_templates_post ( const char *template_id, const char *summary, const struct TALER_Amount *amount, - TALER_MERCHANT_UsingTemplatesPostCallback cb, + TALER_MERCHANT_PostOrdersCallback cb, void *cb_cls); @@ -4413,6 +4401,20 @@ void TALER_MERCHANT_using_templates_post_cancel ( struct TALER_MERCHANT_UsingTemplatesPostHandle *utph); +/** + * Function called when we're done processing the + * HTTP POST /using-template request to create an order. + * + * @param cls the `struct TALER_MERCHANT_PostOrdersHandle or TALER_MERCHANT_UsingTemplatesPostHandle` + * @param response_code HTTP response code, 0 on error + * @param response response body, NULL if not JSON + */ +void +TALER_MERCHANT_handle_post_using_templates_create_order (void *cb_cls, + TALER_MERCHANT_PostOrdersCallback cb, + long response_code, + const json_t *json); + /* ********************* /webhooks *********************** */ diff --git a/src/lib/merchant_api_common.c b/src/lib/merchant_api_common.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2020 Taler Systems SA + Copyright (C) 2020 to 2022 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 @@ -18,6 +18,7 @@ * @file merchant_api_common.c * @brief Implementation of common logic for libtalermerchant * @author Christian Grothoff + * @author Priscilla Huang */ #include "platform.h" #include <curl/curl.h> @@ -371,3 +372,145 @@ TALER_MERCHANT_parse_refund_uri_free ( GNUNET_free (parse_data->order_id); GNUNET_free (parse_data->ssid); } + + +/** + * Function called when we're done processing the + * HTTP POST /using-template request to create an order. + * + * @param cls the `struct TALER_MERCHANT_PostOrdersHandle or TALER_MERCHANT_UsingTemplatesPostHandle` + * @param response_code HTTP response code, 0 on error + * @param response response body, NULL if not JSON + */ +void +TALER_MERCHANT_handle_post_using_templates_create_order (void *cb_cls, + TALER_MERCHANT_PostOrdersCallback cb, + long response_code, + const json_t *json) +{ + struct TALER_MERCHANT_PostOrdersReply por = { + .hr.http_status = (unsigned int) response_code, + .hr.reply = json + }; + struct TALER_ClaimTokenP token; + + switch (response_code) + { + case 0: + por.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; + break; + case MHD_HTTP_OK: + { + bool no_token; + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_string ("order_id", + &por.details.ok.order_id), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_fixed_auto ("token", + &token), + &no_token), + GNUNET_JSON_spec_end () + }; + + if (GNUNET_OK != + GNUNET_JSON_parse (json, + spec, + NULL, NULL)) + { + GNUNET_break_op (0); + por.hr.http_status = 0; + por.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; + } + else + { + if (! no_token) + por.details.ok.token = &token; + } + } + break; + case MHD_HTTP_BAD_REQUEST: + json_dumpf (json, + stderr, + JSON_INDENT (2)); + por.hr.ec = TALER_JSON_get_error_code (json); + por.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_UNAUTHORIZED: + por.hr.ec = TALER_JSON_get_error_code (json); + por.hr.hint = TALER_JSON_get_error_hint (json); + /* Nothing really to verify, merchant says we need to authenticate. */ + 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 */ + por.hr.ec = TALER_JSON_get_error_code (json); + por.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 */ + por.hr.ec = TALER_JSON_get_error_code (json); + por.hr.hint = TALER_JSON_get_error_hint (json); + break; + case MHD_HTTP_CONFLICT: + por.hr.ec = TALER_JSON_get_error_code (json); + por.hr.hint = TALER_JSON_get_error_hint (json); + break; + case MHD_HTTP_GONE: + /* The quantity of some product requested was not available. */ + { + + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_string ( + "product_id", + &por.details.gone.product_id), + GNUNET_JSON_spec_uint64 ( + "requested_quantity", + &por.details.gone.requested_quantity), + GNUNET_JSON_spec_uint64 ( + "available_quantity", + &por.details.gone.available_quantity), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_timestamp ( + "restock_expected", + &por.details.gone.restock_expected), + NULL), + GNUNET_JSON_spec_end () + }; + + if (GNUNET_OK != + GNUNET_JSON_parse (json, + spec, + NULL, NULL)) + { + GNUNET_break_op (0); + por.hr.http_status = 0; + por.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; + } + break; + } + case MHD_HTTP_INTERNAL_SERVER_ERROR: + /* Server had an internal issue; we should retry, + but this API leaves this to the application */ + por.hr.ec = TALER_JSON_get_error_code (json); + por.hr.hint = TALER_JSON_get_error_hint (json); + break; + default: + /* unexpected response code */ + por.hr.ec = TALER_JSON_get_error_code (json); + por.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) por.hr.ec); + GNUNET_break_op (0); + break; + } // end of switch + cb (cb_cls, + &por); +} diff --git a/src/lib/merchant_api_post_orders.c b/src/lib/merchant_api_post_orders.c @@ -88,136 +88,8 @@ handle_post_order_finished (void *cls, { struct TALER_MERCHANT_PostOrdersHandle *po = cls; const json_t *json = response; - struct TALER_MERCHANT_PostOrdersReply por = { - .hr.http_status = (unsigned int) response_code, - .hr.reply = json - }; - struct TALER_ClaimTokenP token; - po->job = NULL; - // to_be_written_new_function (po->cb, po->cb_cls, response_code, json); - // roughly from here - switch (response_code) - { - case 0: - por.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - break; - case MHD_HTTP_OK: - { - bool no_token; - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_string ("order_id", - &por.details.ok.order_id), - GNUNET_JSON_spec_mark_optional ( - GNUNET_JSON_spec_fixed_auto ("token", - &token), - &no_token), - GNUNET_JSON_spec_end () - }; - - if (GNUNET_OK != - GNUNET_JSON_parse (json, - spec, - NULL, NULL)) - { - GNUNET_break_op (0); - por.hr.http_status = 0; - por.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; - } - else - { - if (! no_token) - por.details.ok.token = &token; - } - } - break; - case MHD_HTTP_BAD_REQUEST: - json_dumpf (json, - stderr, - JSON_INDENT (2)); - por.hr.ec = TALER_JSON_get_error_code (json); - por.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_UNAUTHORIZED: - por.hr.ec = TALER_JSON_get_error_code (json); - por.hr.hint = TALER_JSON_get_error_hint (json); - /* Nothing really to verify, merchant says we need to authenticate. */ - 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 */ - por.hr.ec = TALER_JSON_get_error_code (json); - por.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 */ - por.hr.ec = TALER_JSON_get_error_code (json); - por.hr.hint = TALER_JSON_get_error_hint (json); - break; - case MHD_HTTP_CONFLICT: - por.hr.ec = TALER_JSON_get_error_code (json); - por.hr.hint = TALER_JSON_get_error_hint (json); - break; - case MHD_HTTP_GONE: - /* The quantity of some product requested was not available. */ - { - - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_string ( - "product_id", - &por.details.gone.product_id), - GNUNET_JSON_spec_uint64 ( - "requested_quantity", - &por.details.gone.requested_quantity), - GNUNET_JSON_spec_uint64 ( - "available_quantity", - &por.details.gone.available_quantity), - GNUNET_JSON_spec_mark_optional ( - GNUNET_JSON_spec_timestamp ( - "restock_expected", - &por.details.gone.restock_expected), - NULL), - GNUNET_JSON_spec_end () - }; - - if (GNUNET_OK != - GNUNET_JSON_parse (json, - spec, - NULL, NULL)) - { - GNUNET_break_op (0); - por.hr.http_status = 0; - por.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; - } - break; - } - case MHD_HTTP_INTERNAL_SERVER_ERROR: - /* Server had an internal issue; we should retry, - but this API leaves this to the application */ - por.hr.ec = TALER_JSON_get_error_code (json); - por.hr.hint = TALER_JSON_get_error_hint (json); - break; - default: - /* unexpected response code */ - por.hr.ec = TALER_JSON_get_error_code (json); - por.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) por.hr.ec); - GNUNET_break_op (0); - break; - } - po->cb (po->cb_cls, - &por); - // end of new function - + TALER_MERCHANT_handle_post_using_templates_create_order (po->cb_cls, po->cb, response_code, json); TALER_MERCHANT_orders_post_cancel (po); } diff --git a/src/lib/merchant_api_post_using_templates.c b/src/lib/merchant_api_post_using_templates.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2020-2021 Taler Systems SA + Copyright (C) 2022 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 @@ -52,7 +52,7 @@ struct TALER_MERCHANT_UsingTemplatesPostHandle /** * Function to call with the result. */ - TALER_MERCHANT_UsingTemplatesPostCallback cb; + TALER_MERCHANT_PostOrdersCallback cb; /** * Closure for @a cb. @@ -85,75 +85,8 @@ handle_post_using_templates_finished (void *cls, { struct TALER_MERCHANT_UsingTemplatesPostHandle *utph = cls; const json_t *json = response; - struct TALER_MERCHANT_HttpResponse hr = { - .http_status = (unsigned int) response_code, - .reply = json - }; - utph->job = NULL; - // to_be_written_new_function (utph->cb, utph->cb_cls, response_code, json); - // start of code to be removed - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "POST /using-templates completed with response code %u\n", - (unsigned int) response_code); - switch (response_code) - { - case 0: - hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - break; - case MHD_HTTP_NO_CONTENT: - break; - case MHD_HTTP_NOT_ACCEPTABLE: - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); - 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_FORBIDDEN: - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); - /* Nothing really to verify, merchant says we tried to abort the payment - * after it was successful. We should pass the JSON reply to the - * application */ - break; - case MHD_HTTP_NOT_FOUND: - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); - /* Nothing really to verify, this should never - happen, we should pass the 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_INTERNAL_SERVER_ERROR: - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); - /* Server had an internal issue; we should retry, - but this API leaves this to the application */ - break; - default: - TALER_MERCHANT_parse_error_details_ (json, - response_code, - &hr); - /* unexpected response code */ - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d\n", - (unsigned int) response_code, - (int) hr.ec); - GNUNET_break_op (0); - break; - } /* end of the switch */ - utph->cb (utph->cb_cls, - &hr); - // end of code to be removed - + TALER_MERCHANT_handle_post_using_templates_create_order (utph->cb_cls, utph->cb, response_code, json); TALER_MERCHANT_using_templates_post_cancel (utph); } @@ -165,7 +98,7 @@ TALER_MERCHANT_using_templates_post ( const char *template_id, const char *summary, const struct TALER_Amount *amount, - TALER_MERCHANT_UsingTemplatesPostCallback cb, + TALER_MERCHANT_PostOrdersCallback cb, void *cb_cls) { struct TALER_MERCHANT_UsingTemplatesPostHandle *utph; diff --git a/src/testing/test_merchant_api.c b/src/testing/test_merchant_api.c @@ -1370,35 +1370,35 @@ run (void *cls, MHD_HTTP_NO_CONTENT), TALER_TESTING_cmd_merchant_post_using_templates ( "using-templates-t1", - "post-templates-t1", + "template-1", merchant_url, "summary-1", "EUR:10", MHD_HTTP_OK), TALER_TESTING_cmd_merchant_post_using_templates ( "using-templates-t1-amount-missing", - "post-templates-t1", + "template-1", merchant_url, "summary-1", NULL, MHD_HTTP_CONFLICT), TALER_TESTING_cmd_merchant_post_using_templates ( "using-templates-t1-summary-missing", - "post-templates-t1", + "template-1", merchant_url, NULL, "EUR:10", MHD_HTTP_CONFLICT), TALER_TESTING_cmd_merchant_post_using_templates ( "using-templates-t1-amount-conflict", - "post-templates-t3-amount", + "template-amount", merchant_url, "summary-1", "EUR:10", MHD_HTTP_CONFLICT), TALER_TESTING_cmd_merchant_post_using_templates ( "using-templates-t1-amount-duplicate", - "post-templates-t3-amount", + "template-amount", merchant_url, "summary-1", "EUR:4",