merchant

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

merchant_api_post-private-transfers.c (7205B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2014-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_post-private-transfers-new.c
     21  * @brief Implementation of the POST /private/transfers request
     22  * @author Christian Grothoff
     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/post-private-transfers.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 POST /private/transfers operation.
     39  */
     40 struct TALER_MERCHANT_PostPrivateTransfersHandle
     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_PostPrivateTransfersCallback cb;
     61 
     62   /**
     63    * Closure for @a cb.
     64    */
     65   TALER_MERCHANT_POST_PRIVATE_TRANSFERS_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    * Amount credited in this transfer.
     79    */
     80   struct TALER_Amount credit_amount;
     81 
     82   /**
     83    * Wire transfer identifier.
     84    */
     85   struct TALER_WireTransferIdentifierRawP wtid;
     86 
     87   /**
     88    * Payto URI of the merchant account.
     89    */
     90   struct TALER_FullPayto payto_uri;
     91 
     92   /**
     93    * Base URL of the exchange.
     94    */
     95   char *exchange_url;
     96 };
     97 
     98 
     99 /**
    100  * Function called when we're done processing the
    101  * HTTP POST /private/transfers request.
    102  *
    103  * @param cls the `struct TALER_MERCHANT_PostPrivateTransfersHandle`
    104  * @param response_code HTTP response code, 0 on error
    105  * @param response response body, NULL if not in JSON
    106  */
    107 static void
    108 handle_post_transfers_finished (void *cls,
    109                                 long response_code,
    110                                 const void *response)
    111 {
    112   struct TALER_MERCHANT_PostPrivateTransfersHandle *ppth = cls;
    113   const json_t *json = response;
    114   struct TALER_MERCHANT_PostPrivateTransfersResponse ptr = {
    115     .hr.http_status = (unsigned int) response_code,
    116     .hr.reply = json
    117   };
    118 
    119   ppth->job = NULL;
    120   switch (response_code)
    121   {
    122   case 0:
    123     ptr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
    124     break;
    125   case MHD_HTTP_NO_CONTENT:
    126     break;
    127   case MHD_HTTP_UNAUTHORIZED:
    128     ptr.hr.ec = TALER_JSON_get_error_code (json);
    129     ptr.hr.hint = TALER_JSON_get_error_hint (json);
    130     break;
    131   case MHD_HTTP_NOT_FOUND:
    132     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    133                 "Did not find any data\n");
    134     ptr.hr.ec = TALER_JSON_get_error_code (json);
    135     ptr.hr.hint = TALER_JSON_get_error_hint (json);
    136     break;
    137   case MHD_HTTP_CONFLICT:
    138     ptr.hr.ec = TALER_JSON_get_error_code (json);
    139     ptr.hr.hint = TALER_JSON_get_error_hint (json);
    140     break;
    141   case MHD_HTTP_INTERNAL_SERVER_ERROR:
    142     ptr.hr.ec = TALER_JSON_get_error_code (json);
    143     ptr.hr.hint = TALER_JSON_get_error_hint (json);
    144     break;
    145   default:
    146     GNUNET_break_op (0);
    147     TALER_MERCHANT_parse_error_details_ (json,
    148                                          response_code,
    149                                          &ptr.hr);
    150     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    151                 "Unexpected response code %u/%d\n",
    152                 (unsigned int) ptr.hr.http_status,
    153                 (int) ptr.hr.ec);
    154     break;
    155   }
    156   ppth->cb (ppth->cb_cls,
    157             &ptr);
    158   TALER_MERCHANT_post_private_transfers_cancel (ppth);
    159 }
    160 
    161 
    162 struct TALER_MERCHANT_PostPrivateTransfersHandle *
    163 TALER_MERCHANT_post_private_transfers_create (
    164   struct GNUNET_CURL_Context *ctx,
    165   const char *url,
    166   const struct TALER_Amount *credit_amount,
    167   const struct TALER_WireTransferIdentifierRawP *wtid,
    168   struct TALER_FullPayto payto_uri,
    169   const char *exchange_url)
    170 {
    171   struct TALER_MERCHANT_PostPrivateTransfersHandle *ppth;
    172 
    173   ppth = GNUNET_new (struct TALER_MERCHANT_PostPrivateTransfersHandle);
    174   ppth->ctx = ctx;
    175   ppth->base_url = GNUNET_strdup (url);
    176   ppth->credit_amount = *credit_amount;
    177   ppth->wtid = *wtid;
    178   ppth->payto_uri.full_payto = GNUNET_strdup (payto_uri.full_payto);
    179   ppth->exchange_url = GNUNET_strdup (exchange_url);
    180   return ppth;
    181 }
    182 
    183 
    184 enum TALER_ErrorCode
    185 TALER_MERCHANT_post_private_transfers_start (
    186   struct TALER_MERCHANT_PostPrivateTransfersHandle *ppth,
    187   TALER_MERCHANT_PostPrivateTransfersCallback cb,
    188   TALER_MERCHANT_POST_PRIVATE_TRANSFERS_RESULT_CLOSURE *cb_cls)
    189 {
    190   json_t *req_obj;
    191   CURL *eh;
    192 
    193   ppth->cb = cb;
    194   ppth->cb_cls = cb_cls;
    195   ppth->url = TALER_url_join (ppth->base_url,
    196                               "private/transfers",
    197                               NULL);
    198   if (NULL == ppth->url)
    199     return TALER_EC_GENERIC_CONFIGURATION_INVALID;
    200   req_obj = GNUNET_JSON_PACK (
    201     TALER_JSON_pack_amount ("credit_amount",
    202                             &ppth->credit_amount),
    203     GNUNET_JSON_pack_data_auto ("wtid",
    204                                 &ppth->wtid),
    205     TALER_JSON_pack_full_payto ("payto_uri",
    206                                 ppth->payto_uri),
    207     GNUNET_JSON_pack_string ("exchange_url",
    208                              ppth->exchange_url));
    209   eh = TALER_MERCHANT_curl_easy_get_ (ppth->url);
    210   if ( (NULL == eh) ||
    211        (GNUNET_OK !=
    212         TALER_curl_easy_post (&ppth->post_ctx,
    213                               eh,
    214                               req_obj)) )
    215   {
    216     GNUNET_break (0);
    217     json_decref (req_obj);
    218     if (NULL != eh)
    219       curl_easy_cleanup (eh);
    220     return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
    221   }
    222   json_decref (req_obj);
    223   ppth->job = GNUNET_CURL_job_add2 (ppth->ctx,
    224                                     eh,
    225                                     ppth->post_ctx.headers,
    226                                     &handle_post_transfers_finished,
    227                                     ppth);
    228   if (NULL == ppth->job)
    229     return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
    230   return TALER_EC_NONE;
    231 }
    232 
    233 
    234 void
    235 TALER_MERCHANT_post_private_transfers_cancel (
    236   struct TALER_MERCHANT_PostPrivateTransfersHandle *ppth)
    237 {
    238   if (NULL != ppth->job)
    239   {
    240     GNUNET_CURL_job_cancel (ppth->job);
    241     ppth->job = NULL;
    242   }
    243   TALER_curl_easy_post_finished (&ppth->post_ctx);
    244   GNUNET_free (ppth->payto_uri.full_payto);
    245   GNUNET_free (ppth->exchange_url);
    246   GNUNET_free (ppth->url);
    247   GNUNET_free (ppth->base_url);
    248   GNUNET_free (ppth);
    249 }
    250 
    251 
    252 /* end of merchant_api_post-private-transfers-new.c */