merchant

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

merchant_api_patch-private-orders-ORDER_ID-forget.c (8129B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2020-2026 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_patch-private-orders-ORDER_ID-forget-new.c
     21  * @brief Implementation of the PATCH /private/orders/$ORDER_ID/forget request
     22  * @author Jonathan Buchanan
     23  */
     24 #include "taler/platform.h"
     25 #include <curl/curl.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/taler-merchant/patch-private-orders-ORDER_ID-forget.h>
     31 #include "merchant_api_curl_defaults.h"
     32 #include "merchant_api_common.h"
     33 #include <taler/taler_json_lib.h>
     34 #include <taler/taler_curl_lib.h>
     35 
     36 
     37 /**
     38  * Handle for a PATCH /private/orders/$ORDER_ID/forget operation.
     39  */
     40 struct TALER_MERCHANT_PatchPrivateOrdersForgetHandle
     41 {
     42   /**
     43    * Base URL of the merchant backend.
     44    */
     45   char *base_url;
     46 
     47   /**
     48    * The full URL for this request.
     49    */
     50   char *url;
     51 
     52   /**
     53    * Handle for the request.
     54    */
     55   struct GNUNET_CURL_Job *job;
     56 
     57   /**
     58    * Function to call with the result.
     59    */
     60   TALER_MERCHANT_PatchPrivateOrdersForgetCallback cb;
     61 
     62   /**
     63    * Closure for @a cb.
     64    */
     65   TALER_MERCHANT_PATCH_PRIVATE_ORDERS_FORGET_RESULT_CLOSURE *cb_cls;
     66 
     67   /**
     68    * Reference to the execution context.
     69    */
     70   struct GNUNET_CURL_Context *ctx;
     71 
     72   /**
     73    * Minor context that holds body and headers.
     74    */
     75   struct TALER_CURL_PostContext post_ctx;
     76 
     77   /**
     78    * Order identifier.
     79    */
     80   char *order_id;
     81 
     82   /**
     83    * Array of JSON pointer paths to redact.
     84    */
     85   char **fields;
     86 
     87   /**
     88    * Number of entries in @e fields.
     89    */
     90   unsigned int fields_length;
     91 };
     92 
     93 
     94 /**
     95  * Function called when we're done processing the
     96  * HTTP PATCH /private/orders/$ORDER_ID/forget request.
     97  *
     98  * @param cls the `struct TALER_MERCHANT_PatchPrivateOrdersForgetHandle`
     99  * @param response_code HTTP response code, 0 on error
    100  * @param response response body, NULL if not in JSON
    101  */
    102 static void
    103 handle_patch_orders_forget_finished (void *cls,
    104                                      long response_code,
    105                                      const void *response)
    106 {
    107   struct TALER_MERCHANT_PatchPrivateOrdersForgetHandle *ofh = cls;
    108   const json_t *json = response;
    109   struct TALER_MERCHANT_PatchPrivateOrdersForgetResponse por = {
    110     .hr.http_status = (unsigned int) response_code,
    111     .hr.reply = json
    112   };
    113 
    114   ofh->job = NULL;
    115   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    116               "PATCH /private/orders/$ORDER_ID/forget completed with response code %u\n",
    117               (unsigned int) response_code);
    118   switch (response_code)
    119   {
    120   case 0:
    121     por.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
    122     break;
    123   case MHD_HTTP_OK:
    124     /* fields were NOW forgotten */
    125     break;
    126   case MHD_HTTP_NO_CONTENT:
    127     /* fields were already forgotten before */
    128     break;
    129   case MHD_HTTP_BAD_REQUEST:
    130     por.hr.ec = TALER_JSON_get_error_code (json);
    131     por.hr.hint = TALER_JSON_get_error_hint (json);
    132     break;
    133   case MHD_HTTP_UNAUTHORIZED:
    134     por.hr.ec = TALER_JSON_get_error_code (json);
    135     por.hr.hint = TALER_JSON_get_error_hint (json);
    136     break;
    137   case MHD_HTTP_NOT_FOUND:
    138     por.hr.ec = TALER_JSON_get_error_code (json);
    139     por.hr.hint = TALER_JSON_get_error_hint (json);
    140     break;
    141   case MHD_HTTP_CONFLICT:
    142     por.hr.ec = TALER_JSON_get_error_code (json);
    143     por.hr.hint = TALER_JSON_get_error_hint (json);
    144     break;
    145   case MHD_HTTP_INTERNAL_SERVER_ERROR:
    146     por.hr.ec = TALER_JSON_get_error_code (json);
    147     por.hr.hint = TALER_JSON_get_error_hint (json);
    148     break;
    149   default:
    150     TALER_MERCHANT_parse_error_details_ (json,
    151                                          response_code,
    152                                          &por.hr);
    153     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    154                 "Unexpected response code %u/%d\n",
    155                 (unsigned int) response_code,
    156                 (int) por.hr.ec);
    157     GNUNET_break_op (0);
    158     break;
    159   }
    160   ofh->cb (ofh->cb_cls,
    161            &por);
    162   TALER_MERCHANT_patch_private_orders_forget_cancel (ofh);
    163 }
    164 
    165 
    166 struct TALER_MERCHANT_PatchPrivateOrdersForgetHandle *
    167 TALER_MERCHANT_patch_private_orders_forget_create (
    168   struct GNUNET_CURL_Context *ctx,
    169   const char *url,
    170   const char *order_id,
    171   unsigned int fields_length,
    172   const char *fields[static fields_length])
    173 {
    174   struct TALER_MERCHANT_PatchPrivateOrdersForgetHandle *ofh;
    175 
    176   ofh = GNUNET_new (struct TALER_MERCHANT_PatchPrivateOrdersForgetHandle);
    177   ofh->ctx = ctx;
    178   ofh->base_url = GNUNET_strdup (url);
    179   ofh->order_id = GNUNET_strdup (order_id);
    180   ofh->fields_length = fields_length;
    181   ofh->fields = GNUNET_new_array (fields_length,
    182                                   char *);
    183   for (unsigned int i = 0; i < fields_length; i++)
    184     ofh->fields[i] = GNUNET_strdup (fields[i]);
    185   return ofh;
    186 }
    187 
    188 
    189 enum TALER_ErrorCode
    190 TALER_MERCHANT_patch_private_orders_forget_start (
    191   struct TALER_MERCHANT_PatchPrivateOrdersForgetHandle *ofh,
    192   TALER_MERCHANT_PatchPrivateOrdersForgetCallback cb,
    193   TALER_MERCHANT_PATCH_PRIVATE_ORDERS_FORGET_RESULT_CLOSURE *cb_cls)
    194 {
    195   json_t *req_fields;
    196   json_t *req_obj;
    197   CURL *eh;
    198 
    199   ofh->cb = cb;
    200   ofh->cb_cls = cb_cls;
    201   {
    202     char *path;
    203 
    204     GNUNET_asprintf (&path,
    205                      "private/orders/%s/forget",
    206                      ofh->order_id);
    207     ofh->url = TALER_url_join (ofh->base_url,
    208                                path,
    209                                NULL);
    210     GNUNET_free (path);
    211   }
    212   if (NULL == ofh->url)
    213     return TALER_EC_GENERIC_CONFIGURATION_INVALID;
    214   req_fields = json_array ();
    215   if (NULL == req_fields)
    216     return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
    217   for (unsigned int i = 0; i < ofh->fields_length; i++)
    218   {
    219     if (0 !=
    220         json_array_append_new (req_fields,
    221                                json_string (ofh->fields[i])))
    222     {
    223       json_decref (req_fields);
    224       return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
    225     }
    226   }
    227   req_obj = GNUNET_JSON_PACK (
    228     GNUNET_JSON_pack_array_steal ("fields",
    229                                   req_fields));
    230   eh = TALER_MERCHANT_curl_easy_get_ (ofh->url);
    231   if ( (NULL == eh) ||
    232        (GNUNET_OK !=
    233         TALER_curl_easy_post (&ofh->post_ctx,
    234                               eh,
    235                               req_obj)) )
    236   {
    237     GNUNET_break (0);
    238     json_decref (req_obj);
    239     if (NULL != eh)
    240       curl_easy_cleanup (eh);
    241     return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
    242   }
    243   json_decref (req_obj);
    244   GNUNET_assert (CURLE_OK ==
    245                  curl_easy_setopt (eh,
    246                                    CURLOPT_CUSTOMREQUEST,
    247                                    MHD_HTTP_METHOD_PATCH));
    248   ofh->job = GNUNET_CURL_job_add2 (ofh->ctx,
    249                                    eh,
    250                                    ofh->post_ctx.headers,
    251                                    &handle_patch_orders_forget_finished,
    252                                    ofh);
    253   if (NULL == ofh->job)
    254     return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
    255   return TALER_EC_NONE;
    256 }
    257 
    258 
    259 void
    260 TALER_MERCHANT_patch_private_orders_forget_cancel (
    261   struct TALER_MERCHANT_PatchPrivateOrdersForgetHandle *ofh)
    262 {
    263   if (NULL != ofh->job)
    264   {
    265     GNUNET_CURL_job_cancel (ofh->job);
    266     ofh->job = NULL;
    267   }
    268   TALER_curl_easy_post_finished (&ofh->post_ctx);
    269   for (unsigned int i = 0; i < ofh->fields_length; i++)
    270     GNUNET_free (ofh->fields[i]);
    271   GNUNET_free (ofh->fields);
    272   GNUNET_free (ofh->order_id);
    273   GNUNET_free (ofh->url);
    274   GNUNET_free (ofh->base_url);
    275   GNUNET_free (ofh);
    276 }
    277 
    278 
    279 /* end of merchant_api_patch-private-orders-ORDER_ID-forget-new.c */