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 */