merchant

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

merchant_api_post_order_claim.c (6805B)


      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_order_claim.c
     21  * @brief Implementation of POST /orders/$ID/claim
     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 <taler/taler_json_lib.h>
     34 #include <taler/taler_signatures.h>
     35 #include <taler/taler_curl_lib.h>
     36 
     37 
     38 /**
     39  * Structure representing a POST /orders/$ID/claim operation.
     40  */
     41 struct TALER_MERCHANT_OrderClaimHandle
     42 {
     43   /**
     44    * Full URL, includes "/orders/$ID/claim".
     45    */
     46   char *url;
     47 
     48   /**
     49    * Handle for the request.
     50    */
     51   struct GNUNET_CURL_Job *job;
     52 
     53   /**
     54    * Function to call with the result.
     55    */
     56   TALER_MERCHANT_OrderClaimCallback cb;
     57 
     58   /**
     59    * Closure for @a cb.
     60    */
     61   void *cb_cls;
     62 
     63   /**
     64    * Reference to the execution context.
     65    */
     66   struct GNUNET_CURL_Context *ctx;
     67 
     68   /**
     69    * Minor context that holds body and headers.
     70    */
     71   struct TALER_CURL_PostContext post_ctx;
     72 };
     73 
     74 
     75 /**
     76  * Function called when we're done processing the
     77  * POST /orders/$ID/claim request.
     78  *
     79  * @param cls the `struct TALER_MERCHANT_OrderClaimHandle`
     80  * @param response_code HTTP response code, 0 on error
     81  * @param response response body, should be NULL
     82  */
     83 static void
     84 handle_post_order_claim_finished (void *cls,
     85                                   long response_code,
     86                                   const void *response)
     87 {
     88   struct TALER_MERCHANT_OrderClaimHandle *och = cls;
     89   const json_t *json = response;
     90   struct TALER_MERCHANT_OrderClaimResponse ocr = {
     91     .hr.http_status = (unsigned int) response_code,
     92     .hr.reply = json
     93   };
     94   struct GNUNET_JSON_Specification spec[] = {
     95     GNUNET_JSON_spec_object_const (
     96       "contract_terms",
     97       &ocr.details.ok.contract_terms),
     98     GNUNET_JSON_spec_fixed_auto (
     99       "sig",
    100       &ocr.details.ok.sig),
    101     GNUNET_JSON_spec_end ()
    102   };
    103 
    104   och->job = NULL;
    105   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    106               "Order claimed with status %u\n",
    107               (unsigned int) response_code);
    108 
    109   if (MHD_HTTP_OK != response_code)
    110   {
    111     ocr.hr.ec = TALER_JSON_get_error_code (json);
    112     ocr.hr.hint = TALER_JSON_get_error_hint (json);
    113     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    114                 "Proposal lookup failed with HTTP status code %u/%d\n",
    115                 (unsigned int) response_code,
    116                 (int) ocr.hr.ec);
    117     och->cb (och->cb_cls,
    118              &ocr);
    119     TALER_MERCHANT_order_claim_cancel (och);
    120     return;
    121   }
    122 
    123   if (GNUNET_OK !=
    124       GNUNET_JSON_parse (json,
    125                          spec,
    126                          NULL, NULL))
    127   {
    128     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    129                 "Claiming order failed: could not parse JSON response\n");
    130     GNUNET_break_op (0);
    131     ocr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
    132     ocr.hr.http_status = 0;
    133     och->cb (och->cb_cls,
    134              &ocr);
    135     TALER_MERCHANT_order_claim_cancel (och);
    136     return;
    137   }
    138 
    139   if (GNUNET_OK !=
    140       TALER_JSON_contract_hash (ocr.details.ok.contract_terms,
    141                                 &ocr.details.ok.h_contract_terms))
    142   {
    143     GNUNET_break (0);
    144     ocr.hr.ec = TALER_EC_MERCHANT_POST_ORDERS_ID_CLAIM_CLIENT_INTERNAL_FAILURE;
    145     ocr.hr.http_status = 0;
    146     GNUNET_JSON_parse_free (spec);
    147     och->cb (och->cb_cls,
    148              &ocr);
    149     TALER_MERCHANT_order_claim_cancel (och);
    150     return;
    151   }
    152   och->cb (och->cb_cls,
    153            &ocr);
    154   GNUNET_JSON_parse_free (spec);
    155   TALER_MERCHANT_order_claim_cancel (och);
    156 }
    157 
    158 
    159 struct TALER_MERCHANT_OrderClaimHandle *
    160 TALER_MERCHANT_order_claim (struct GNUNET_CURL_Context *ctx,
    161                             const char *backend_url,
    162                             const char *order_id,
    163                             const struct GNUNET_CRYPTO_EddsaPublicKey *nonce,
    164                             const struct TALER_ClaimTokenP *claim_token,
    165                             TALER_MERCHANT_OrderClaimCallback cb,
    166                             void *cb_cls)
    167 {
    168   struct TALER_MERCHANT_OrderClaimHandle *och;
    169   json_t *req_obj;
    170 
    171   if (NULL == order_id)
    172   {
    173     GNUNET_break (0);
    174     return NULL;
    175   }
    176   req_obj = GNUNET_JSON_PACK (
    177     GNUNET_JSON_pack_data_auto ("nonce",
    178                                 nonce),
    179     GNUNET_JSON_pack_allow_null (
    180       GNUNET_JSON_pack_data_auto ("token",
    181                                   claim_token)));
    182   och = GNUNET_new (struct TALER_MERCHANT_OrderClaimHandle);
    183   och->ctx = ctx;
    184   och->cb = cb;
    185   och->cb_cls = cb_cls;
    186   {
    187     char *path;
    188 
    189     GNUNET_asprintf (&path,
    190                      "orders/%s/claim",
    191                      order_id);
    192     och->url = TALER_url_join (backend_url,
    193                                path,
    194                                NULL);
    195     GNUNET_free (path);
    196   }
    197   if (NULL == och->url)
    198   {
    199     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    200                 "Could not construct request URL.\n");
    201     json_decref (req_obj);
    202     GNUNET_free (och);
    203     return NULL;
    204   }
    205   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    206               "Claiming order at %s\n",
    207               och->url);
    208   {
    209     CURL *eh;
    210 
    211     eh = TALER_MERCHANT_curl_easy_get_ (och->url);
    212     GNUNET_assert (GNUNET_OK ==
    213                    TALER_curl_easy_post (&och->post_ctx,
    214                                          eh,
    215                                          req_obj));
    216     json_decref (req_obj);
    217     och->job = GNUNET_CURL_job_add2 (ctx,
    218                                      eh,
    219                                      och->post_ctx.headers,
    220                                      &handle_post_order_claim_finished,
    221                                      och);
    222     GNUNET_assert (NULL != och->job);
    223   }
    224   return och;
    225 }
    226 
    227 
    228 void
    229 TALER_MERCHANT_order_claim_cancel (struct TALER_MERCHANT_OrderClaimHandle *och)
    230 {
    231   if (NULL != och->job)
    232   {
    233     GNUNET_CURL_job_cancel (och->job);
    234     och->job = NULL;
    235   }
    236   TALER_curl_easy_post_finished (&och->post_ctx);
    237   GNUNET_free (och->url);
    238   GNUNET_free (och);
    239 }
    240 
    241 
    242 /* end of merchant_api_post_order_claim.c */