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