exchange_api_get-kyc-proof-PROVIDER_NAME.c (7847B)
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 "taler/platform.h" 23 #include <microhttpd.h> /* just for HTTP proof codes */ 24 #include <gnunet/gnunet_util_lib.h> 25 #include <gnunet/gnunet_curl_lib.h> 26 #include "taler/taler_exchange_service.h" 27 #include "taler/taler_json_lib.h" 28 #include "exchange_api_handle.h" 29 #include "taler/taler_signatures.h" 30 #include "exchange_api_curl_defaults.h" 31 #include "taler/taler-exchange/get-kyc-proof-PROVIDER_NAME.h" 32 33 34 /** 35 * @brief A handle for GET /kyc-proof/$PROVIDER_NAME 36 */ 37 struct TALER_EXCHANGE_GetKycProofHandle 38 { 39 40 /** 41 * The base URL of the exchange. 42 */ 43 char *base_url; 44 45 /** 46 * The full URL for this request. 47 */ 48 char *url; 49 50 /** 51 * Handle to our CURL request. 52 */ 53 CURL *eh; 54 55 /** 56 * Handle for the request. 57 */ 58 struct GNUNET_CURL_Job *job; 59 60 /** 61 * Function to call with the result. 62 */ 63 TALER_EXCHANGE_GetKycProofCallback cb; 64 65 /** 66 * Closure for @e cb. 67 */ 68 TALER_EXCHANGE_GET_KYC_PROOF_RESULT_CLOSURE *cb_cls; 69 70 /** 71 * CURL context to use. 72 */ 73 struct GNUNET_CURL_Context *ctx; 74 75 /** 76 * Hash of the payto URI identifying the target account. 77 */ 78 struct TALER_NormalizedPaytoHashP h_payto; 79 80 /** 81 * Name of the KYC logic / provider. Heap-allocated copy. 82 */ 83 char *logic; 84 85 /** 86 * Additional query string arguments to append to the URL. 87 * Borrowed pointer (not owned), must start with '&'. 88 * NULL if not set. 89 */ 90 const char *args; 91 92 }; 93 94 95 /** 96 * Function called when we're done processing the 97 * HTTP GET /kyc-proof request. 98 * 99 * @param cls the `struct TALER_EXCHANGE_GetKycProofHandle` 100 * @param response_code HTTP response code, 0 on error 101 * @param body response body 102 * @param body_size number of bytes in @a body 103 */ 104 static void 105 handle_get_kyc_proof_finished (void *cls, 106 long response_code, 107 const void *body, 108 size_t body_size) 109 { 110 struct TALER_EXCHANGE_GetKycProofHandle *gkph = cls; 111 struct TALER_EXCHANGE_GetKycProofResponse gkpr = { 112 .hr.http_status = (unsigned int) response_code 113 }; 114 115 (void) body; 116 (void) body_size; 117 gkph->job = NULL; 118 switch (response_code) 119 { 120 case 0: 121 break; 122 case MHD_HTTP_OK: 123 /* KYC process already completed; nothing more to do */ 124 break; 125 case MHD_HTTP_SEE_OTHER: 126 { 127 char *redirect_url; 128 129 GNUNET_assert (CURLE_OK == 130 curl_easy_getinfo (gkph->eh, 131 CURLINFO_REDIRECT_URL, 132 &redirect_url)); 133 gkpr.details.found.redirect_url = redirect_url; 134 break; 135 } 136 case MHD_HTTP_BAD_REQUEST: 137 /* This should never happen, either us or the exchange is buggy 138 (or API version conflict); just pass JSON reply to the application */ 139 break; 140 case MHD_HTTP_UNAUTHORIZED: 141 break; 142 case MHD_HTTP_FORBIDDEN: 143 break; 144 case MHD_HTTP_NOT_FOUND: 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 char *arg_str; 217 218 if (NULL != gkph->job) 219 { 220 GNUNET_break (0); 221 return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; 222 } 223 gkph->cb = cb; 224 gkph->cb_cls = cb_cls; 225 { 226 char hstr[sizeof (gkph->h_payto) * 2]; 227 char *end; 228 229 end = GNUNET_STRINGS_data_to_string (&gkph->h_payto, 230 sizeof (gkph->h_payto), 231 hstr, 232 sizeof (hstr)); 233 *end = '\0'; 234 GNUNET_asprintf (&arg_str, 235 "kyc-proof/%s?state=%s%s", 236 gkph->logic, 237 hstr, 238 (NULL != gkph->args) ? gkph->args : ""); 239 } 240 gkph->url = TALER_url_join (gkph->base_url, 241 arg_str, 242 NULL); 243 GNUNET_free (arg_str); 244 if (NULL == gkph->url) 245 return TALER_EC_GENERIC_CONFIGURATION_INVALID; 246 gkph->eh = TALER_EXCHANGE_curl_easy_get_ (gkph->url); 247 if (NULL == gkph->eh) 248 { 249 GNUNET_break (0); 250 GNUNET_free (gkph->url); 251 gkph->url = NULL; 252 return TALER_EC_GENERIC_CONFIGURATION_INVALID; 253 } 254 /* disable location following, we want to learn the 255 result of a 303 redirect! */ 256 curl_easy_setopt (gkph->eh, 257 CURLOPT_FOLLOWLOCATION, 258 0L); 259 gkph->job = GNUNET_CURL_job_add_raw (gkph->ctx, 260 gkph->eh, 261 NULL, 262 &handle_get_kyc_proof_finished, 263 gkph); 264 if (NULL == gkph->job) 265 { 266 curl_easy_cleanup (gkph->eh); 267 gkph->eh = NULL; 268 GNUNET_free (gkph->url); 269 gkph->url = NULL; 270 return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; 271 } 272 return TALER_EC_NONE; 273 } 274 275 276 void 277 TALER_EXCHANGE_get_kyc_proof_cancel ( 278 struct TALER_EXCHANGE_GetKycProofHandle *gkph) 279 { 280 if (NULL != gkph->job) 281 { 282 GNUNET_CURL_job_cancel (gkph->job); 283 gkph->job = NULL; 284 } 285 GNUNET_free (gkph->url); 286 GNUNET_free (gkph->logic); 287 GNUNET_free (gkph->base_url); 288 GNUNET_free (gkph); 289 } 290 291 292 /* end of exchange_api_get-kyc-proof-PROVIDER_NAME.c */