exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

exchange_api_post-kyc-start-ID.c (6818B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2024-2026 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or modify it under the
      6   terms of the GNU General Public License as published by the Free Software
      7   Foundation; either version 3, or (at your option) any later version.
      8 
      9   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
     10   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11   A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
     12 
     13   You should have received a copy of the GNU General Public License along with
     14   TALER; see the file COPYING.  If not, see
     15   <http://www.gnu.org/licenses/>
     16 */
     17 /**
     18  * @file lib/exchange_api_post-kyc-start-ID.c
     19  * @brief functions to start a KYC process
     20  * @author Christian Grothoff
     21  */
     22 #include "taler/taler_json_lib.h"
     23 #include <microhttpd.h>
     24 #include <gnunet/gnunet_curl_lib.h>
     25 #include "taler/exchange/post-kyc-start-ID.h"
     26 #include "exchange_api_curl_defaults.h"
     27 #include "taler/taler_signatures.h"
     28 #include "taler/taler_curl_lib.h"
     29 
     30 
     31 struct TALER_EXCHANGE_PostKycStartHandle
     32 {
     33 
     34   /**
     35    * The base URL for this request.
     36    */
     37   char *base_url;
     38 
     39   /**
     40    * The full URL for this request.
     41    */
     42   char *url;
     43 
     44   /**
     45    * Minor context that holds body and headers.
     46    */
     47   struct TALER_CURL_PostContext post_ctx;
     48 
     49   /**
     50    * Handle for the request.
     51    */
     52   struct GNUNET_CURL_Job *job;
     53 
     54   /**
     55    * Function to call with the result.
     56    */
     57   TALER_EXCHANGE_PostKycStartCallback cb;
     58 
     59   /**
     60    * Closure for @e cb.
     61    */
     62   TALER_EXCHANGE_POST_KYC_START_RESULT_CLOSURE *cb_cls;
     63 
     64   /**
     65    * Reference to the execution context.
     66    */
     67   struct GNUNET_CURL_Context *ctx;
     68 
     69   /**
     70    * Identifier for the KYC process to start.
     71    */
     72   char *id;
     73 
     74 };
     75 
     76 
     77 /**
     78  * Function called when we're done processing the
     79  * HTTP POST /kyc-start/$ID request.
     80  *
     81  * @param cls the `struct TALER_EXCHANGE_PostKycStartHandle *`
     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_kyc_start_finished (void *cls,
     87                            long response_code,
     88                            const void *response)
     89 {
     90   struct TALER_EXCHANGE_PostKycStartHandle *pksh = cls;
     91   const json_t *json = response;
     92   struct TALER_EXCHANGE_PostKycStartResponse adr = {
     93     .hr.http_status = (unsigned int) response_code,
     94     .hr.reply = json
     95   };
     96 
     97   pksh->job = NULL;
     98   switch (response_code)
     99   {
    100   case 0:
    101     /* no reply */
    102     adr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
    103     adr.hr.hint = "server offline?";
    104     break;
    105   case MHD_HTTP_OK:
    106     {
    107       struct GNUNET_JSON_Specification spec[] = {
    108         GNUNET_JSON_spec_string (
    109           "redirect_url",
    110           &adr.details.ok.redirect_url),
    111         GNUNET_JSON_spec_end ()
    112       };
    113 
    114       if (GNUNET_OK !=
    115           GNUNET_JSON_parse (json,
    116                              spec,
    117                              NULL, NULL))
    118       {
    119         GNUNET_break_op (0);
    120         adr.hr.http_status = 0;
    121         adr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
    122         break;
    123       }
    124     }
    125     break;
    126   case MHD_HTTP_BAD_REQUEST:
    127     adr.hr.ec = TALER_JSON_get_error_code (json);
    128     adr.hr.hint = TALER_JSON_get_error_hint (json);
    129     break;
    130   case MHD_HTTP_NOT_FOUND:
    131     adr.hr.ec = TALER_JSON_get_error_code (json);
    132     adr.hr.hint = TALER_JSON_get_error_hint (json);
    133     break;
    134   case MHD_HTTP_CONFLICT:
    135     adr.hr.ec = TALER_JSON_get_error_code (json);
    136     adr.hr.hint = TALER_JSON_get_error_hint (json);
    137     break;
    138   case MHD_HTTP_INTERNAL_SERVER_ERROR:
    139     adr.hr.ec = TALER_JSON_get_error_code (json);
    140     adr.hr.hint = TALER_JSON_get_error_hint (json);
    141     break;
    142   default:
    143     /* unexpected response code */
    144     GNUNET_break_op (0);
    145     adr.hr.ec = TALER_JSON_get_error_code (json);
    146     adr.hr.hint = TALER_JSON_get_error_hint (json);
    147     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    148                 "Unexpected response code %u/%d for exchange POST kyc-start\n",
    149                 (unsigned int) response_code,
    150                 (int) adr.hr.ec);
    151     break;
    152   }
    153   if (NULL != pksh->cb)
    154   {
    155     pksh->cb (pksh->cb_cls,
    156               &adr);
    157     pksh->cb = NULL;
    158   }
    159   TALER_EXCHANGE_post_kyc_start_cancel (pksh);
    160 }
    161 
    162 
    163 struct TALER_EXCHANGE_PostKycStartHandle *
    164 TALER_EXCHANGE_post_kyc_start_create (
    165   struct GNUNET_CURL_Context *ctx,
    166   const char *url,
    167   const char *id)
    168 {
    169   struct TALER_EXCHANGE_PostKycStartHandle *pksh;
    170 
    171   pksh = GNUNET_new (struct TALER_EXCHANGE_PostKycStartHandle);
    172   pksh->ctx = ctx;
    173   pksh->base_url = GNUNET_strdup (url);
    174   pksh->id = GNUNET_strdup (id);
    175   return pksh;
    176 }
    177 
    178 
    179 enum TALER_ErrorCode
    180 TALER_EXCHANGE_post_kyc_start_start (
    181   struct TALER_EXCHANGE_PostKycStartHandle *pksh,
    182   TALER_EXCHANGE_PostKycStartCallback cb,
    183   TALER_EXCHANGE_POST_KYC_START_RESULT_CLOSURE *cb_cls)
    184 {
    185   CURL *eh;
    186   json_t *body;
    187   char *path;
    188 
    189   pksh->cb = cb;
    190   pksh->cb_cls = cb_cls;
    191   GNUNET_asprintf (&path,
    192                    "kyc-start/%s",
    193                    pksh->id);
    194   pksh->url = TALER_url_join (pksh->base_url,
    195                               path,
    196                               NULL);
    197   GNUNET_free (path);
    198   if (NULL == pksh->url)
    199   {
    200     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    201                 "Could not construct request URL.\n");
    202     return TALER_EC_GENERIC_CONFIGURATION_INVALID;
    203   }
    204   body = json_object (); /* as per spec: empty! */
    205   GNUNET_assert (NULL != body);
    206   eh = TALER_EXCHANGE_curl_easy_get_ (pksh->url);
    207   if ( (NULL == eh) ||
    208        (GNUNET_OK !=
    209         TALER_curl_easy_post (&pksh->post_ctx,
    210                               eh,
    211                               body)) )
    212   {
    213     GNUNET_break (0);
    214     if (NULL != eh)
    215       curl_easy_cleanup (eh);
    216     json_decref (body);
    217     GNUNET_free (pksh->url);
    218     pksh->url = NULL;
    219     return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
    220   }
    221   json_decref (body);
    222   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    223               "Requesting URL '%s'\n",
    224               pksh->url);
    225   pksh->job = GNUNET_CURL_job_add2 (pksh->ctx,
    226                                     eh,
    227                                     pksh->post_ctx.headers,
    228                                     &handle_kyc_start_finished,
    229                                     pksh);
    230   if (NULL == pksh->job)
    231   {
    232     TALER_curl_easy_post_finished (&pksh->post_ctx);
    233     GNUNET_free (pksh->url);
    234     pksh->url = NULL;
    235     return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
    236   }
    237   return TALER_EC_NONE;
    238 }
    239 
    240 
    241 void
    242 TALER_EXCHANGE_post_kyc_start_cancel (
    243   struct TALER_EXCHANGE_PostKycStartHandle *pksh)
    244 {
    245   if (NULL != pksh->job)
    246   {
    247     GNUNET_CURL_job_cancel (pksh->job);
    248     pksh->job = NULL;
    249   }
    250   TALER_curl_easy_post_finished (&pksh->post_ctx);
    251   GNUNET_free (pksh->url);
    252   GNUNET_free (pksh->base_url);
    253   GNUNET_free (pksh->id);
    254   GNUNET_free (pksh);
    255 }
    256 
    257 
    258 /* end of exchange_api_post-kyc-start-ID.c */