merchant_api_post-private-orders.c (8651B)
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-private-orders.c 21 * @brief Implementation of the POST /orders 22 * @author Christian Grothoff 23 * @author Marcello Stanisci 24 */ 25 #include "taler/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/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[], 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[], 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 , 216 unit_quantity_buf, 217 sizeof (unit_quantity_buf)); 218 219 ip = GNUNET_JSON_PACK ( 220 GNUNET_JSON_pack_string ("product_id", 221 inventory_products[i].product_id), 222 GNUNET_JSON_pack_string ("unit_quantity", 223 unit_quantity_buf)); 224 GNUNET_assert (NULL != ip); 225 GNUNET_assert (0 == 226 json_array_append_new (ipa, 227 ip)); 228 } 229 GNUNET_assert (0 == 230 json_object_set_new (req, 231 "inventory_products", 232 ipa)); 233 } 234 if (0 != uuids_length) 235 { 236 json_t *ua = json_array (); 237 238 GNUNET_assert (NULL != ua); 239 for (unsigned int i = 0; i<uuids_length; i++) 240 { 241 json_t *u; 242 243 u = json_string (uuids[i]); 244 GNUNET_assert (0 == 245 json_array_append_new (ua, 246 u)); 247 } 248 GNUNET_assert (0 == 249 json_object_set_new (req, 250 "lock_uuids", 251 ua)); 252 } 253 if (! create_token) 254 { 255 GNUNET_assert (0 == 256 json_object_set_new (req, 257 "create_token", 258 json_boolean (create_token))); 259 } 260 eh = TALER_MERCHANT_curl_easy_get_ (po->url); 261 if (GNUNET_OK != 262 TALER_curl_easy_post (&po->post_ctx, 263 eh, 264 req)) 265 { 266 GNUNET_break (0); 267 curl_easy_cleanup (eh); 268 json_decref (req); 269 GNUNET_free (po); 270 return NULL; 271 } 272 json_decref (req); 273 po->job = GNUNET_CURL_job_add2 (ctx, 274 eh, 275 po->post_ctx.headers, 276 &handle_post_order_finished, 277 po); 278 return po; 279 } 280 281 282 void 283 TALER_MERCHANT_orders_post_cancel ( 284 struct TALER_MERCHANT_PostOrdersHandle *po) 285 { 286 if (NULL != po->job) 287 { 288 GNUNET_CURL_job_cancel (po->job); 289 po->job = NULL; 290 } 291 GNUNET_free (po->url); 292 TALER_curl_easy_post_finished (&po->post_ctx); 293 GNUNET_free (po); 294 } 295 296 297 /* end of merchant_api_post_orders.c */