exchange

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

exchange_api_get-kyc-proof-PROVIDER_NAME.c (8072B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2021, 2022, 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_get-kyc-proof-PROVIDER_NAME.c
     19  * @brief Implementation of the /kyc-proof request
     20  * @author Christian Grothoff
     21  */
     22 #include <microhttpd.h> /* just for HTTP proof codes */
     23 #include <gnunet/gnunet_util_lib.h>
     24 #include <gnunet/gnunet_curl_lib.h>
     25 #include "taler/taler_json_lib.h"
     26 #include "exchange_api_handle.h"
     27 #include "taler/taler_signatures.h"
     28 #include "exchange_api_curl_defaults.h"
     29 #include "taler/exchange/get-kyc-proof-PROVIDER_NAME.h"
     30 
     31 
     32 /**
     33  * @brief A handle for GET /kyc-proof/$PROVIDER_NAME
     34  */
     35 struct TALER_EXCHANGE_GetKycProofHandle
     36 {
     37 
     38   /**
     39    * The base URL of the exchange.
     40    */
     41   char *base_url;
     42 
     43   /**
     44    * The full URL for this request.
     45    */
     46   char *url;
     47 
     48   /**
     49    * Handle to our CURL request.
     50    */
     51   CURL *eh;
     52 
     53   /**
     54    * Handle for the request.
     55    */
     56   struct GNUNET_CURL_Job *job;
     57 
     58   /**
     59    * Function to call with the result.
     60    */
     61   TALER_EXCHANGE_GetKycProofCallback cb;
     62 
     63   /**
     64    * Closure for @e cb.
     65    */
     66   TALER_EXCHANGE_GET_KYC_PROOF_RESULT_CLOSURE *cb_cls;
     67 
     68   /**
     69    * CURL context to use.
     70    */
     71   struct GNUNET_CURL_Context *ctx;
     72 
     73   /**
     74    * Hash of the payto URI identifying the target account.
     75    */
     76   struct TALER_NormalizedPaytoHashP h_payto;
     77 
     78   /**
     79    * Name of the KYC logic / provider. Heap-allocated copy.
     80    */
     81   char *logic;
     82 
     83   /**
     84    * Additional query string arguments to append to the URL.
     85    * Borrowed pointer (not owned), must start with '&'.
     86    * NULL if not set.
     87    */
     88   const char *args;
     89 
     90 };
     91 
     92 
     93 /**
     94  * Function called when we're done processing the
     95  * HTTP GET /kyc-proof request.
     96  *
     97  * @param cls the `struct TALER_EXCHANGE_GetKycProofHandle`
     98  * @param response_code HTTP response code, 0 on error
     99  * @param body response body
    100  * @param body_size number of bytes in @a body
    101  */
    102 static void
    103 handle_get_kyc_proof_finished (void *cls,
    104                                long response_code,
    105                                const void *body,
    106                                size_t body_size)
    107 {
    108   struct TALER_EXCHANGE_GetKycProofHandle *gkph = cls;
    109   struct TALER_EXCHANGE_GetKycProofResponse gkpr = {
    110     .hr.http_status = (unsigned int) response_code
    111   };
    112 
    113   (void) body;
    114   (void) body_size;
    115   gkph->job = NULL;
    116   switch (response_code)
    117   {
    118   case 0:
    119     break;
    120   case MHD_HTTP_OK:
    121     /* KYC process already completed; nothing more to do */
    122     break;
    123   case MHD_HTTP_SEE_OTHER:
    124     {
    125       char *redirect_url;
    126 
    127       GNUNET_assert (CURLE_OK ==
    128                      curl_easy_getinfo (gkph->eh,
    129                                         CURLINFO_REDIRECT_URL,
    130                                         &redirect_url));
    131       gkpr.details.see_other.redirect_url = redirect_url;
    132       break;
    133     }
    134   case MHD_HTTP_BAD_REQUEST:
    135     /* This should never happen, either us or the exchange is buggy
    136        (or API version conflict); just pass JSON reply to the application */
    137     break;
    138   case MHD_HTTP_UNAUTHORIZED:
    139     break;
    140   case MHD_HTTP_NOT_FOUND:
    141     break;
    142   case MHD_HTTP_INTERNAL_SERVER_ERROR:
    143     /* Server had an internal issue; we should retry, but this API
    144        leaves this to the application */
    145     break;
    146   case MHD_HTTP_BAD_GATEWAY:
    147     /* Server had an internal issue; we should retry, but this API
    148        leaves this to the application */
    149     break;
    150   case MHD_HTTP_GATEWAY_TIMEOUT:
    151     /* Server had an internal issue; we should retry, but this API
    152        leaves this to the application */
    153     break;
    154   default:
    155     /* unexpected response code */
    156     GNUNET_break_op (0);
    157     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    158                 "Unexpected response code %u for exchange get_kyc_proof\n",
    159                 (unsigned int) response_code);
    160     break;
    161   }
    162   gkph->cb (gkph->cb_cls,
    163             &gkpr);
    164   TALER_EXCHANGE_get_kyc_proof_cancel (gkph);
    165 }
    166 
    167 
    168 struct TALER_EXCHANGE_GetKycProofHandle *
    169 TALER_EXCHANGE_get_kyc_proof_create (
    170   struct GNUNET_CURL_Context *ctx,
    171   const char *url,
    172   const struct TALER_NormalizedPaytoHashP *h_payto,
    173   const char *logic)
    174 {
    175   struct TALER_EXCHANGE_GetKycProofHandle *gkph;
    176 
    177   gkph = GNUNET_new (struct TALER_EXCHANGE_GetKycProofHandle);
    178   gkph->ctx = ctx;
    179   gkph->base_url = GNUNET_strdup (url);
    180   gkph->h_payto = *h_payto;
    181   gkph->logic = GNUNET_strdup (logic);
    182   return gkph;
    183 }
    184 
    185 
    186 enum GNUNET_GenericReturnValue
    187 TALER_EXCHANGE_get_kyc_proof_set_options_ (
    188   struct TALER_EXCHANGE_GetKycProofHandle *gkph,
    189   unsigned int num_options,
    190   const struct TALER_EXCHANGE_GetKycProofOptionValue *options)
    191 {
    192   for (unsigned int i = 0; i < num_options; i++)
    193   {
    194     const struct TALER_EXCHANGE_GetKycProofOptionValue *opt = &options[i];
    195 
    196     switch (opt->option)
    197     {
    198     case TALER_EXCHANGE_GET_KYC_PROOF_OPTION_END:
    199       return GNUNET_OK;
    200     case TALER_EXCHANGE_GET_KYC_PROOF_OPTION_ARGS:
    201       GNUNET_assert (opt->details.args[0] == '&');
    202       gkph->args = opt->details.args;
    203       break;
    204     }
    205   }
    206   return GNUNET_OK;
    207 }
    208 
    209 
    210 enum TALER_ErrorCode
    211 TALER_EXCHANGE_get_kyc_proof_start (
    212   struct TALER_EXCHANGE_GetKycProofHandle *gkph,
    213   TALER_EXCHANGE_GetKycProofCallback cb,
    214   TALER_EXCHANGE_GET_KYC_PROOF_RESULT_CLOSURE *cb_cls)
    215 {
    216   if (NULL != gkph->job)
    217   {
    218     GNUNET_break (0);
    219     return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
    220   }
    221   gkph->cb = cb;
    222   gkph->cb_cls = cb_cls;
    223   {
    224     char hstr[sizeof (gkph->h_payto) * 2];
    225     char *arg_str;
    226     char *end;
    227     char *url;
    228 
    229     GNUNET_asprintf (&arg_str,
    230                      "kyc-proof/%s",
    231                      gkph->logic);
    232     end = GNUNET_STRINGS_data_to_string (&gkph->h_payto,
    233                                          sizeof (gkph->h_payto),
    234                                          hstr,
    235                                          sizeof (hstr));
    236     *end = '\0';
    237     url = TALER_url_join (gkph->base_url,
    238                           arg_str,
    239                           "state", hstr,
    240                           NULL);
    241     GNUNET_free (arg_str);
    242     if (NULL == url)
    243     {
    244       GNUNET_break (0);
    245       return TALER_EC_GENERIC_CONFIGURATION_INVALID;
    246     }
    247     if (NULL != gkph->args)
    248     {
    249       GNUNET_asprintf (&gkph->url,
    250                        "%s%s",
    251                        url,
    252                        gkph->args);
    253       GNUNET_free (url);
    254     }
    255     else
    256     {
    257       gkph->url = url;
    258     }
    259   }
    260   gkph->eh = TALER_EXCHANGE_curl_easy_get_ (gkph->url);
    261   if (NULL == gkph->eh)
    262   {
    263     GNUNET_break (0);
    264     GNUNET_free (gkph->url);
    265     return TALER_EC_GENERIC_CONFIGURATION_INVALID;
    266   }
    267   /* disable location following, we want to learn the
    268      result of a 303 redirect! */
    269   curl_easy_setopt (gkph->eh,
    270                     CURLOPT_FOLLOWLOCATION,
    271                     0L);
    272   gkph->job = GNUNET_CURL_job_add_raw (gkph->ctx,
    273                                        gkph->eh,
    274                                        NULL,
    275                                        &handle_get_kyc_proof_finished,
    276                                        gkph);
    277   if (NULL == gkph->job)
    278   {
    279     curl_easy_cleanup (gkph->eh);
    280     gkph->eh = NULL;
    281     GNUNET_free (gkph->url);
    282     return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
    283   }
    284   return TALER_EC_NONE;
    285 }
    286 
    287 
    288 void
    289 TALER_EXCHANGE_get_kyc_proof_cancel (
    290   struct TALER_EXCHANGE_GetKycProofHandle *gkph)
    291 {
    292   if (NULL != gkph->job)
    293   {
    294     GNUNET_CURL_job_cancel (gkph->job);
    295     gkph->job = NULL;
    296   }
    297   GNUNET_free (gkph->url);
    298   GNUNET_free (gkph->logic);
    299   GNUNET_free (gkph->base_url);
    300   GNUNET_free (gkph);
    301 }
    302 
    303 
    304 /* end of exchange_api_get-kyc-proof-PROVIDER_NAME.c */