diff options
Diffstat (limited to 'src/lib/merchant_api_get_orders.c')
-rw-r--r-- | src/lib/merchant_api_get_orders.c | 233 |
1 files changed, 148 insertions, 85 deletions
diff --git a/src/lib/merchant_api_get_orders.c b/src/lib/merchant_api_get_orders.c index 7f08acb6..459409fd 100644 --- a/src/lib/merchant_api_get_orders.c +++ b/src/lib/merchant_api_get_orders.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2018, 2020, 2021 Taler Systems SA + Copyright (C) 2014-2023 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -30,6 +30,10 @@ #include <taler/taler_json_lib.h> #include <taler/taler_signatures.h> +/** + * Maximum number of orders we return. + */ +#define MAX_ORDERS 1024 /** * Handle for a GET /orders operation. @@ -68,65 +72,64 @@ struct TALER_MERCHANT_OrdersGetHandle * Parse order information from @a ia. * * @param ia JSON array (or NULL!) with order data + * @param[in] ogr response to fill * @param ogh operation handle * @return #GNUNET_OK on success */ static enum GNUNET_GenericReturnValue parse_orders (const json_t *ia, + struct TALER_MERCHANT_OrdersGetResponse *ogr, struct TALER_MERCHANT_OrdersGetHandle *ogh) { - unsigned int oes_len = json_array_size (ia); - struct TALER_MERCHANT_OrderEntry oes[oes_len]; - size_t index; - json_t *value; - int ret; - - ret = GNUNET_OK; - json_array_foreach (ia, index, value) { - struct TALER_MERCHANT_OrderEntry *ie = &oes[index]; - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_string ("order_id", - &ie->order_id), - GNUNET_JSON_spec_timestamp ("timestamp", - &ie->timestamp), - GNUNET_JSON_spec_uint64 ("row_id", - &ie->order_serial), - TALER_JSON_spec_amount_any ("amount", - &ie->amount), - GNUNET_JSON_spec_string ("summary", - &ie->summary), - GNUNET_JSON_spec_bool ("refundable", - &ie->refundable), - GNUNET_JSON_spec_bool ("paid", - &ie->paid), - GNUNET_JSON_spec_end () - }; + unsigned int oes_len = (unsigned int) json_array_size (ia); - if (GNUNET_OK != - GNUNET_JSON_parse (value, - spec, - NULL, NULL)) - { - GNUNET_break_op (0); - ret = GNUNET_SYSERR; - continue; - } - if (GNUNET_SYSERR == ret) - break; + if ( (json_array_size (ia) != (size_t) oes_len) || + (oes_len > MAX_ORDERS) ) + { + GNUNET_break (0); + return GNUNET_SYSERR; } - if (GNUNET_OK == ret) { - struct TALER_MERCHANT_HttpResponse hr = { - .http_status = MHD_HTTP_OK - }; + struct TALER_MERCHANT_OrderEntry oes[GNUNET_NZL (oes_len)]; + size_t index; + json_t *value; + + json_array_foreach (ia, index, value) { + struct TALER_MERCHANT_OrderEntry *ie = &oes[index]; + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_string ("order_id", + &ie->order_id), + GNUNET_JSON_spec_timestamp ("timestamp", + &ie->timestamp), + GNUNET_JSON_spec_uint64 ("row_id", + &ie->order_serial), + TALER_JSON_spec_amount_any ("amount", + &ie->amount), + GNUNET_JSON_spec_string ("summary", + &ie->summary), + GNUNET_JSON_spec_bool ("refundable", + &ie->refundable), + GNUNET_JSON_spec_bool ("paid", + &ie->paid), + GNUNET_JSON_spec_end () + }; + if (GNUNET_OK != + GNUNET_JSON_parse (value, + spec, + NULL, NULL)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + } + ogr->details.ok.orders_length = oes_len; + ogr->details.ok.orders = oes; ogh->cb (ogh->cb_cls, - &hr, - oes_len, - oes); + ogr); ogh->cb = NULL; /* just to be sure */ } - return ret; + return GNUNET_OK; } @@ -145,9 +148,9 @@ handle_get_orders_finished (void *cls, { struct TALER_MERCHANT_OrdersGetHandle *ogh = cls; const json_t *json = response; - struct TALER_MERCHANT_HttpResponse hr = { - .http_status = (unsigned int) response_code, - .reply = json + struct TALER_MERCHANT_OrdersGetResponse ogr = { + .hr.http_status = (unsigned int) response_code, + .hr.reply = json }; ogh->job = NULL; @@ -158,10 +161,10 @@ handle_get_orders_finished (void *cls, { case MHD_HTTP_OK: { - json_t *orders; + const json_t *orders; struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_json ("orders", - &orders), + GNUNET_JSON_spec_array_const ("orders", + &orders), GNUNET_JSON_spec_end () }; @@ -170,52 +173,43 @@ handle_get_orders_finished (void *cls, spec, NULL, NULL)) { - hr.http_status = 0; - hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; + ogr.hr.http_status = 0; + ogr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; + break; } - else + if (GNUNET_OK == + parse_orders (orders, + &ogr, + ogh)) { - if ( (! json_is_array (orders)) || - (GNUNET_OK == - parse_orders (orders, - ogh)) ) - { - GNUNET_JSON_parse_free (spec); - TALER_MERCHANT_orders_get_cancel (ogh); - return; - } - else - { - hr.http_status = 0; - hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - } + TALER_MERCHANT_orders_get_cancel (ogh); + return; } - GNUNET_JSON_parse_free (spec); + ogr.hr.http_status = 0; + ogr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; break; } case MHD_HTTP_UNAUTHORIZED: - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); + ogr.hr.ec = TALER_JSON_get_error_code (json); + ogr.hr.hint = TALER_JSON_get_error_hint (json); /* Nothing really to verify, merchant says we need to authenticate. */ break; case MHD_HTTP_NOT_FOUND: - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); + ogr.hr.ec = TALER_JSON_get_error_code (json); + ogr.hr.hint = TALER_JSON_get_error_hint (json); break; default: /* unexpected response code */ - hr.ec = TALER_JSON_get_error_code (json); - hr.hint = TALER_JSON_get_error_hint (json); + ogr.hr.ec = TALER_JSON_get_error_code (json); + ogr.hr.hint = TALER_JSON_get_error_hint (json); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u/%d\n", (unsigned int) response_code, - (int) hr.ec); + (int) ogr.hr.ec); break; } ogh->cb (ogh->cb_cls, - &hr, - 0, - NULL); + &ogr); TALER_MERCHANT_orders_get_cancel (ogh); } @@ -255,12 +249,51 @@ TALER_MERCHANT_orders_get2 ( TALER_MERCHANT_OrdersGetCallback cb, void *cb_cls) { + return TALER_MERCHANT_orders_get3 ( + ctx, + backend_url, + paid, + refunded, + wired, + NULL, + NULL, + date, + start_row, + delta, + timeout, + cb, + cb_cls); +} + + +struct TALER_MERCHANT_OrdersGetHandle * +TALER_MERCHANT_orders_get3 ( + struct GNUNET_CURL_Context *ctx, + const char *backend_url, + enum TALER_EXCHANGE_YesNoAll paid, + enum TALER_EXCHANGE_YesNoAll refunded, + enum TALER_EXCHANGE_YesNoAll wired, + const char *session_id, + const char *fulfillment_url, + struct GNUNET_TIME_Timestamp date, + uint64_t start_row, + int64_t delta, + struct GNUNET_TIME_Relative timeout, + TALER_MERCHANT_OrdersGetCallback cb, + void *cb_cls) +{ struct TALER_MERCHANT_OrdersGetHandle *ogh; CURL *eh; - unsigned int timeout_ms = timeout.rel_value_us - / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us; + unsigned int tms = timeout.rel_value_us + / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us; GNUNET_assert (NULL != backend_url); + if ( (delta > MAX_ORDERS) || + (delta < -MAX_ORDERS) ) + { + GNUNET_break (0); + return NULL; + } if (0 == delta) { GNUNET_break (0); @@ -274,6 +307,8 @@ TALER_MERCHANT_orders_get2 ( /* build ogh->url with the various optional arguments */ { char *dstr; + char *fec = NULL; + char *sid = NULL; bool have_date; bool have_srow; char cbuf[30]; @@ -282,8 +317,8 @@ TALER_MERCHANT_orders_get2 ( GNUNET_snprintf (tbuf, sizeof (tbuf), - "%llu", - (unsigned long long) timeout_ms); + "%u", + tms); GNUNET_snprintf (dbuf, sizeof (dbuf), "%lld", @@ -292,6 +327,14 @@ TALER_MERCHANT_orders_get2 ( sizeof (cbuf), "%llu", (unsigned long long) start_row); + if (NULL != session_id) + (void) GNUNET_STRINGS_urlencode (strlen (session_id), + session_id, + &sid); + if (NULL != fulfillment_url) + (void) GNUNET_STRINGS_urlencode (strlen (fulfillment_url), + fulfillment_url, + &fec); dstr = GNUNET_strdup (GNUNET_TIME_timestamp2s (date)); if (delta > 0) { @@ -330,11 +373,17 @@ TALER_MERCHANT_orders_get2 ( ? dbuf : NULL, "timeout_ms", - (0 != timeout_ms) + (0 != tms) ? tbuf : NULL, + "session_id", + sid, + "fulfillment_url", + fec, NULL); GNUNET_free (dstr); + GNUNET_free (sid); + GNUNET_free (fec); } if (NULL == ogh->url) { @@ -347,6 +396,20 @@ TALER_MERCHANT_orders_get2 ( "Requesting URL '%s'\n", ogh->url); eh = TALER_MERCHANT_curl_easy_get_ (ogh->url); + if (NULL == eh) + { + GNUNET_break (0); + GNUNET_free (ogh->url); + GNUNET_free (ogh); + return NULL; + } + if (0 != tms) + { + GNUNET_break (CURLE_OK == + curl_easy_setopt (eh, + CURLOPT_TIMEOUT_MS, + (long) (tms + 100L))); + } ogh->job = GNUNET_CURL_job_add (ctx, eh, &handle_get_orders_finished, |