merchant

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

merchant_api_get_tokenfamily.c (6927B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2023-2024 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or modify it under the
      6   terms of the GNU Lesser General Public License as published by the Free Software
      7   Foundation; either version 2.1, or (at your option) any later version.
      8 
      9   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
     10   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11   A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
     12 
     13   You should have received a copy of the GNU Lesser General Public License along with
     14   TALER; see the file COPYING.LGPL.  If not, see
     15   <http://www.gnu.org/licenses/>
     16 */
     17 /**
     18  * @file merchant_api_get_tokenfamily.c
     19  * @brief Implementation of the GET /tokenfamily/$ID request of the merchant's HTTP API
     20  * @author Christian Blättler
     21  */
     22 #include "platform.h"
     23 #include <curl/curl.h>
     24 #include <gnunet/gnunet_common.h>
     25 #include <gnunet/gnunet_json_lib.h>
     26 #include <jansson.h>
     27 #include <microhttpd.h> /* just for HTTP status codes */
     28 #include <gnunet/gnunet_util_lib.h>
     29 #include <gnunet/gnunet_curl_lib.h>
     30 #include "taler_merchant_service.h"
     31 #include "merchant_api_curl_defaults.h"
     32 #include <taler/taler_json_lib.h>
     33 #include <taler/taler_signatures.h>
     34 
     35 
     36 /**
     37  * Handle for a GET /tokenfamilies/$SLUG operation.
     38  */
     39 struct TALER_MERCHANT_TokenFamilyGetHandle
     40 {
     41   /**
     42    * The url for this request.
     43    */
     44   char *url;
     45 
     46   /**
     47    * Handle for the request.
     48    */
     49   struct GNUNET_CURL_Job *job;
     50 
     51   /**
     52    * Function to call with the result.
     53    */
     54   TALER_MERCHANT_TokenFamilyGetCallback cb;
     55 
     56   /**
     57    * Closure for @a cb.
     58    */
     59   void *cb_cls;
     60 
     61   /**
     62    * Reference to the execution context.
     63    */
     64   struct GNUNET_CURL_Context *ctx;
     65 
     66 };
     67 
     68 
     69 /**
     70  * Function called when we're done processing the
     71  * HTTP GET /tokenfamilies/$ID request.
     72  *
     73  * @param cls the `struct TALER_MERCHANT_TokenFamilyGetHandle`
     74  * @param response_code HTTP response code, 0 on error
     75  * @param response response body, NULL if not in JSON
     76  */
     77 static void
     78 handle_get_token_family_finished (void *cls,
     79                                   long response_code,
     80                                   const void *response)
     81 {
     82   struct TALER_MERCHANT_TokenFamilyGetHandle *handle = cls;
     83   const json_t *json = response;
     84   struct TALER_MERCHANT_TokenFamilyGetResponse res = {
     85     .hr.http_status = (unsigned int) response_code,
     86     .hr.reply = json
     87   };
     88 
     89   handle->job = NULL;
     90   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     91               "Got /tokenfamilies/$ID response with status code %u\n",
     92               (unsigned int) response_code);
     93   switch (response_code)
     94   {
     95   case MHD_HTTP_OK:
     96     {
     97       // Parse token family response
     98       struct GNUNET_JSON_Specification spec[] = {
     99         GNUNET_JSON_spec_string ("slug",
    100                                  &res.details.ok.slug),
    101         GNUNET_JSON_spec_string ("name",
    102                                  &res.details.ok.name),
    103         GNUNET_JSON_spec_string ("description",
    104                                  &res.details.ok.description),
    105         GNUNET_JSON_spec_object_const ("description_i18n",
    106                                        &res.details.ok.description_i18n),
    107         GNUNET_JSON_spec_object_const ("extra_data",
    108                                        &res.details.ok.extra_data),
    109         GNUNET_JSON_spec_timestamp ("valid_after",
    110                                     &res.details.ok.valid_after),
    111         GNUNET_JSON_spec_timestamp ("valid_before",
    112                                     &res.details.ok.valid_before),
    113         GNUNET_JSON_spec_relative_time ("duation",
    114                                         &res.details.ok.duration),
    115         GNUNET_JSON_spec_relative_time ("validity_granularity",
    116                                         &res.details.ok.validity_granularity),
    117         GNUNET_JSON_spec_relative_time ("start_offset",
    118                                         &res.details.ok.start_offset),
    119         GNUNET_JSON_spec_string ("kind",
    120                                  &res.details.ok.kind),
    121         GNUNET_JSON_spec_uint64 ("issued",
    122                                  &res.details.ok.issued),
    123         GNUNET_JSON_spec_uint64 ("used",
    124                                  &res.details.ok.used),
    125         GNUNET_JSON_spec_end ()
    126       };
    127 
    128       if (GNUNET_OK ==
    129           GNUNET_JSON_parse (json,
    130                              spec,
    131                              NULL, NULL))
    132       {
    133         handle->cb (handle->cb_cls,
    134                     &res);
    135         GNUNET_JSON_parse_free (spec);
    136         TALER_MERCHANT_token_family_get_cancel (handle);
    137         return;
    138       }
    139       res.hr.http_status = 0;
    140       res.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
    141       break;
    142     }
    143   case MHD_HTTP_UNAUTHORIZED:
    144     res.hr.ec = TALER_JSON_get_error_code (json);
    145     res.hr.hint = TALER_JSON_get_error_hint (json);
    146     /* Nothing really to verify, merchant says we need to authenticate. */
    147     break;
    148   case MHD_HTTP_NOT_FOUND:
    149     res.hr.ec = TALER_JSON_get_error_code (json);
    150     res.hr.hint = TALER_JSON_get_error_hint (json);
    151     break;
    152   default:
    153     /* unexpected response code */
    154     res.hr.ec = TALER_JSON_get_error_code (json);
    155     res.hr.hint = TALER_JSON_get_error_hint (json);
    156     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    157                 "Unexpected response code %u/%d\n",
    158                 (unsigned int) response_code,
    159                 (int) res.hr.ec);
    160     break;
    161   }
    162 }
    163 
    164 
    165 struct TALER_MERCHANT_TokenFamilyGetHandle *
    166 TALER_MERCHANT_token_family_get (
    167   struct GNUNET_CURL_Context *ctx,
    168   const char *backend_url,
    169   const char *token_family_slug,
    170   TALER_MERCHANT_TokenFamilyGetCallback cb,
    171   void *cb_cls)
    172 {
    173   struct TALER_MERCHANT_TokenFamilyGetHandle *handle;
    174   CURL *eh;
    175 
    176   handle = GNUNET_new (struct TALER_MERCHANT_TokenFamilyGetHandle);
    177   handle->ctx = ctx;
    178   handle->cb = cb;
    179   handle->cb_cls = cb_cls;
    180   {
    181     char *path;
    182 
    183     GNUNET_asprintf (&path,
    184                      "private/tokenfamilies/%s",
    185                      token_family_slug);
    186     handle->url = TALER_url_join (backend_url,
    187                                   path,
    188                                   NULL);
    189     GNUNET_free (path);
    190   }
    191   if (NULL == handle->url)
    192   {
    193     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    194                 "Could not construct request URL.\n");
    195     GNUNET_free (handle);
    196     return NULL;
    197   }
    198   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    199               "Requesting URL '%s'\n",
    200               handle->url);
    201   eh = TALER_MERCHANT_curl_easy_get_ (handle->url);
    202   handle->job = GNUNET_CURL_job_add (ctx,
    203                                      eh,
    204                                      &handle_get_token_family_finished,
    205                                      handle);
    206   return handle;
    207 }
    208 
    209 
    210 void
    211 TALER_MERCHANT_token_family_get_cancel (
    212   struct TALER_MERCHANT_TokenFamilyGetHandle *handle)
    213 {
    214   if (NULL != handle->job)
    215     GNUNET_CURL_job_cancel (handle->job);
    216   GNUNET_free (handle->url);
    217   GNUNET_free (handle);
    218 }