merchant

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

merchant_api_post_tokenfamilies.c (8060B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2020-2024 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or modify
      6   it under the terms of the GNU Lesser General Public License as
      7   published by the Free Software Foundation; either version 2.1,
      8   or (at your option) any later version.
      9 
     10   TALER is distributed in the hope that it will be useful,
     11   but WITHOUT ANY WARRANTY; without even the implied warranty of
     12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13   GNU Lesser General Public License for more details.
     14 
     15   You should have received a copy of the GNU Lesser General
     16   Public License along with TALER; see the file COPYING.LGPL.
     17   If not, see <http://www.gnu.org/licenses/>
     18 */
     19 /**
     20  * @file merchant_api_post_tokenfamilies.c
     21  * @brief Implementation of the POST /tokenfamilies request
     22  *        of the merchant's HTTP API
     23  * @author Christian Blättler
     24  */
     25 #include "platform.h"
     26 #include <curl/curl.h>
     27 #include <gnunet/gnunet_json_lib.h>
     28 #include <gnunet/gnunet_time_lib.h>
     29 #include <jansson.h>
     30 #include <microhttpd.h> /* just for HTTP status codes */
     31 #include <gnunet/gnunet_util_lib.h>
     32 #include "taler_merchant_service.h"
     33 #include "merchant_api_curl_defaults.h"
     34 #include "merchant_api_common.h"
     35 #include <taler/taler_json_lib.h>
     36 #include <taler/taler_curl_lib.h>
     37 
     38 
     39 /**
     40  * Handle for a POST /tokenfamilies operation.
     41  */
     42 struct TALER_MERCHANT_TokenFamiliesPostHandle
     43 {
     44 
     45   /**
     46    * The url for this request.
     47    */
     48   char *url;
     49 
     50   /**
     51    * Handle for the request.
     52    */
     53   struct GNUNET_CURL_Job *job;
     54 
     55   /**
     56    * Function to call with the result.
     57    */
     58   TALER_MERCHANT_TokenFamiliesPostCallback cb;
     59 
     60   /**
     61    * Closure for @a cb.
     62    */
     63   void *cb_cls;
     64 
     65   /**
     66    * Reference to the execution context.
     67    */
     68   struct GNUNET_CURL_Context *ctx;
     69 
     70   /**
     71    * Minor context that holds body and headers.
     72    */
     73   struct TALER_CURL_PostContext post_ctx;
     74 
     75 };
     76 
     77 /**
     78  * Function called when we're done processing the
     79  * HTTP POST /tokenfamilies request.
     80  *
     81  * @param cls the `struct TALER_MERCHANT_TokenFamiliesPostHandle`
     82  * @param response_code HTTP response code, 0 on error
     83  * @param response response body, NULL if not in JSON
     84  */
     85 static void
     86 handle_post_token_families_finished (void *cls,
     87                                      long response_code,
     88                                      const void *response)
     89 {
     90   struct TALER_MERCHANT_TokenFamiliesPostHandle *handle = cls;
     91   const json_t *json = response;
     92   struct TALER_MERCHANT_HttpResponse hr = {
     93     .http_status = (unsigned int) response_code,
     94     .reply = json
     95   };
     96 
     97   handle->job = NULL;
     98   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     99               "POST /tokenfamilies completed with response code %u\n",
    100               (unsigned int) response_code);
    101   switch (response_code)
    102   {
    103   case 0:
    104     hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
    105     break;
    106   case MHD_HTTP_NO_CONTENT:
    107     break;
    108   case MHD_HTTP_BAD_REQUEST:
    109     hr.ec = TALER_JSON_get_error_code (json);
    110     hr.hint = TALER_JSON_get_error_hint (json);
    111     /* This should never happen, either us
    112      * or the merchant is buggy (or API version conflict);
    113      * just pass JSON reply to the application */
    114     break;
    115   case MHD_HTTP_UNAUTHORIZED:
    116     hr.ec = TALER_JSON_get_error_code (json);
    117     hr.hint = TALER_JSON_get_error_hint (json);
    118     /* Nothing really to verify, merchant says we need to authenticate. */
    119     break;
    120   case MHD_HTTP_FORBIDDEN:
    121     hr.ec = TALER_JSON_get_error_code (json);
    122     hr.hint = TALER_JSON_get_error_hint (json);
    123     /* Nothing really to verify, merchant says we tried to abort the payment
    124      * after it was successful. We should pass the JSON reply to the
    125      * application */
    126     break;
    127   case MHD_HTTP_NOT_FOUND:
    128     hr.ec = TALER_JSON_get_error_code (json);
    129     hr.hint = TALER_JSON_get_error_hint (json);
    130     /* Nothing really to verify, this should never
    131        happen, we should pass the JSON reply to the
    132        application */
    133     break;
    134   case MHD_HTTP_CONFLICT:
    135     hr.ec = TALER_JSON_get_error_code (json);
    136     hr.hint = TALER_JSON_get_error_hint (json);
    137     break;
    138   case MHD_HTTP_INTERNAL_SERVER_ERROR:
    139     hr.ec = TALER_JSON_get_error_code (json);
    140     hr.hint = TALER_JSON_get_error_hint (json);
    141     /* Server had an internal issue; we should retry,
    142        but this API leaves this to the application */
    143     break;
    144   default:
    145     TALER_MERCHANT_parse_error_details_ (json,
    146                                          response_code,
    147                                          &hr);
    148     /* unexpected response code */
    149     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    150                 "Unexpected response code %u/%d\n",
    151                 (unsigned int) response_code,
    152                 (int) hr.ec);
    153     GNUNET_break_op (0);
    154     break;
    155   }
    156   handle->cb (handle->cb_cls,
    157               &hr);
    158   TALER_MERCHANT_token_families_post_cancel (handle);
    159 }
    160 
    161 
    162 struct TALER_MERCHANT_TokenFamiliesPostHandle *
    163 TALER_MERCHANT_token_families_post (
    164   struct GNUNET_CURL_Context *ctx,
    165   const char *backend_url,
    166   const char *slug,
    167   const char *name,
    168   const char *description,
    169   const json_t *description_i18n,
    170   const json_t *extra_data,
    171   struct GNUNET_TIME_Timestamp valid_after,
    172   struct GNUNET_TIME_Timestamp valid_before,
    173   struct GNUNET_TIME_Relative duration,
    174   struct GNUNET_TIME_Relative validity_granularity,
    175   struct GNUNET_TIME_Relative start_offset,
    176   const char *kind,
    177   TALER_MERCHANT_TokenFamiliesPostCallback cb,
    178   void *cb_cls)
    179 {
    180   struct TALER_MERCHANT_TokenFamiliesPostHandle *handle;
    181   json_t *req_obj;
    182 
    183   req_obj = GNUNET_JSON_PACK (
    184     GNUNET_JSON_pack_string ("slug",
    185                              slug),
    186     GNUNET_JSON_pack_string ("name",
    187                              name),
    188     GNUNET_JSON_pack_string ("description",
    189                              description),
    190     GNUNET_JSON_pack_allow_null (
    191       GNUNET_JSON_pack_object_incref ("description_i18n",
    192                                       (json_t *) description_i18n)),
    193     GNUNET_JSON_pack_allow_null (
    194       GNUNET_JSON_pack_object_incref ("extra_data",
    195                                       (json_t *) extra_data)),
    196     GNUNET_JSON_pack_allow_null (
    197       GNUNET_JSON_pack_timestamp ("valid_after",
    198                                   valid_after)),
    199     GNUNET_JSON_pack_timestamp ("valid_before",
    200                                 valid_before),
    201     GNUNET_JSON_pack_time_rel ("duration",
    202                                duration),
    203     GNUNET_JSON_pack_time_rel ("validity_granularity",
    204                                validity_granularity),
    205     GNUNET_JSON_pack_time_rel ("start_offset",
    206                                start_offset),
    207     GNUNET_JSON_pack_string ("kind",
    208                              kind));
    209   handle = GNUNET_new (struct TALER_MERCHANT_TokenFamiliesPostHandle);
    210   handle->ctx = ctx;
    211   handle->cb = cb;
    212   handle->cb_cls = cb_cls;
    213   handle->url = TALER_url_join (backend_url,
    214                                 "private/tokenfamilies",
    215                                 NULL);
    216   if (NULL == handle->url)
    217   {
    218 
    219     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    220                 "Could not construct request URL.\n");
    221     json_decref (req_obj);
    222     GNUNET_free (handle);
    223     return NULL;
    224   }
    225   {
    226     CURL *eh;
    227 
    228     eh = TALER_MERCHANT_curl_easy_get_ (handle->url);
    229     GNUNET_assert (GNUNET_OK ==
    230                    TALER_curl_easy_post (&handle->post_ctx,
    231                                          eh,
    232                                          req_obj));
    233     json_decref (req_obj);
    234     handle->job = GNUNET_CURL_job_add2 (ctx,
    235                                         eh,
    236                                         handle->post_ctx.headers,
    237                                         &handle_post_token_families_finished,
    238                                         handle);
    239     GNUNET_assert (NULL != handle->job);
    240   }
    241   return handle;
    242 }
    243 
    244 
    245 void
    246 TALER_MERCHANT_token_families_post_cancel (
    247   struct TALER_MERCHANT_TokenFamiliesPostHandle *pph)
    248 {
    249   if (NULL != pph->job)
    250   {
    251     GNUNET_CURL_job_cancel (pph->job);
    252     pph->job = NULL;
    253   }
    254   TALER_curl_easy_post_finished (&pph->post_ctx);
    255   GNUNET_free (pph->url);
    256   GNUNET_free (pph);
    257 }