merchant

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

commit 778176a664c9ecf96073ffbc2e1823a4366fd37a
parent 843f00401878a2db69cea3d3a5f72f27bd763070
Author: Christian Grothoff <christian@grothoff.org>
Date:   Fri, 16 Apr 2021 23:38:46 +0200

use POST instead of PATCH

Diffstat:
Msrc/include/taler_merchant_service.h | 24++++++++++++++++++------
Msrc/lib/Makefile.am | 2+-
Dsrc/lib/merchant_api_patch_instance_auth.c | 229-------------------------------------------------------------------------------
Asrc/lib/merchant_api_post_instance_auth.c | 229+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 248 insertions(+), 236 deletions(-)

diff --git a/src/include/taler_merchant_service.h b/src/include/taler_merchant_service.h @@ -613,7 +613,19 @@ TALER_MERCHANT_instance_patch_cancel ( /** * Handle for an operation to modify authentication settings. */ -struct TALER_MERCHANT_InstanceAuthPatchHande; +struct TALER_MERCHANT_InstanceAuthPostHande; + + +/** + * Function called with the result of the GET /instances/$ID operation. + * + * @param cls closure + * @param hr HTTP response data + */ +typedef void +(*TALER_MERCHANT_InstanceAuthPostCallback)( + void *cls, + const struct TALER_MERCHANT_HttpResponse *hr); /** @@ -630,13 +642,13 @@ struct TALER_MERCHANT_InstanceAuthPatchHande; * @param cb_cls closure for @a config_cb * @return the instances handle; NULL upon error */ -struct TALER_MERCHANT_InstanceAuthPatchHandle * -TALER_MERCHANT_instance_auth_patch ( +struct TALER_MERCHANT_InstanceAuthPostHandle * +TALER_MERCHANT_instance_auth_post ( struct GNUNET_CURL_Context *ctx, const char *backend_url, const char *instance_id, const char *auth_token, - TALER_MERCHANT_InstancePatchCallback cb, + TALER_MERCHANT_InstanceAuthPostCallback cb, void *cb_cls); @@ -648,8 +660,8 @@ TALER_MERCHANT_instance_auth_patch ( * @param iaph request to cancel. */ void -TALER_MERCHANT_instance_auth_patch_cancel ( - struct TALER_MERCHANT_InstanceAuthPatchHandle *iaph); +TALER_MERCHANT_instance_auth_post_cancel ( + struct TALER_MERCHANT_InstanceAuthPostHandle *iaph); /** diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am @@ -34,7 +34,7 @@ libtalermerchant_la_SOURCES = \ merchant_api_patch_instance.c \ merchant_api_patch_order_forget.c \ merchant_api_patch_product.c \ - merchant_api_patch_instance_auth.c \ + merchant_api_post_instance_auth.c \ merchant_api_post_instances.c \ merchant_api_post_orders.c \ merchant_api_post_order_abort.c \ diff --git a/src/lib/merchant_api_patch_instance_auth.c b/src/lib/merchant_api_patch_instance_auth.c @@ -1,229 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014-2018, 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 merchant_api_patch_instance_auth.c - * @brief Implementation of the PATCH /instance/$ID/private/auth request - * @author Christian Grothoff - */ -#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> - - -/** - * Handle for a PATCH /instances/$ID/private/auth operation. - */ -struct TALER_MERCHANT_InstanceAuthPatchHandle -{ - /** - * The url for this request. - */ - char *url; - - /** - * Handle for the request. - */ - struct GNUNET_CURL_Job *job; - - /** - * Function to call with the result. - */ - TALER_MERCHANT_InstancePatchCallback 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 GET /instances/$ID/private/auth request. - * - * @param cls the `struct TALER_MERCHANT_InstanceAuthPatchHandle` - * @param response_code HTTP response code, 0 on error - * @param response response body, NULL if not in JSON - */ -static void -handle_patch_instance_auth_finished (void *cls, - long response_code, - const void *response) -{ - struct TALER_MERCHANT_InstanceAuthPatchHandle *iaph = cls; - const json_t *json = response; - struct TALER_MERCHANT_HttpResponse hr = { - .http_status = (unsigned int) response_code, - .reply = json - }; - - iaph->job = NULL; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Got /instances/$ID response with status code %u\n", - (unsigned int) response_code); - switch (response_code) - { - case MHD_HTTP_NO_CONTENT: - break; - case MHD_HTTP_UNAUTHORIZED: - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); - /* Nothing really to verify, merchant says we need to authenticate. */ - 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); - break; - } - iaph->cb (iaph->cb_cls, - &hr); - TALER_MERCHANT_instance_auth_patch_cancel (iaph); -} - - -struct TALER_MERCHANT_InstanceAuthPatchHandle * -TALER_MERCHANT_instance_auth_patch ( - struct GNUNET_CURL_Context *ctx, - const char *backend_url, - const char *instance_id, - const char *auth_token, - TALER_MERCHANT_InstancePatchCallback cb, - void *cb_cls) -{ - struct TALER_MERCHANT_InstanceAuthPatchHandle *iaph; - json_t *req_obj; - - iaph = GNUNET_new (struct TALER_MERCHANT_InstanceAuthPatchHandle); - iaph->ctx = ctx; - iaph->cb = cb; - iaph->cb_cls = cb_cls; - if (NULL != instance_id) - { - char *path; - - GNUNET_asprintf (&path, - "instances/%s/private/auth", - instance_id); - iaph->url = TALER_url_join (backend_url, - path, - NULL); - GNUNET_free (path); - } - else - { - /* backend_url is already identifying the instance */ - iaph->url = TALER_url_join (backend_url, - "/private/auth", - NULL); - } - if (NULL == iaph->url) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Could not construct request URL.\n"); - GNUNET_free (iaph); - return NULL; - } - if (NULL == auth_token) - { - req_obj = json_pack ("{s:s}", - "method", - "external"); - } - else - { - req_obj = json_pack ("{s:s, s:s}", - "method", - "token", - "token", - auth_token); - } - if (NULL == req_obj) - { - GNUNET_break (0); - GNUNET_free (iaph->url); - GNUNET_free (iaph); - return NULL; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Requesting URL '%s'\n", - iaph->url); - { - CURL *eh; - - eh = curl_easy_init (); - if (GNUNET_OK != - TALER_curl_easy_post (&iaph->post_ctx, - eh, - req_obj)) - { - GNUNET_break (0); - json_decref (req_obj); - GNUNET_free (iaph->url); - GNUNET_free (iaph); - return NULL; - } - json_decref (req_obj); - GNUNET_assert (CURLE_OK == - curl_easy_setopt (eh, - CURLOPT_URL, - iaph->url)); - GNUNET_assert (CURLE_OK == - curl_easy_setopt (eh, - CURLOPT_CUSTOMREQUEST, - MHD_HTTP_METHOD_POST)); // FIXME: PATCH? - iaph->job = GNUNET_CURL_job_add (ctx, - eh, - &handle_patch_instance_auth_finished, - iaph); - } - return iaph; -} - - -void -TALER_MERCHANT_instance_auth_patch_cancel ( - struct TALER_MERCHANT_InstanceAuthPatchHandle *iaph) -{ - if (NULL != iaph->job) - GNUNET_CURL_job_cancel (iaph->job); - TALER_curl_easy_post_finished (&iaph->post_ctx); - GNUNET_free (iaph->url); - GNUNET_free (iaph); -} diff --git a/src/lib/merchant_api_post_instance_auth.c b/src/lib/merchant_api_post_instance_auth.c @@ -0,0 +1,229 @@ +/* + This file is part of TALER + Copyright (C) 2014-2018, 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 merchant_api_post_instance_auth.c + * @brief Implementation of the POST /instance/$ID/private/auth request + * @author Christian Grothoff + */ +#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> + + +/** + * Handle for a POST /instances/$ID/private/auth operation. + */ +struct TALER_MERCHANT_InstanceAuthPostHandle +{ + /** + * The url for this request. + */ + char *url; + + /** + * Handle for the request. + */ + struct GNUNET_CURL_Job *job; + + /** + * Function to call with the result. + */ + TALER_MERCHANT_InstanceAuthPostCallback 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 GET /instances/$ID/private/auth request. + * + * @param cls the `struct TALER_MERCHANT_InstanceAuthPostHandle` + * @param response_code HTTP response code, 0 on error + * @param response response body, NULL if not in JSON + */ +static void +handle_post_instance_auth_finished (void *cls, + long response_code, + const void *response) +{ + struct TALER_MERCHANT_InstanceAuthPostHandle *iaph = cls; + const json_t *json = response; + struct TALER_MERCHANT_HttpResponse hr = { + .http_status = (unsigned int) response_code, + .reply = json + }; + + iaph->job = NULL; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Got /instances/$ID response with status code %u\n", + (unsigned int) response_code); + switch (response_code) + { + case MHD_HTTP_NO_CONTENT: + break; + case MHD_HTTP_UNAUTHORIZED: + hr.ec = TALER_JSON_get_error_code (json); + hr.hint = TALER_JSON_get_error_hint (json); + /* Nothing really to verify, merchant says we need to authenticate. */ + 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); + break; + } + iaph->cb (iaph->cb_cls, + &hr); + TALER_MERCHANT_instance_auth_post_cancel (iaph); +} + + +struct TALER_MERCHANT_InstanceAuthPostHandle * +TALER_MERCHANT_instance_auth_post ( + struct GNUNET_CURL_Context *ctx, + const char *backend_url, + const char *instance_id, + const char *auth_token, + TALER_MERCHANT_InstanceAuthPostCallback cb, + void *cb_cls) +{ + struct TALER_MERCHANT_InstanceAuthPostHandle *iaph; + json_t *req_obj; + + iaph = GNUNET_new (struct TALER_MERCHANT_InstanceAuthPostHandle); + iaph->ctx = ctx; + iaph->cb = cb; + iaph->cb_cls = cb_cls; + if (NULL != instance_id) + { + char *path; + + GNUNET_asprintf (&path, + "instances/%s/private/auth", + instance_id); + iaph->url = TALER_url_join (backend_url, + path, + NULL); + GNUNET_free (path); + } + else + { + /* backend_url is already identifying the instance */ + iaph->url = TALER_url_join (backend_url, + "/private/auth", + NULL); + } + if (NULL == iaph->url) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Could not construct request URL.\n"); + GNUNET_free (iaph); + return NULL; + } + if (NULL == auth_token) + { + req_obj = json_pack ("{s:s}", + "method", + "external"); + } + else + { + req_obj = json_pack ("{s:s, s:s}", + "method", + "token", + "token", + auth_token); + } + if (NULL == req_obj) + { + GNUNET_break (0); + GNUNET_free (iaph->url); + GNUNET_free (iaph); + return NULL; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Requesting URL '%s'\n", + iaph->url); + { + CURL *eh; + + eh = curl_easy_init (); + if (GNUNET_OK != + TALER_curl_easy_post (&iaph->post_ctx, + eh, + req_obj)) + { + GNUNET_break (0); + json_decref (req_obj); + GNUNET_free (iaph->url); + GNUNET_free (iaph); + return NULL; + } + json_decref (req_obj); + GNUNET_assert (CURLE_OK == + curl_easy_setopt (eh, + CURLOPT_URL, + iaph->url)); + GNUNET_assert (CURLE_OK == + curl_easy_setopt (eh, + CURLOPT_CUSTOMREQUEST, + MHD_HTTP_METHOD_POST)); // FIXME: POST? + iaph->job = GNUNET_CURL_job_add (ctx, + eh, + &handle_post_instance_auth_finished, + iaph); + } + return iaph; +} + + +void +TALER_MERCHANT_instance_auth_post_cancel ( + struct TALER_MERCHANT_InstanceAuthPostHandle *iaph) +{ + if (NULL != iaph->job) + GNUNET_CURL_job_cancel (iaph->job); + TALER_curl_easy_post_finished (&iaph->post_ctx); + GNUNET_free (iaph->url); + GNUNET_free (iaph); +}