merchant

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

commit 3d9b1a2af013b12929af8850ffa4618e5608ae3f
parent 52f50bed405b6048b7c81cb1645e3d536e272430
Author: bohdan-potuzhnyi <bohdan.potuzhnyi@gmail.com>
Date:   Fri,  6 Dec 2024 09:20:50 +0100

adding new donau c-api

Diffstat:
Msrc/lib/Makefile.am | 3++-
Asrc/lib/merchant_api_post_donau_instance.c | 248+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 250 insertions(+), 1 deletion(-)

diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am @@ -84,7 +84,8 @@ libtalermerchant_la_LIBADD = \ if HAVE_DONAU libtalermerchant_la_SOURCES += \ - merchant_api_get_donau_instance.c + merchant_api_get_donau_instance.c \ + merchant_api_post_donau_instance.c libtalermerchant_la_LIBADD += \ -ldonau diff --git a/src/lib/merchant_api_post_donau_instance.c b/src/lib/merchant_api_post_donau_instance.c @@ -0,0 +1,247 @@ +/* + This file is part of TALER + Copyright (C) 2024 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_donau_instance.c + * @brief Implementation of the POST /donau request + * of the merchant's HTTP API + * @author Bohdan Potuzhnyi + * @author Vlada Svirsh + */ +#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 "taler_merchant_service.h" +#include "merchant_api_curl_defaults.h" +#include "merchant_api_common.h" +#include <taler/taler_json_lib.h> +#include <taler/taler_signatures.h> +#include <taler/taler_curl_lib.h> +#include <taler/taler_kyclogic_lib.h> +/* DONAU RELATED IMPORTS */ +#include "taler_merchant_donau.h" +#include <donau/donau_service.h> + + +/** + * Handle for a POST /donau operation. + */ +struct TALER_MERCHANT_DonauInstancePostHandle +{ + /** + * URL for this request. + */ + char *url; + + /** + * Handle for the CURL job. + */ + struct GNUNET_CURL_Job *job; + + /** + * Function to call with the result. + */ + TALER_MERCHANT_DonauInstancePostCallback 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 the POST /donau operation is finished. + * + * @param cls the `struct TALER_MERCHANT_DonauInstancePostHandle` + * @param response_code HTTP response code, 0 on error + * @param response response body, NULL if not in JSON + */ +static void +handle_post_donau_finished (void *cls, + long response_code, + const void *response) +{ + struct TALER_MERCHANT_DonauInstancePostHandle *dph = cls; + const json_t *json = response; + struct TALER_MERCHANT_HttpResponse hr = { + .http_status = (unsigned int) response_code, + .reply = json + }; + + dph->job = NULL; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "POST /donau 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_BAD_REQUEST: + case MHD_HTTP_INTERNAL_SERVER_ERROR: + hr.ec = TALER_JSON_get_error_code (json); + hr.hint = TALER_JSON_get_error_hint (json); + break; + default: + TALER_MERCHANT_parse_error_details_ (json, + response_code, + &hr); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unexpected response code %u/%d\n", + (unsigned int) response_code, + (int) hr.ec); + break; + } + + dph->cb (dph->cb_cls, + &hr); + TALER_MERCHANT_donau_instances_post_cancel (dph); +} + + +struct TALER_MERCHANT_DonauInstancePostHandle * +TALER_MERCHANT_donau_instances_post ( + struct GNUNET_CURL_Context *ctx, + const char *backend_url, + const struct TALER_MERCHANT_DONAU_Charity *charity, + const char *auth_token, + TALER_MERCHANT_DonauInstancePostCallback cb, + void *cb_cls) +{ + struct TALER_MERCHANT_DonauInstancePostHandle *dph; + json_t *req_obj; + json_t *auth_obj; + + if (NULL != auth_token) + { + if (0 != strncasecmp (RFC_8959_PREFIX, + auth_token, + strlen (RFC_8959_PREFIX))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Authentication token must start with `%s'\n", + RFC_8959_PREFIX); + return NULL; + } + auth_obj = GNUNET_JSON_PACK ( + GNUNET_JSON_pack_string ("method", + "token"), + GNUNET_JSON_pack_string ("token", + auth_token)); + } + else + { + auth_obj = GNUNET_JSON_PACK ( + GNUNET_JSON_pack_string ("method", + "external")); + } + if (NULL == auth_obj) + { + GNUNET_break (0); + return NULL; + } + + req_obj = GNUNET_JSON_PACK ( + GNUNET_JSON_pack_string ("donau_url", + charity->charity_url), + GNUNET_JSON_pack_string ("charity_name", + charity->name), + GNUNET_JSON_pack_data_auto ("charity_pub_key", + &charity->charity_pub), + GNUNET_JSON_pack_uint64 ("charity_id", + charity->charity_id), + TALER_JSON_pack_amount ("max_per_year", + &charity->max_per_year), + TALER_JSON_pack_amount ("receipts_to_date", + &charity->receipts_to_date), + GNUNET_JSON_pack_uint64 ("current_year", + charity->current_year) + ); + + dph = GNUNET_new (struct TALER_MERCHANT_DonauInstancePostHandle); + dph->ctx = ctx; + dph->cb = cb; + dph->cb_cls = cb_cls; + dph->url = TALER_url_join (backend_url, + "donau", + NULL); + + if (NULL == dph->url) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to construct request URL\n"); + json_decref (req_obj); + GNUNET_free (dph); + return NULL; + } + { + CURL *eh; + + eh = TALER_MERCHANT_curl_easy_get_(dph->url); + if (GNUNET_OK != TALER_curl_easy_post(&dph->post_ctx, eh, req_obj)) + { + GNUNET_break(0); + curl_easy_cleanup(eh); + json_decref(req_obj); + GNUNET_free(dph); + return NULL; + } + + json_decref(req_obj); + + dph->job = GNUNET_CURL_job_add2(ctx, + eh, + dph->post_ctx.headers, + &handle_post_donau_finished, + dph); + } + return dph; +} + +void +TALER_MERCHANT_donau_instances_post_cancel ( + struct TALER_MERCHANT_DonauInstancePostHandle *dph) +{ + if (NULL != dph->job) + { + GNUNET_CURL_job_cancel (dph->job); + dph->job = NULL; + } + TALER_curl_easy_post_finished (&dph->post_ctx); + GNUNET_free (dph->url); + GNUNET_free (dph); +} + +/* end of merchant_api_post_donau_instance.c */ +\ No newline at end of file