merchant_api_post_donau_instance.c (6239B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2024 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify 6 it under the terms of the GNU Lesser General Public License as 7 published by the Free Software Foundation; either version 2.1, 8 or (at your option) any later version. 9 10 TALER is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General 16 Public License along with TALER; see the file COPYING.LGPL. 17 If not, see <http://www.gnu.org/licenses/> 18 */ 19 /** 20 * @file merchant_api_post_donau_instance.c 21 * @brief Implementation of the POST /donau request 22 * of the merchant's HTTP API 23 * @author Bohdan Potuzhnyi 24 * @author Vlada Svirsh 25 */ 26 #include "platform.h" 27 #include <curl/curl.h> 28 #include <jansson.h> 29 #include <microhttpd.h> /* just for HTTP status codes */ 30 #include <gnunet/gnunet_util_lib.h> 31 #include "taler_merchant_service.h" 32 #include "merchant_api_curl_defaults.h" 33 #include "merchant_api_common.h" 34 #include <taler/taler_json_lib.h> 35 #include <taler/taler_signatures.h> 36 #include <taler/taler_curl_lib.h> 37 #include <taler/taler_kyclogic_lib.h> 38 /* DONAU RELATED IMPORTS */ 39 #include "taler_merchant_donau.h" 40 #include <donau/donau_service.h> 41 42 43 /** 44 * Handle for a POST /donau operation. 45 */ 46 struct TALER_MERCHANT_DonauInstancePostHandle 47 { 48 /** 49 * URL for this request. 50 */ 51 char *url; 52 53 /** 54 * Handle for the CURL job. 55 */ 56 struct GNUNET_CURL_Job *job; 57 58 /** 59 * Function to call with the result. 60 */ 61 TALER_MERCHANT_DonauInstancePostCallback cb; 62 63 /** 64 * Closure for @a cb. 65 */ 66 void *cb_cls; 67 68 /** 69 * Reference to the execution context. 70 */ 71 struct GNUNET_CURL_Context *ctx; 72 73 /** 74 * Minor context that holds body and headers. 75 */ 76 struct TALER_CURL_PostContext post_ctx; 77 }; 78 79 80 /** 81 * Function called when the POST /donau operation is finished. 82 * 83 * @param cls the `struct TALER_MERCHANT_DonauInstancePostHandle` 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_post_donau_finished (void *cls, 89 long response_code, 90 const void *response) 91 { 92 struct TALER_MERCHANT_DonauInstancePostHandle *dph = cls; 93 const json_t *json = response; 94 struct TALER_MERCHANT_HttpResponse hr = { 95 .http_status = (unsigned int) response_code, 96 .reply = json 97 }; 98 99 dph->job = NULL; 100 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 101 "POST /donau completed with response code %u\n", 102 (unsigned int) response_code); 103 104 switch (response_code) 105 { 106 case 0: 107 hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; 108 break; 109 case MHD_HTTP_NO_CONTENT: 110 break; 111 case MHD_HTTP_BAD_REQUEST: 112 case MHD_HTTP_INTERNAL_SERVER_ERROR: 113 default: 114 TALER_MERCHANT_parse_error_details_ (json, 115 response_code, 116 &hr); 117 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 118 "Unexpected response code %u/%d\n", 119 (unsigned int) response_code, 120 (int) hr.ec); 121 break; 122 } 123 124 dph->cb (dph->cb_cls, 125 &hr); 126 TALER_MERCHANT_donau_instances_post_cancel (dph); 127 } 128 129 130 struct TALER_MERCHANT_DonauInstancePostHandle * 131 TALER_MERCHANT_donau_instances_post ( 132 struct GNUNET_CURL_Context *ctx, 133 const char *backend_url, 134 const struct TALER_MERCHANT_DONAU_Charity *charity, 135 const char *auth_token, 136 TALER_MERCHANT_DonauInstancePostCallback cb, 137 void *cb_cls) 138 { 139 struct TALER_MERCHANT_DonauInstancePostHandle *dph; 140 json_t *req_obj; 141 json_t *auth_obj; 142 143 if (NULL != auth_token) 144 { 145 if (0 != strncasecmp (RFC_8959_PREFIX, 146 auth_token, 147 strlen (RFC_8959_PREFIX))) 148 { 149 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 150 "Authentication token must start with `%s'\n", 151 RFC_8959_PREFIX); 152 return NULL; 153 } 154 auth_obj = GNUNET_JSON_PACK ( 155 GNUNET_JSON_pack_string ("method", 156 "token"), 157 GNUNET_JSON_pack_string ("token", 158 auth_token)); 159 } 160 else 161 { 162 auth_obj = GNUNET_JSON_PACK ( 163 GNUNET_JSON_pack_string ("method", 164 "external")); 165 } 166 if (NULL == auth_obj) 167 { 168 GNUNET_break (0); 169 return NULL; 170 } 171 172 req_obj = GNUNET_JSON_PACK ( 173 GNUNET_JSON_pack_string ("donau_url", 174 charity->charity_url), 175 GNUNET_JSON_pack_uint64 ("charity_id", 176 charity->charity_id) 177 ); 178 179 dph = GNUNET_new (struct TALER_MERCHANT_DonauInstancePostHandle); 180 dph->ctx = ctx; 181 dph->cb = cb; 182 dph->cb_cls = cb_cls; 183 dph->url = TALER_url_join (backend_url, 184 "private/donau", 185 NULL); 186 187 if (NULL == dph->url) 188 { 189 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 190 "Failed to construct request URL\n"); 191 json_decref (req_obj); 192 GNUNET_free (dph); 193 return NULL; 194 } 195 { 196 CURL *eh; 197 198 eh = TALER_MERCHANT_curl_easy_get_ (dph->url); 199 if (GNUNET_OK != TALER_curl_easy_post (&dph->post_ctx, 200 eh, 201 req_obj)) 202 { 203 GNUNET_break (0); 204 curl_easy_cleanup (eh); 205 json_decref (req_obj); 206 GNUNET_free (dph); 207 return NULL; 208 } 209 210 json_decref (req_obj); 211 212 dph->job = GNUNET_CURL_job_add2 (ctx, 213 eh, 214 dph->post_ctx.headers, 215 &handle_post_donau_finished, 216 dph); 217 } 218 return dph; 219 } 220 221 222 void 223 TALER_MERCHANT_donau_instances_post_cancel ( 224 struct TALER_MERCHANT_DonauInstancePostHandle *dph) 225 { 226 if (NULL != dph->job) 227 { 228 GNUNET_CURL_job_cancel (dph->job); 229 dph->job = NULL; 230 } 231 TALER_curl_easy_post_finished (&dph->post_ctx); 232 GNUNET_free (dph->url); 233 GNUNET_free (dph); 234 } 235 236 237 /* end of merchant_api_post_donau_instance.c */