exchange_api_get-kyc-proof-PROVIDER_NAME.c (7949B)
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 * OAuth2 state identifying the target account. Heap-allocated copy. 75 */ 76 char *state; 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_FORBIDDEN: 141 /* KYC process failed, or the request was not issued for it */ 142 break; 143 case MHD_HTTP_NOT_FOUND: 144 break; 145 case MHD_HTTP_INTERNAL_SERVER_ERROR: 146 /* Server had an internal issue; we should retry, but this API 147 leaves this to the application */ 148 break; 149 case MHD_HTTP_BAD_GATEWAY: 150 /* Server had an internal issue; we should retry, but this API 151 leaves this to the application */ 152 break; 153 case MHD_HTTP_GATEWAY_TIMEOUT: 154 /* Server had an internal issue; we should retry, but this API 155 leaves this to the application */ 156 break; 157 default: 158 /* unexpected response code */ 159 GNUNET_break_op (0); 160 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 161 "Unexpected response code %u for exchange get_kyc_proof\n", 162 (unsigned int) response_code); 163 break; 164 } 165 gkph->cb (gkph->cb_cls, 166 &gkpr); 167 TALER_EXCHANGE_get_kyc_proof_cancel (gkph); 168 } 169 170 171 struct TALER_EXCHANGE_GetKycProofHandle * 172 TALER_EXCHANGE_get_kyc_proof_create ( 173 struct GNUNET_CURL_Context *ctx, 174 const char *url, 175 const char *state, 176 const char *logic) 177 { 178 struct TALER_EXCHANGE_GetKycProofHandle *gkph; 179 180 gkph = GNUNET_new (struct TALER_EXCHANGE_GetKycProofHandle); 181 gkph->ctx = ctx; 182 gkph->base_url = GNUNET_strdup (url); 183 gkph->state = GNUNET_strdup (state); 184 gkph->logic = GNUNET_strdup (logic); 185 return gkph; 186 } 187 188 189 enum GNUNET_GenericReturnValue 190 TALER_EXCHANGE_get_kyc_proof_set_options_ ( 191 struct TALER_EXCHANGE_GetKycProofHandle *gkph, 192 unsigned int num_options, 193 const struct TALER_EXCHANGE_GetKycProofOptionValue *options) 194 { 195 for (unsigned int i = 0; i < num_options; i++) 196 { 197 const struct TALER_EXCHANGE_GetKycProofOptionValue *opt = &options[i]; 198 199 switch (opt->option) 200 { 201 case TALER_EXCHANGE_GET_KYC_PROOF_OPTION_END: 202 return GNUNET_OK; 203 case TALER_EXCHANGE_GET_KYC_PROOF_OPTION_ARGS: 204 GNUNET_assert (opt->details.args[0] == '&'); 205 gkph->args = opt->details.args; 206 break; 207 } 208 } 209 return GNUNET_OK; 210 } 211 212 213 enum TALER_ErrorCode 214 TALER_EXCHANGE_get_kyc_proof_start ( 215 struct TALER_EXCHANGE_GetKycProofHandle *gkph, 216 TALER_EXCHANGE_GetKycProofCallback cb, 217 TALER_EXCHANGE_GET_KYC_PROOF_RESULT_CLOSURE *cb_cls) 218 { 219 if (NULL != gkph->job) 220 { 221 GNUNET_break (0); 222 return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; 223 } 224 gkph->cb = cb; 225 gkph->cb_cls = cb_cls; 226 { 227 char *arg_str; 228 char *url; 229 230 GNUNET_asprintf (&arg_str, 231 "kyc-proof/%s", 232 gkph->logic); 233 url = TALER_url_join (gkph->base_url, 234 arg_str, 235 "state", gkph->state, 236 NULL); 237 GNUNET_free (arg_str); 238 if (NULL == url) 239 { 240 GNUNET_break (0); 241 return TALER_EC_GENERIC_CONFIGURATION_INVALID; 242 } 243 if (NULL != gkph->args) 244 { 245 GNUNET_asprintf (&gkph->url, 246 "%s%s", 247 url, 248 gkph->args); 249 GNUNET_free (url); 250 } 251 else 252 { 253 gkph->url = url; 254 } 255 } 256 gkph->eh = TALER_EXCHANGE_curl_easy_get_ (gkph->url); 257 if (NULL == gkph->eh) 258 { 259 GNUNET_break (0); 260 GNUNET_free (gkph->url); 261 return TALER_EC_GENERIC_CONFIGURATION_INVALID; 262 } 263 /* disable location following, we want to learn the 264 result of a 303 redirect! */ 265 GNUNET_assert (CURLE_OK == 266 curl_easy_setopt (gkph->eh, 267 CURLOPT_FOLLOWLOCATION, 268 0L)); 269 gkph->job = GNUNET_CURL_job_add_raw (gkph->ctx, 270 gkph->eh, 271 NULL, 272 &handle_get_kyc_proof_finished, 273 gkph); 274 if (NULL == gkph->job) 275 { 276 curl_easy_cleanup (gkph->eh); 277 gkph->eh = NULL; 278 GNUNET_free (gkph->url); 279 return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; 280 } 281 return TALER_EC_NONE; 282 } 283 284 285 void 286 TALER_EXCHANGE_get_kyc_proof_cancel ( 287 struct TALER_EXCHANGE_GetKycProofHandle *gkph) 288 { 289 if (NULL != gkph->job) 290 { 291 GNUNET_CURL_job_cancel (gkph->job); 292 gkph->job = NULL; 293 } 294 GNUNET_free (gkph->url); 295 GNUNET_free (gkph->logic); 296 GNUNET_free (gkph->state); 297 GNUNET_free (gkph->base_url); 298 GNUNET_free (gkph); 299 } 300 301 302 /* end of exchange_api_get-kyc-proof-PROVIDER_NAME.c */