merchant_api_get-management-instances-INSTANCE.c (8520B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2014-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 Lesser General Public License as published by the Free Software 7 Foundation; either version 2.1, 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 Lesser General Public License for more details. 12 13 You should have received a copy of the GNU Lesser General Public License along with 14 TALER; see the file COPYING.LGPL. If not, see 15 <http://www.gnu.org/licenses/> 16 */ 17 /** 18 * @file merchant_api_get-management-instances-INSTANCE-new.c 19 * @brief Implementation of the GET /management/instances/$INSTANCE request 20 * @author Christian Grothoff 21 */ 22 #include "taler/platform.h" 23 #include <curl/curl.h> 24 #include <jansson.h> 25 #include <microhttpd.h> /* just for HTTP status codes */ 26 #include <gnunet/gnunet_util_lib.h> 27 #include <gnunet/gnunet_curl_lib.h> 28 #include <taler/taler-merchant/get-management-instances-INSTANCE.h> 29 #include "merchant_api_curl_defaults.h" 30 #include <taler/taler_json_lib.h> 31 32 33 /** 34 * Handle for a GET /management/instances/$INSTANCE operation. 35 */ 36 struct TALER_MERCHANT_GetManagementInstanceHandle 37 { 38 /** 39 * Base URL of the merchant backend. 40 */ 41 char *base_url; 42 43 /** 44 * Instance identifier to query. 45 */ 46 char *instance_id; 47 48 /** 49 * The full URL for this request. 50 */ 51 char *url; 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_MERCHANT_GetManagementInstanceCallback cb; 62 63 /** 64 * Closure for @a cb. 65 */ 66 TALER_MERCHANT_GET_MANAGEMENT_INSTANCE_RESULT_CLOSURE *cb_cls; 67 68 /** 69 * Reference to the execution context. 70 */ 71 struct GNUNET_CURL_Context *ctx; 72 }; 73 74 75 /** 76 * Function called when we're done processing the 77 * HTTP GET /management/instances/$INSTANCE request. 78 * 79 * @param cls the `struct TALER_MERCHANT_GetManagementInstanceHandle` 80 * @param response_code HTTP response code, 0 on error 81 * @param response response body, NULL if not in JSON 82 */ 83 static void 84 handle_get_instance_finished (void *cls, 85 long response_code, 86 const void *response) 87 { 88 struct TALER_MERCHANT_GetManagementInstanceHandle *gmi = cls; 89 const json_t *json = response; 90 struct TALER_MERCHANT_GetManagementInstanceResponse igr = { 91 .hr.http_status = (unsigned int) response_code, 92 .hr.reply = json 93 }; 94 95 gmi->job = NULL; 96 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 97 "Got /management/instances/$INSTANCE response with status code %u\n", 98 (unsigned int) response_code); 99 switch (response_code) 100 { 101 case MHD_HTTP_OK: 102 { 103 const json_t *address; 104 const json_t *jurisdiction; 105 struct GNUNET_JSON_Specification spec[] = { 106 GNUNET_JSON_spec_string ( 107 "name", 108 &igr.details.ok.details.name), 109 GNUNET_JSON_spec_fixed_auto ( 110 "merchant_pub", 111 &igr.details.ok.details.merchant_pub), 112 GNUNET_JSON_spec_object_const ( 113 "address", 114 &address), 115 GNUNET_JSON_spec_object_const ( 116 "jurisdiction", 117 &jurisdiction), 118 GNUNET_JSON_spec_bool ( 119 "use_stefan", 120 &igr.details.ok.details.use_stefan), 121 GNUNET_JSON_spec_relative_time ( 122 "default_wire_transfer_delay", 123 &igr.details.ok.details.default_wire_transfer_delay), 124 GNUNET_JSON_spec_relative_time ( 125 "default_pay_delay", 126 &igr.details.ok.details.default_pay_delay), 127 GNUNET_JSON_spec_mark_optional ( 128 GNUNET_JSON_spec_relative_time ( 129 "default_refund_delay", 130 &igr.details.ok.details.default_refund_delay), 131 NULL), 132 GNUNET_JSON_spec_mark_optional ( 133 GNUNET_JSON_spec_time_rounder_interval ( 134 "default_wire_transfer_rounding_interval", 135 &igr.details.ok.details.default_wire_transfer_rounding_interval), 136 NULL), 137 GNUNET_JSON_spec_mark_optional ( 138 GNUNET_JSON_spec_string ( 139 "email", 140 &igr.details.ok.details.email), 141 NULL), 142 GNUNET_JSON_spec_mark_optional ( 143 GNUNET_JSON_spec_bool ( 144 "email_validated", 145 &igr.details.ok.details.email_validated), 146 NULL), 147 GNUNET_JSON_spec_mark_optional ( 148 GNUNET_JSON_spec_string ( 149 "phone_number", 150 &igr.details.ok.details.phone_number), 151 NULL), 152 GNUNET_JSON_spec_mark_optional ( 153 GNUNET_JSON_spec_bool ( 154 "phone_validated", 155 &igr.details.ok.details.phone_validated), 156 NULL), 157 GNUNET_JSON_spec_mark_optional ( 158 GNUNET_JSON_spec_string ( 159 "website", 160 &igr.details.ok.details.website), 161 NULL), 162 GNUNET_JSON_spec_mark_optional ( 163 GNUNET_JSON_spec_string ( 164 "logo", 165 &igr.details.ok.details.logo), 166 NULL), 167 GNUNET_JSON_spec_end () 168 }; 169 170 if (GNUNET_OK != 171 GNUNET_JSON_parse (json, 172 spec, 173 NULL, NULL)) 174 { 175 GNUNET_break_op (0); 176 igr.hr.http_status = 0; 177 igr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; 178 break; 179 } 180 igr.details.ok.details.address = address; 181 igr.details.ok.details.jurisdiction = jurisdiction; 182 gmi->cb (gmi->cb_cls, 183 &igr); 184 TALER_MERCHANT_get_management_instance_cancel (gmi); 185 return; 186 } 187 case MHD_HTTP_UNAUTHORIZED: 188 igr.hr.ec = TALER_JSON_get_error_code (json); 189 igr.hr.hint = TALER_JSON_get_error_hint (json); 190 break; 191 case MHD_HTTP_NOT_FOUND: 192 igr.hr.ec = TALER_JSON_get_error_code (json); 193 igr.hr.hint = TALER_JSON_get_error_hint (json); 194 break; 195 default: 196 igr.hr.ec = TALER_JSON_get_error_code (json); 197 igr.hr.hint = TALER_JSON_get_error_hint (json); 198 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 199 "Unexpected response code %u/%d\n", 200 (unsigned int) response_code, 201 (int) igr.hr.ec); 202 break; 203 } 204 gmi->cb (gmi->cb_cls, 205 &igr); 206 TALER_MERCHANT_get_management_instance_cancel (gmi); 207 } 208 209 210 struct TALER_MERCHANT_GetManagementInstanceHandle * 211 TALER_MERCHANT_get_management_instance_create ( 212 struct GNUNET_CURL_Context *ctx, 213 const char *url, 214 const char *instance_id) 215 { 216 struct TALER_MERCHANT_GetManagementInstanceHandle *gmi; 217 218 gmi = GNUNET_new (struct TALER_MERCHANT_GetManagementInstanceHandle); 219 gmi->ctx = ctx; 220 gmi->base_url = GNUNET_strdup (url); 221 if (NULL != instance_id) 222 gmi->instance_id = GNUNET_strdup (instance_id); 223 return gmi; 224 } 225 226 227 enum TALER_ErrorCode 228 TALER_MERCHANT_get_management_instance_start ( 229 struct TALER_MERCHANT_GetManagementInstanceHandle *gmi, 230 TALER_MERCHANT_GetManagementInstanceCallback cb, 231 TALER_MERCHANT_GET_MANAGEMENT_INSTANCE_RESULT_CLOSURE *cb_cls) 232 { 233 CURL *eh; 234 235 gmi->cb = cb; 236 gmi->cb_cls = cb_cls; 237 if (NULL != gmi->instance_id) 238 { 239 char *path; 240 241 GNUNET_asprintf (&path, 242 "instances/%s/private", 243 gmi->instance_id); 244 gmi->url = TALER_url_join (gmi->base_url, 245 path, 246 NULL); 247 GNUNET_free (path); 248 } 249 else 250 { 251 gmi->url = TALER_url_join (gmi->base_url, 252 "private", 253 NULL); 254 } 255 if (NULL == gmi->url) 256 return TALER_EC_GENERIC_CONFIGURATION_INVALID; 257 eh = TALER_MERCHANT_curl_easy_get_ (gmi->url); 258 if (NULL == eh) 259 return TALER_EC_GENERIC_CONFIGURATION_INVALID; 260 gmi->job = GNUNET_CURL_job_add (gmi->ctx, 261 eh, 262 &handle_get_instance_finished, 263 gmi); 264 if (NULL == gmi->job) 265 return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; 266 return TALER_EC_NONE; 267 } 268 269 270 void 271 TALER_MERCHANT_get_management_instance_cancel ( 272 struct TALER_MERCHANT_GetManagementInstanceHandle *gmi) 273 { 274 if (NULL != gmi->job) 275 { 276 GNUNET_CURL_job_cancel (gmi->job); 277 gmi->job = NULL; 278 } 279 GNUNET_free (gmi->url); 280 GNUNET_free (gmi->instance_id); 281 GNUNET_free (gmi->base_url); 282 GNUNET_free (gmi); 283 } 284 285 286 /* end of merchant_api_get-management-instances-INSTANCE-new.c */