exchange_api_post-kyc-start-ID.c (6894B)
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/platform.h" 23 #include "taler/taler_json_lib.h" 24 #include <microhttpd.h> 25 #include <gnunet/gnunet_curl_lib.h> 26 #include "taler/taler_exchange_service.h" 27 #include "taler/taler-exchange/post-kyc-start-ID.h" 28 #include "exchange_api_curl_defaults.h" 29 #include "taler/taler_signatures.h" 30 #include "taler/taler_curl_lib.h" 31 32 33 struct TALER_EXCHANGE_PostKycStartHandle 34 { 35 36 /** 37 * The base URL for this request. 38 */ 39 char *base_url; 40 41 /** 42 * The full URL for this request. 43 */ 44 char *url; 45 46 /** 47 * Minor context that holds body and headers. 48 */ 49 struct TALER_CURL_PostContext post_ctx; 50 51 /** 52 * Handle for the request. 53 */ 54 struct GNUNET_CURL_Job *job; 55 56 /** 57 * Function to call with the result. 58 */ 59 TALER_EXCHANGE_PostKycStartCallback cb; 60 61 /** 62 * Closure for @e cb. 63 */ 64 TALER_EXCHANGE_POST_KYC_START_RESULT_CLOSURE *cb_cls; 65 66 /** 67 * Reference to the execution context. 68 */ 69 struct GNUNET_CURL_Context *ctx; 70 71 /** 72 * Identifier for the KYC process to start. 73 */ 74 char *id; 75 76 }; 77 78 79 /** 80 * Function called when we're done processing the 81 * HTTP POST /kyc-start/$ID request. 82 * 83 * @param cls the `struct TALER_EXCHANGE_PostKycStartHandle *` 84 * @param response_code HTTP response code, 0 on error 85 * @param response response body, NULL if not in JSON 86 */ 87 static void 88 handle_kyc_start_finished (void *cls, 89 long response_code, 90 const void *response) 91 { 92 struct TALER_EXCHANGE_PostKycStartHandle *pksh = cls; 93 const json_t *json = response; 94 struct TALER_EXCHANGE_PostKycStartResponse adr = { 95 .hr.http_status = (unsigned int) response_code, 96 .hr.reply = json 97 }; 98 99 pksh->job = NULL; 100 switch (response_code) 101 { 102 case 0: 103 /* no reply */ 104 adr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; 105 adr.hr.hint = "server offline?"; 106 break; 107 case MHD_HTTP_OK: 108 { 109 struct GNUNET_JSON_Specification spec[] = { 110 GNUNET_JSON_spec_string ( 111 "redirect_url", 112 &adr.details.ok.redirect_url), 113 GNUNET_JSON_spec_end () 114 }; 115 116 if (GNUNET_OK != 117 GNUNET_JSON_parse (json, 118 spec, 119 NULL, NULL)) 120 { 121 GNUNET_break_op (0); 122 adr.hr.http_status = 0; 123 adr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; 124 break; 125 } 126 } 127 break; 128 case MHD_HTTP_BAD_REQUEST: 129 adr.hr.ec = TALER_JSON_get_error_code (json); 130 adr.hr.hint = TALER_JSON_get_error_hint (json); 131 break; 132 case MHD_HTTP_NOT_FOUND: 133 adr.hr.ec = TALER_JSON_get_error_code (json); 134 adr.hr.hint = TALER_JSON_get_error_hint (json); 135 break; 136 case MHD_HTTP_CONFLICT: 137 adr.hr.ec = TALER_JSON_get_error_code (json); 138 adr.hr.hint = TALER_JSON_get_error_hint (json); 139 break; 140 case MHD_HTTP_INTERNAL_SERVER_ERROR: 141 adr.hr.ec = TALER_JSON_get_error_code (json); 142 adr.hr.hint = TALER_JSON_get_error_hint (json); 143 break; 144 default: 145 /* unexpected response code */ 146 GNUNET_break_op (0); 147 adr.hr.ec = TALER_JSON_get_error_code (json); 148 adr.hr.hint = TALER_JSON_get_error_hint (json); 149 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 150 "Unexpected response code %u/%d for exchange POST kyc-start\n", 151 (unsigned int) response_code, 152 (int) adr.hr.ec); 153 break; 154 } 155 if (NULL != pksh->cb) 156 { 157 pksh->cb (pksh->cb_cls, 158 &adr); 159 pksh->cb = NULL; 160 } 161 TALER_EXCHANGE_post_kyc_start_cancel (pksh); 162 } 163 164 165 struct TALER_EXCHANGE_PostKycStartHandle * 166 TALER_EXCHANGE_post_kyc_start_create ( 167 struct GNUNET_CURL_Context *ctx, 168 const char *url, 169 const char *id) 170 { 171 struct TALER_EXCHANGE_PostKycStartHandle *pksh; 172 173 pksh = GNUNET_new (struct TALER_EXCHANGE_PostKycStartHandle); 174 pksh->ctx = ctx; 175 pksh->base_url = GNUNET_strdup (url); 176 pksh->id = GNUNET_strdup (id); 177 return pksh; 178 } 179 180 181 enum TALER_ErrorCode 182 TALER_EXCHANGE_post_kyc_start_start ( 183 struct TALER_EXCHANGE_PostKycStartHandle *pksh, 184 TALER_EXCHANGE_PostKycStartCallback cb, 185 TALER_EXCHANGE_POST_KYC_START_RESULT_CLOSURE *cb_cls) 186 { 187 CURL *eh; 188 json_t *body; 189 char *path; 190 191 pksh->cb = cb; 192 pksh->cb_cls = cb_cls; 193 GNUNET_asprintf (&path, 194 "kyc-start/%s", 195 pksh->id); 196 pksh->url = TALER_url_join (pksh->base_url, 197 path, 198 NULL); 199 GNUNET_free (path); 200 if (NULL == pksh->url) 201 { 202 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 203 "Could not construct request URL.\n"); 204 return TALER_EC_GENERIC_CONFIGURATION_INVALID; 205 } 206 body = json_object (); /* as per spec: empty! */ 207 GNUNET_assert (NULL != body); 208 eh = TALER_EXCHANGE_curl_easy_get_ (pksh->url); 209 if ( (NULL == eh) || 210 (GNUNET_OK != 211 TALER_curl_easy_post (&pksh->post_ctx, 212 eh, 213 body)) ) 214 { 215 GNUNET_break (0); 216 if (NULL != eh) 217 curl_easy_cleanup (eh); 218 json_decref (body); 219 GNUNET_free (pksh->url); 220 pksh->url = NULL; 221 return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; 222 } 223 json_decref (body); 224 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 225 "Requesting URL '%s'\n", 226 pksh->url); 227 pksh->job = GNUNET_CURL_job_add2 (pksh->ctx, 228 eh, 229 pksh->post_ctx.headers, 230 &handle_kyc_start_finished, 231 pksh); 232 if (NULL == pksh->job) 233 { 234 TALER_curl_easy_post_finished (&pksh->post_ctx); 235 GNUNET_free (pksh->url); 236 pksh->url = NULL; 237 return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; 238 } 239 return TALER_EC_NONE; 240 } 241 242 243 void 244 TALER_EXCHANGE_post_kyc_start_cancel ( 245 struct TALER_EXCHANGE_PostKycStartHandle *pksh) 246 { 247 if (NULL != pksh->job) 248 { 249 GNUNET_CURL_job_cancel (pksh->job); 250 pksh->job = NULL; 251 } 252 TALER_curl_easy_post_finished (&pksh->post_ctx); 253 GNUNET_free (pksh->url); 254 GNUNET_free (pksh->base_url); 255 GNUNET_free (pksh->id); 256 GNUNET_free (pksh); 257 } 258 259 260 /* end of exchange_api_post-kyc-start-ID.c */