merchant_api_post_orders.c (8623B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2014-2023 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, but 11 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 Public 16 License along with TALER; see the file COPYING.LGPL. If not, 17 see <http://www.gnu.org/licenses/> 18 */ 19 /** 20 * @file merchant_api_post_orders.c 21 * @brief Implementation of the POST /orders 22 * @author Christian Grothoff 23 * @author Marcello Stanisci 24 */ 25 #include "platform.h" 26 #include <curl/curl.h> 27 #include <jansson.h> 28 #include <microhttpd.h> /* just for HTTP status codes */ 29 #include <gnunet/gnunet_util_lib.h> 30 #include <gnunet/gnunet_curl_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 38 39 /** 40 * @brief A POST /orders Handle 41 */ 42 struct TALER_MERCHANT_PostOrdersHandle 43 { 44 45 /** 46 * The url for this request. 47 */ 48 char *url; 49 50 /** 51 * Handle for the request. 52 */ 53 struct GNUNET_CURL_Job *job; 54 55 /** 56 * Function to call with the result. 57 */ 58 TALER_MERCHANT_PostOrdersCallback cb; 59 60 /** 61 * Closure for @a cb. 62 */ 63 void *cb_cls; 64 65 /** 66 * Reference to the execution context. 67 */ 68 struct GNUNET_CURL_Context *ctx; 69 70 /** 71 * Minor context that holds body and headers. 72 */ 73 struct TALER_CURL_PostContext post_ctx; 74 }; 75 76 77 /** 78 * Function called when we're done processing the 79 * HTTP POST /orders request. 80 * 81 * @param cls the `struct TALER_MERCHANT_PostOrdersHandle` 82 * @param response_code HTTP response code, 0 on error 83 * @param response response body, NULL if not JSON 84 */ 85 static void 86 handle_post_order_finished (void *cls, 87 long response_code, 88 const void *response) 89 { 90 struct TALER_MERCHANT_PostOrdersHandle *po = cls; 91 const json_t *json = response; 92 93 po->job = NULL; 94 TALER_MERCHANT_handle_order_creation_response_ (po->cb, 95 po->cb_cls, 96 response_code, 97 json); 98 TALER_MERCHANT_orders_post_cancel (po); 99 } 100 101 102 struct TALER_MERCHANT_PostOrdersHandle * 103 TALER_MERCHANT_orders_post (struct GNUNET_CURL_Context *ctx, 104 const char *backend_url, 105 const json_t *order, 106 struct GNUNET_TIME_Relative refund_delay, 107 TALER_MERCHANT_PostOrdersCallback cb, 108 void *cb_cls) 109 { 110 static const char *no_uuids[GNUNET_NZL (0)]; 111 112 return TALER_MERCHANT_orders_post2 (ctx, 113 backend_url, 114 order, 115 refund_delay, 116 NULL, 117 0, 118 NULL, 119 0, 120 no_uuids, 121 true, 122 cb, 123 cb_cls); 124 } 125 126 127 struct TALER_MERCHANT_PostOrdersHandle * 128 TALER_MERCHANT_orders_post2 ( 129 struct GNUNET_CURL_Context *ctx, 130 const char *backend_url, 131 const json_t *order, 132 struct GNUNET_TIME_Relative refund_delay, 133 const char *payment_target, 134 unsigned int inventory_products_length, 135 const struct TALER_MERCHANT_InventoryProduct inventory_products[], 136 unsigned int uuids_length, 137 const char *uuids[static uuids_length], 138 bool create_token, 139 TALER_MERCHANT_PostOrdersCallback cb, 140 void *cb_cls) 141 { 142 return TALER_MERCHANT_orders_post3 ( 143 ctx, 144 backend_url, 145 order, 146 NULL, /* session ID */ 147 refund_delay, 148 payment_target, 149 inventory_products_length, 150 inventory_products, 151 uuids_length, 152 uuids, 153 create_token, 154 cb, 155 cb_cls); 156 } 157 158 159 struct TALER_MERCHANT_PostOrdersHandle * 160 TALER_MERCHANT_orders_post3 ( 161 struct GNUNET_CURL_Context *ctx, 162 const char *backend_url, 163 const json_t *order, 164 const char *session_id, 165 struct GNUNET_TIME_Relative refund_delay, 166 const char *payment_target, 167 unsigned int inventory_products_length, 168 const struct TALER_MERCHANT_InventoryProduct inventory_products[], 169 unsigned int uuids_length, 170 const char *uuids[static uuids_length], 171 bool create_token, 172 TALER_MERCHANT_PostOrdersCallback cb, 173 void *cb_cls) 174 { 175 struct TALER_MERCHANT_PostOrdersHandle *po; 176 json_t *req; 177 CURL *eh; 178 179 po = GNUNET_new (struct TALER_MERCHANT_PostOrdersHandle); 180 po->ctx = ctx; 181 po->cb = cb; 182 po->cb_cls = cb_cls; 183 po->url = TALER_url_join (backend_url, 184 "private/orders", 185 NULL); 186 req = GNUNET_JSON_PACK ( 187 GNUNET_JSON_pack_object_incref ("order", 188 (json_t *) order), 189 GNUNET_JSON_pack_allow_null ( 190 GNUNET_JSON_pack_string ("session_id", 191 session_id)), 192 GNUNET_JSON_pack_allow_null ( 193 GNUNET_JSON_pack_string ("payment_target", 194 payment_target))); 195 if (0 != refund_delay.rel_value_us) 196 { 197 GNUNET_assert (0 == 198 json_object_set_new (req, 199 "refund_delay", 200 GNUNET_JSON_from_time_rel ( 201 refund_delay))); 202 } 203 if (0 != inventory_products_length) 204 { 205 json_t *ipa = json_array (); 206 207 GNUNET_assert (NULL != ipa); 208 for (unsigned int i = 0; i<inventory_products_length; i++) 209 { 210 json_t *ip; 211 char unit_quantity_buf[64]; 212 213 TALER_MERCHANT_format_quantity_string (inventory_products[i].quantity, 214 inventory_products[i].quantity_frac, 215 unit_quantity_buf, 216 sizeof (unit_quantity_buf)); 217 218 ip = GNUNET_JSON_PACK ( 219 GNUNET_JSON_pack_string ("product_id", 220 inventory_products[i].product_id), 221 GNUNET_JSON_pack_string ("unit_quantity", 222 unit_quantity_buf)); 223 GNUNET_assert (NULL != ip); 224 GNUNET_assert (0 == 225 json_array_append_new (ipa, 226 ip)); 227 } 228 GNUNET_assert (0 == 229 json_object_set_new (req, 230 "inventory_products", 231 ipa)); 232 } 233 if (0 != uuids_length) 234 { 235 json_t *ua = json_array (); 236 237 GNUNET_assert (NULL != ua); 238 for (unsigned int i = 0; i<uuids_length; i++) 239 { 240 json_t *u; 241 242 u = json_string (uuids[i]); 243 GNUNET_assert (0 == 244 json_array_append_new (ua, 245 u)); 246 } 247 GNUNET_assert (0 == 248 json_object_set_new (req, 249 "lock_uuids", 250 ua)); 251 } 252 if (! create_token) 253 { 254 GNUNET_assert (0 == 255 json_object_set_new (req, 256 "create_token", 257 json_boolean (create_token))); 258 } 259 eh = TALER_MERCHANT_curl_easy_get_ (po->url); 260 if (GNUNET_OK != 261 TALER_curl_easy_post (&po->post_ctx, 262 eh, 263 req)) 264 { 265 GNUNET_break (0); 266 curl_easy_cleanup (eh); 267 json_decref (req); 268 GNUNET_free (po); 269 return NULL; 270 } 271 json_decref (req); 272 po->job = GNUNET_CURL_job_add2 (ctx, 273 eh, 274 po->post_ctx.headers, 275 &handle_post_order_finished, 276 po); 277 return po; 278 } 279 280 281 void 282 TALER_MERCHANT_orders_post_cancel ( 283 struct TALER_MERCHANT_PostOrdersHandle *po) 284 { 285 if (NULL != po->job) 286 { 287 GNUNET_CURL_job_cancel (po->job); 288 po->job = NULL; 289 } 290 GNUNET_free (po->url); 291 TALER_curl_easy_post_finished (&po->post_ctx); 292 GNUNET_free (po); 293 } 294 295 296 /* end of merchant_api_post_orders.c */