merchant_api_get-private-templates-TEMPLATE_ID.c (6728B)
1 /* 2 This file is part of TALER 3 Copyright (C) 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 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-private-templates-TEMPLATE_ID-new.c 19 * @brief Implementation of the GET /private/templates/$TEMPLATE_ID 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-private-templates-TEMPLATE_ID.h> 29 #include "merchant_api_curl_defaults.h" 30 #include <taler/taler_json_lib.h> 31 32 33 /** 34 * Handle for a GET /private/templates/$TEMPLATE_ID operation. 35 */ 36 struct TALER_MERCHANT_GetPrivateTemplateHandle 37 { 38 /** 39 * Base URL of the merchant backend. 40 */ 41 char *base_url; 42 43 /** 44 * Template identifier. 45 */ 46 char *template_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_GetPrivateTemplateCallback cb; 62 63 /** 64 * Closure for @a cb. 65 */ 66 TALER_MERCHANT_GET_PRIVATE_TEMPLATE_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 /private/templates/$TEMPLATE_ID request. 78 * 79 * @param cls the `struct TALER_MERCHANT_GetPrivateTemplateHandle` 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_template_finished (void *cls, 85 long response_code, 86 const void *response) 87 { 88 struct TALER_MERCHANT_GetPrivateTemplateHandle *gpt = cls; 89 const json_t *json = response; 90 struct TALER_MERCHANT_GetPrivateTemplateResponse tgr = { 91 .hr.http_status = (unsigned int) response_code, 92 .hr.reply = json 93 }; 94 95 gpt->job = NULL; 96 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 97 "Got /private/templates/$TEMPLATE_ID 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 *contract; 104 struct GNUNET_JSON_Specification spec[] = { 105 GNUNET_JSON_spec_string ("template_description", 106 &tgr.details.ok.template_description), 107 GNUNET_JSON_spec_mark_optional ( 108 GNUNET_JSON_spec_string ("otp_id", 109 &tgr.details.ok.otp_id), 110 NULL), 111 GNUNET_JSON_spec_object_const ("template_contract", 112 &contract), 113 GNUNET_JSON_spec_mark_optional ( 114 GNUNET_JSON_spec_object_const ("editable_defaults", 115 &tgr.details.ok.editable_defaults), 116 NULL), 117 GNUNET_JSON_spec_mark_optional ( 118 GNUNET_JSON_spec_string ("required_currency", 119 &tgr.details.ok.required_currency), 120 NULL), 121 GNUNET_JSON_spec_end () 122 }; 123 124 if (GNUNET_OK == 125 GNUNET_JSON_parse (json, 126 spec, 127 NULL, NULL)) 128 { 129 tgr.details.ok.template_contract = contract; 130 gpt->cb (gpt->cb_cls, 131 &tgr); 132 TALER_MERCHANT_get_private_template_cancel (gpt); 133 return; 134 } 135 tgr.hr.http_status = 0; 136 tgr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; 137 break; 138 } 139 case MHD_HTTP_UNAUTHORIZED: 140 tgr.hr.ec = TALER_JSON_get_error_code (json); 141 tgr.hr.hint = TALER_JSON_get_error_hint (json); 142 break; 143 case MHD_HTTP_NOT_FOUND: 144 tgr.hr.ec = TALER_JSON_get_error_code (json); 145 tgr.hr.hint = TALER_JSON_get_error_hint (json); 146 break; 147 default: 148 tgr.hr.ec = TALER_JSON_get_error_code (json); 149 tgr.hr.hint = TALER_JSON_get_error_hint (json); 150 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 151 "Unexpected response code %u/%d\n", 152 (unsigned int) response_code, 153 (int) tgr.hr.ec); 154 break; 155 } 156 gpt->cb (gpt->cb_cls, 157 &tgr); 158 TALER_MERCHANT_get_private_template_cancel (gpt); 159 } 160 161 162 struct TALER_MERCHANT_GetPrivateTemplateHandle * 163 TALER_MERCHANT_get_private_template_create ( 164 struct GNUNET_CURL_Context *ctx, 165 const char *url, 166 const char *template_id) 167 { 168 struct TALER_MERCHANT_GetPrivateTemplateHandle *gpt; 169 170 gpt = GNUNET_new (struct TALER_MERCHANT_GetPrivateTemplateHandle); 171 gpt->ctx = ctx; 172 gpt->base_url = GNUNET_strdup (url); 173 gpt->template_id = GNUNET_strdup (template_id); 174 return gpt; 175 } 176 177 178 enum TALER_ErrorCode 179 TALER_MERCHANT_get_private_template_start ( 180 struct TALER_MERCHANT_GetPrivateTemplateHandle *gpt, 181 TALER_MERCHANT_GetPrivateTemplateCallback cb, 182 TALER_MERCHANT_GET_PRIVATE_TEMPLATE_RESULT_CLOSURE *cb_cls) 183 { 184 CURL *eh; 185 186 gpt->cb = cb; 187 gpt->cb_cls = cb_cls; 188 { 189 char *path; 190 191 GNUNET_asprintf (&path, 192 "private/templates/%s", 193 gpt->template_id); 194 gpt->url = TALER_url_join (gpt->base_url, 195 path, 196 NULL); 197 GNUNET_free (path); 198 } 199 if (NULL == gpt->url) 200 return TALER_EC_GENERIC_CONFIGURATION_INVALID; 201 eh = TALER_MERCHANT_curl_easy_get_ (gpt->url); 202 if (NULL == eh) 203 return TALER_EC_GENERIC_CONFIGURATION_INVALID; 204 gpt->job = GNUNET_CURL_job_add (gpt->ctx, 205 eh, 206 &handle_get_template_finished, 207 gpt); 208 if (NULL == gpt->job) 209 return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; 210 return TALER_EC_NONE; 211 } 212 213 214 void 215 TALER_MERCHANT_get_private_template_cancel ( 216 struct TALER_MERCHANT_GetPrivateTemplateHandle *gpt) 217 { 218 if (NULL != gpt->job) 219 { 220 GNUNET_CURL_job_cancel (gpt->job); 221 gpt->job = NULL; 222 } 223 GNUNET_free (gpt->url); 224 GNUNET_free (gpt->template_id); 225 GNUNET_free (gpt->base_url); 226 GNUNET_free (gpt); 227 } 228 229 230 /* end of merchant_api_get-private-templates-TEMPLATE_ID-new.c */