merchant_api_get-templates-TEMPLATE_ID.c (6193B)
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-templates-TEMPLATE_ID-new.c 19 * @brief Implementation of the GET /templates/$TEMPLATE_ID request (wallet-facing) 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-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 /templates/$TEMPLATE_ID operation (wallet-facing). 35 */ 36 struct TALER_MERCHANT_GetTemplatesHandle 37 { 38 /** 39 * Base URL of the merchant backend. 40 */ 41 char *base_url; 42 43 /** 44 * The full URL for this request. 45 */ 46 char *url; 47 48 /** 49 * Handle for the request. 50 */ 51 struct GNUNET_CURL_Job *job; 52 53 /** 54 * Function to call with the result. 55 */ 56 TALER_MERCHANT_GetTemplatesCallback cb; 57 58 /** 59 * Closure for @a cb. 60 */ 61 TALER_MERCHANT_GET_TEMPLATES_RESULT_CLOSURE *cb_cls; 62 63 /** 64 * Reference to the execution context. 65 */ 66 struct GNUNET_CURL_Context *ctx; 67 68 /** 69 * Template identifier. 70 */ 71 char *template_id; 72 }; 73 74 75 /** 76 * Function called when we're done processing the 77 * HTTP GET /templates/$TEMPLATE_ID request. 78 * 79 * @param cls the `struct TALER_MERCHANT_GetTemplatesHandle` 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_GetTemplatesHandle *gth = cls; 89 const json_t *json = response; 90 struct TALER_MERCHANT_GetTemplatesResponse wtgr = { 91 .hr.http_status = (unsigned int) response_code, 92 .hr.reply = json 93 }; 94 95 gth->job = NULL; 96 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 97 "Got /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 struct GNUNET_JSON_Specification spec[] = { 104 GNUNET_JSON_spec_object_const ("template_contract", 105 &wtgr.details.ok.template_contract), 106 GNUNET_JSON_spec_mark_optional ( 107 GNUNET_JSON_spec_object_const ( 108 "editable_defaults", 109 &wtgr.details.ok.editable_defaults), 110 NULL), 111 /* FIXME: never actually set by the merchant in the current code! */ 112 GNUNET_JSON_spec_mark_optional ( 113 GNUNET_JSON_spec_string ( 114 "required_currency", 115 &wtgr.details.ok.required_currency), 116 NULL), 117 GNUNET_JSON_spec_end () 118 }; 119 120 if (GNUNET_OK != 121 GNUNET_JSON_parse (json, 122 spec, 123 NULL, NULL)) 124 { 125 wtgr.hr.http_status = 0; 126 wtgr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; 127 break; 128 } 129 break; 130 } 131 case MHD_HTTP_UNAUTHORIZED: 132 wtgr.hr.ec = TALER_JSON_get_error_code (json); 133 wtgr.hr.hint = TALER_JSON_get_error_hint (json); 134 break; 135 case MHD_HTTP_NOT_FOUND: 136 wtgr.hr.ec = TALER_JSON_get_error_code (json); 137 wtgr.hr.hint = TALER_JSON_get_error_hint (json); 138 break; 139 default: 140 wtgr.hr.ec = TALER_JSON_get_error_code (json); 141 wtgr.hr.hint = TALER_JSON_get_error_hint (json); 142 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 143 "Unexpected response code %u/%d\n", 144 (unsigned int) response_code, 145 (int) wtgr.hr.ec); 146 break; 147 } 148 gth->cb (gth->cb_cls, 149 &wtgr); 150 TALER_MERCHANT_get_templates_cancel (gth); 151 } 152 153 154 struct TALER_MERCHANT_GetTemplatesHandle * 155 TALER_MERCHANT_get_templates_create ( 156 struct GNUNET_CURL_Context *ctx, 157 const char *url, 158 const char *template_id) 159 { 160 struct TALER_MERCHANT_GetTemplatesHandle *gth; 161 162 gth = GNUNET_new (struct TALER_MERCHANT_GetTemplatesHandle); 163 gth->ctx = ctx; 164 gth->base_url = GNUNET_strdup (url); 165 gth->template_id = GNUNET_strdup (template_id); 166 return gth; 167 } 168 169 170 enum TALER_ErrorCode 171 TALER_MERCHANT_get_templates_start ( 172 struct TALER_MERCHANT_GetTemplatesHandle *gth, 173 TALER_MERCHANT_GetTemplatesCallback cb, 174 TALER_MERCHANT_GET_TEMPLATES_RESULT_CLOSURE *cb_cls) 175 { 176 CURL *eh; 177 178 gth->cb = cb; 179 gth->cb_cls = cb_cls; 180 { 181 char *path; 182 183 GNUNET_asprintf (&path, 184 "templates/%s", 185 gth->template_id); 186 gth->url = TALER_url_join (gth->base_url, 187 path, 188 NULL); 189 GNUNET_free (path); 190 } 191 if (NULL == gth->url) 192 return TALER_EC_GENERIC_CONFIGURATION_INVALID; 193 eh = TALER_MERCHANT_curl_easy_get_ (gth->url); 194 if (NULL == eh) 195 return TALER_EC_GENERIC_CONFIGURATION_INVALID; 196 gth->job = GNUNET_CURL_job_add (gth->ctx, 197 eh, 198 &handle_get_template_finished, 199 gth); 200 if (NULL == gth->job) 201 return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; 202 return TALER_EC_NONE; 203 } 204 205 206 void 207 TALER_MERCHANT_get_templates_cancel ( 208 struct TALER_MERCHANT_GetTemplatesHandle *gth) 209 { 210 if (NULL != gth->job) 211 { 212 GNUNET_CURL_job_cancel (gth->job); 213 gth->job = NULL; 214 } 215 GNUNET_free (gth->url); 216 GNUNET_free (gth->base_url); 217 GNUNET_free (gth->template_id); 218 GNUNET_free (gth); 219 } 220 221 222 /* end of merchant_api_get-templates-TEMPLATE_ID-new.c */