merchant

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

merchant_api_post_orders.c (8623B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2014-2023 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, but
     11   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 Public
     16   License along with TALER; see the file COPYING.LGPL.  If not,
     17   see <http://www.gnu.org/licenses/>
     18 */
     19 /**
     20  * @file merchant_api_post_orders.c
     21  * @brief Implementation of the POST /orders
     22  * @author Christian Grothoff
     23  * @author Marcello Stanisci
     24  */
     25 #include "platform.h"
     26 #include <curl/curl.h>
     27 #include <jansson.h>
     28 #include <microhttpd.h> /* just for HTTP status codes */
     29 #include <gnunet/gnunet_util_lib.h>
     30 #include <gnunet/gnunet_curl_lib.h>
     31 #include "taler_merchant_service.h"
     32 #include "merchant_api_curl_defaults.h"
     33 #include "merchant_api_common.h"
     34 #include <taler/taler_json_lib.h>
     35 #include <taler/taler_signatures.h>
     36 #include <taler/taler_curl_lib.h>
     37 
     38 
     39 /**
     40  * @brief A POST /orders Handle
     41  */
     42 struct TALER_MERCHANT_PostOrdersHandle
     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_PostOrdersCallback 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 /orders request.
     80  *
     81  * @param cls the `struct TALER_MERCHANT_PostOrdersHandle`
     82  * @param response_code HTTP response code, 0 on error
     83  * @param response response body, NULL if not JSON
     84  */
     85 static void
     86 handle_post_order_finished (void *cls,
     87                             long response_code,
     88                             const void *response)
     89 {
     90   struct TALER_MERCHANT_PostOrdersHandle *po = cls;
     91   const json_t *json = response;
     92 
     93   po->job = NULL;
     94   TALER_MERCHANT_handle_order_creation_response_ (po->cb,
     95                                                   po->cb_cls,
     96                                                   response_code,
     97                                                   json);
     98   TALER_MERCHANT_orders_post_cancel (po);
     99 }
    100 
    101 
    102 struct TALER_MERCHANT_PostOrdersHandle *
    103 TALER_MERCHANT_orders_post (struct GNUNET_CURL_Context *ctx,
    104                             const char *backend_url,
    105                             const json_t *order,
    106                             struct GNUNET_TIME_Relative refund_delay,
    107                             TALER_MERCHANT_PostOrdersCallback cb,
    108                             void *cb_cls)
    109 {
    110   static const char *no_uuids[GNUNET_NZL (0)];
    111 
    112   return TALER_MERCHANT_orders_post2 (ctx,
    113                                       backend_url,
    114                                       order,
    115                                       refund_delay,
    116                                       NULL,
    117                                       0,
    118                                       NULL,
    119                                       0,
    120                                       no_uuids,
    121                                       true,
    122                                       cb,
    123                                       cb_cls);
    124 }
    125 
    126 
    127 struct TALER_MERCHANT_PostOrdersHandle *
    128 TALER_MERCHANT_orders_post2 (
    129   struct GNUNET_CURL_Context *ctx,
    130   const char *backend_url,
    131   const json_t *order,
    132   struct GNUNET_TIME_Relative refund_delay,
    133   const char *payment_target,
    134   unsigned int inventory_products_length,
    135   const struct TALER_MERCHANT_InventoryProduct inventory_products[],
    136   unsigned int uuids_length,
    137   const char *uuids[static uuids_length],
    138   bool create_token,
    139   TALER_MERCHANT_PostOrdersCallback cb,
    140   void *cb_cls)
    141 {
    142   return TALER_MERCHANT_orders_post3 (
    143     ctx,
    144     backend_url,
    145     order,
    146     NULL, /* session ID */
    147     refund_delay,
    148     payment_target,
    149     inventory_products_length,
    150     inventory_products,
    151     uuids_length,
    152     uuids,
    153     create_token,
    154     cb,
    155     cb_cls);
    156 }
    157 
    158 
    159 struct TALER_MERCHANT_PostOrdersHandle *
    160 TALER_MERCHANT_orders_post3 (
    161   struct GNUNET_CURL_Context *ctx,
    162   const char *backend_url,
    163   const json_t *order,
    164   const char *session_id,
    165   struct GNUNET_TIME_Relative refund_delay,
    166   const char *payment_target,
    167   unsigned int inventory_products_length,
    168   const struct TALER_MERCHANT_InventoryProduct inventory_products[],
    169   unsigned int uuids_length,
    170   const char *uuids[static uuids_length],
    171   bool create_token,
    172   TALER_MERCHANT_PostOrdersCallback cb,
    173   void *cb_cls)
    174 {
    175   struct TALER_MERCHANT_PostOrdersHandle *po;
    176   json_t *req;
    177   CURL *eh;
    178 
    179   po = GNUNET_new (struct TALER_MERCHANT_PostOrdersHandle);
    180   po->ctx = ctx;
    181   po->cb = cb;
    182   po->cb_cls = cb_cls;
    183   po->url = TALER_url_join (backend_url,
    184                             "private/orders",
    185                             NULL);
    186   req = GNUNET_JSON_PACK (
    187     GNUNET_JSON_pack_object_incref ("order",
    188                                     (json_t *) order),
    189     GNUNET_JSON_pack_allow_null (
    190       GNUNET_JSON_pack_string ("session_id",
    191                                session_id)),
    192     GNUNET_JSON_pack_allow_null (
    193       GNUNET_JSON_pack_string ("payment_target",
    194                                payment_target)));
    195   if (0 != refund_delay.rel_value_us)
    196   {
    197     GNUNET_assert (0 ==
    198                    json_object_set_new (req,
    199                                         "refund_delay",
    200                                         GNUNET_JSON_from_time_rel (
    201                                           refund_delay)));
    202   }
    203   if (0 != inventory_products_length)
    204   {
    205     json_t *ipa = json_array ();
    206 
    207     GNUNET_assert (NULL != ipa);
    208     for (unsigned int i = 0; i<inventory_products_length; i++)
    209     {
    210       json_t *ip;
    211       char unit_quantity_buf[64];
    212 
    213       TALER_MERCHANT_format_quantity_string (inventory_products[i].quantity,
    214                                              inventory_products[i].quantity_frac,
    215                                              unit_quantity_buf,
    216                                              sizeof (unit_quantity_buf));
    217 
    218       ip = GNUNET_JSON_PACK (
    219         GNUNET_JSON_pack_string ("product_id",
    220                                  inventory_products[i].product_id),
    221         GNUNET_JSON_pack_string ("unit_quantity",
    222                                  unit_quantity_buf));
    223       GNUNET_assert (NULL != ip);
    224       GNUNET_assert (0 ==
    225                      json_array_append_new (ipa,
    226                                             ip));
    227     }
    228     GNUNET_assert (0 ==
    229                    json_object_set_new (req,
    230                                         "inventory_products",
    231                                         ipa));
    232   }
    233   if (0 != uuids_length)
    234   {
    235     json_t *ua = json_array ();
    236 
    237     GNUNET_assert (NULL != ua);
    238     for (unsigned int i = 0; i<uuids_length; i++)
    239     {
    240       json_t *u;
    241 
    242       u = json_string (uuids[i]);
    243       GNUNET_assert (0 ==
    244                      json_array_append_new (ua,
    245                                             u));
    246     }
    247     GNUNET_assert (0 ==
    248                    json_object_set_new (req,
    249                                         "lock_uuids",
    250                                         ua));
    251   }
    252   if (! create_token)
    253   {
    254     GNUNET_assert (0 ==
    255                    json_object_set_new (req,
    256                                         "create_token",
    257                                         json_boolean (create_token)));
    258   }
    259   eh = TALER_MERCHANT_curl_easy_get_ (po->url);
    260   if (GNUNET_OK !=
    261       TALER_curl_easy_post (&po->post_ctx,
    262                             eh,
    263                             req))
    264   {
    265     GNUNET_break (0);
    266     curl_easy_cleanup (eh);
    267     json_decref (req);
    268     GNUNET_free (po);
    269     return NULL;
    270   }
    271   json_decref (req);
    272   po->job = GNUNET_CURL_job_add2 (ctx,
    273                                   eh,
    274                                   po->post_ctx.headers,
    275                                   &handle_post_order_finished,
    276                                   po);
    277   return po;
    278 }
    279 
    280 
    281 void
    282 TALER_MERCHANT_orders_post_cancel (
    283   struct TALER_MERCHANT_PostOrdersHandle *po)
    284 {
    285   if (NULL != po->job)
    286   {
    287     GNUNET_CURL_job_cancel (po->job);
    288     po->job = NULL;
    289   }
    290   GNUNET_free (po->url);
    291   TALER_curl_easy_post_finished (&po->post_ctx);
    292   GNUNET_free (po);
    293 }
    294 
    295 
    296 /* end of merchant_api_post_orders.c */