diff options
-rw-r--r-- | src/backend/taler-merchant-httpd.c | 7 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd.h | 16 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_post-orders-ID-pay.c | 33 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_private-get-orders-ID.c | 28 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_private-get-orders.c | 82 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_private-get-orders.h | 13 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_private-post-orders-ID-refund.c | 34 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_private-post-transfers.c | 11 | ||||
-rw-r--r-- | src/backenddb/plugin_merchantdb_postgres.c | 52 | ||||
-rw-r--r-- | src/include/taler_merchantdb_plugin.h | 19 | ||||
-rw-r--r-- | src/lib/merchant_api_get_orders.c | 2 |
11 files changed, 219 insertions, 78 deletions
diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c index 4fdd9f6d..488e45b9 100644 --- a/src/backend/taler-merchant-httpd.c +++ b/src/backend/taler-merchant-httpd.c @@ -170,6 +170,7 @@ TMH_instance_decref (struct TMH_MerchantInstance *mi) GNUNET_CONTAINER_multihashmap_remove (TMH_by_id_map, &h_instance, mi)); + TMH_force_get_orders_resume (mi); while (NULL != (wm = (mi->wm_head))) { GNUNET_CONTAINER_DLL_remove (mi->wm_head, @@ -437,15 +438,11 @@ do_shutdown (void *cls) struct TMH_SuspendedConnection *sc; (void) cls; - TMH_force_get_orders_resume (); TMH_force_ac_resume (); TMH_force_pc_resume (); + TMH_force_rc_resume (); TMH_force_post_transfers_resume (); -#if 0 - TMH_force_trh_resume (); - TMH_force_refund_resume (); TMH_force_tip_pickup_resume (); -#endif if (NULL != mhd_task) { GNUNET_SCHEDULER_cancel (mhd_task); diff --git a/src/backend/taler-merchant-httpd.h b/src/backend/taler-merchant-httpd.h index 42d86d3f..f4c1b64b 100644 --- a/src/backend/taler-merchant-httpd.h +++ b/src/backend/taler-merchant-httpd.h @@ -79,6 +79,12 @@ struct TMH_WireMethod /** + * A pending GET /orders request that is in long polling mode. + */ +struct TMH_PendingOrder; + + +/** * Information that defines a merchant "instance". That way, a single * backend can account for several merchants, as used to do in donation * shops @@ -97,6 +103,16 @@ struct TMH_MerchantInstance struct TMH_WireMethod *wm_tail; /** + * Head of DLL of long-polling GET /orders requests of this instance. + */ + struct TMH_PendingOrder *po_head; + + /** + * Tail of DLL of long-polling GET /orders requests of this instance. + */ + struct TMH_PendingOrder *po_tail; + + /** * Merchant's private key. */ struct TALER_MerchantPrivateKeyP merchant_priv; diff --git a/src/backend/taler-merchant-httpd_post-orders-ID-pay.c b/src/backend/taler-merchant-httpd_post-orders-ID-pay.c index 405a48e0..15f57c47 100644 --- a/src/backend/taler-merchant-httpd_post-orders-ID-pay.c +++ b/src/backend/taler-merchant-httpd_post-orders-ID-pay.c @@ -31,6 +31,7 @@ #include "taler-merchant-httpd_auditors.h" #include "taler-merchant-httpd_exchanges.h" #include "taler-merchant-httpd_post-orders-ID-pay.h" +#include "taler-merchant-httpd_private-get-orders.h" /** @@ -204,6 +205,11 @@ struct PayContext char *order_id; /** + * Serial number of this order in the database (set once we did the lookup). + */ + uint64_t order_serial; + + /** * Hashed proposal. */ struct GNUNET_HashCode h_contract_terms; @@ -340,9 +346,9 @@ struct PayContext int suspended; /** - * #GNUNET_YES if we already tried a forced /keys download. + * true if we already tried a forced /keys download. */ - int tried_force_keys; + bool tried_force_keys; }; @@ -772,7 +778,7 @@ process_pay_with_exchange (void *cls, { /* let's try *forcing* a re-download of /keys from the exchange. Maybe the wallet has seen /keys that we missed. */ - pc->tried_force_keys = GNUNET_YES; + pc->tried_force_keys = true; pc->fo = TMH_EXCHANGES_find_exchange (pc->current_exchange, pc->wm->wire_method, GNUNET_YES, @@ -1257,6 +1263,7 @@ begin_transaction (struct PayContext *pc) enum GNUNET_DB_QueryStatus qs; struct TMH_HandlerContext *hc = pc->hc; const char *instance_id = hc->instance->settings.id; + bool refunded; /* Avoid re-trying transactions on soft errors forever! */ if (pc->retry_counter++ > MAX_RETRIES) @@ -1345,6 +1352,7 @@ begin_transaction (struct PayContext *pc) "Merchant database error checking for refunds"); return; } + refunded = (qs > 0); /* Check if there are coins that still need to be processed */ @@ -1415,6 +1423,13 @@ begin_transaction (struct PayContext *pc) TMH_long_poll_resume (pc->order_id, hc->instance, NULL); + TMH_notify_order_change (hc->instance, + pc->order_id, + true, /* paid */ + refunded, + false, /* wired */ + pc->timestamp, + pc->order_serial); /* Generate response (payment successful) */ { @@ -1593,13 +1608,12 @@ parse_pay (struct MHD_Connection *connection, { enum GNUNET_DB_QueryStatus qs; json_t *contract_terms = NULL; - uint64_t order_serial; qs = TMH_db->lookup_contract_terms (TMH_db->cls, hc->instance->settings.id, pc->order_id, &contract_terms, - &order_serial); + &pc->order_serial); if (0 > qs) { /* single, read-only SQL statements should never cause @@ -1687,12 +1701,9 @@ parse_pay (struct MHD_Connection *connection, }; enum GNUNET_GenericReturnValue res; - /* FIXME: this is a tad wrong, as IF the contract is - malformed, the routine generates an error that blames - it on the client (400) instead of on us! */ - res = TALER_MHD_parse_json_data (connection, - contract_terms, - espec); + res = TALER_MHD_parse_internal_json_data (connection, + contract_terms, + espec); json_decref (contract_terms); if (GNUNET_YES != res) { diff --git a/src/backend/taler-merchant-httpd_private-get-orders-ID.c b/src/backend/taler-merchant-httpd_private-get-orders-ID.c index d413f71b..e983273a 100644 --- a/src/backend/taler-merchant-httpd_private-get-orders-ID.c +++ b/src/backend/taler-merchant-httpd_private-get-orders-ID.c @@ -25,6 +25,8 @@ #include <taler/taler_json_lib.h> #include "taler-merchant-httpd_mhd.h" #include "taler-merchant-httpd_exchanges.h" +#include "taler-merchant-httpd_private-get-orders.h" + /** * How long do we wait on the exchange? @@ -1084,11 +1086,37 @@ TMH_private_get_orders_ID (const struct TMH_RequestHandler *rh, TALER_amount_cmp (&expect_total, &gorc->deposits_total)) { + struct GNUNET_TIME_Absolute timestamp; + /* expect_total <= gorc->deposits_total: good: we got paid */ wired = true; qs = TMH_db->mark_order_wired (TMH_db->cls, gorc->order_serial); GNUNET_break (qs >= 0); /* just warn if transaction failed */ + { + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_absolute_time ("timestamp", + ×tamp), + GNUNET_JSON_spec_end () + }; + enum GNUNET_GenericReturnValue res; + + res = TALER_MHD_parse_internal_json_data (connection, + gorc->contract_terms, + spec); + if (GNUNET_YES != res) + { + GNUNET_break (0); + return res; + } + } + TMH_notify_order_change (hc->instance, + hc->infix, + true, /* paid */ + false, /* technically unknown, but OK here */ + true, /* wired */ + timestamp, + gorc->order_serial); } } diff --git a/src/backend/taler-merchant-httpd_private-get-orders.c b/src/backend/taler-merchant-httpd_private-get-orders.c index d2f502f9..05d518f5 100644 --- a/src/backend/taler-merchant-httpd_private-get-orders.c +++ b/src/backend/taler-merchant-httpd_private-get-orders.c @@ -25,18 +25,18 @@ /** * A pending GET /orders request that is in long polling mode. */ -struct PendingOrder +struct TMH_PendingOrder { /** * Kept in a DLL. */ - struct PendingOrder *prev; + struct TMH_PendingOrder *prev; /** * Kept in a DLL. */ - struct PendingOrder *next; + struct TMH_PendingOrder *next; /** * Which connection was suspended. @@ -49,9 +49,10 @@ struct PendingOrder struct GNUNET_CONTAINER_HeapNode *hn; /** - * Which instance is this client polling? + * Which instance is this client polling? This also defines + * which DLL this struct is part of. */ - char *instance_id; + struct TMH_MerchantInstance *mi; /** * At what time does this request expire? If set in the future, we @@ -61,7 +62,7 @@ struct PendingOrder /** * Array where we append matching orders. Must be - * json_decref()'ed when done with the `struct PendingOrder`! + * json_decref()'ed when done with the `struct TMH_PendingOrder`! */ json_t *pa; @@ -73,16 +74,6 @@ struct PendingOrder /** - * Head of DLL of long-polling GET /orders requests. - */ -static struct PendingOrder *po_head; - -/** - * Tail of DLL of long-polling GET /orders requests. - */ -static struct PendingOrder *po_tail; - -/** * Task to timeout pending orders. */ static struct GNUNET_SCHEDULER_Task *order_timeout_task; @@ -94,23 +85,25 @@ static struct GNUNET_CONTAINER_Heap *order_timeout_heap; /** - * We are shutting down, force resume of all GET /orders requests. + * We are shutting down (or an instance is being deleted), force resume of all + * GET /orders requests. + * + * @param mi instance to force resuming for */ void -TMH_force_get_orders_resume () +TMH_force_get_orders_resume (struct TMH_MerchantInstance *mi) { - struct PendingOrder *po; + struct TMH_PendingOrder *po; - while (NULL != (po = po_head)) + while (NULL != (po = mi->po_head)) { - GNUNET_CONTAINER_DLL_remove (po_head, - po_tail, + GNUNET_CONTAINER_DLL_remove (mi->po_head, + mi->po_tail, po); GNUNET_assert (po == GNUNET_CONTAINER_heap_remove_root (order_timeout_heap)); MHD_resume_connection (po->con); json_decref (po->pa); - GNUNET_free (po->instance_id); GNUNET_free (po); } if (NULL != order_timeout_task) @@ -134,7 +127,8 @@ TMH_force_get_orders_resume () static void order_timeout (void *cls) { - struct PendingOrder *po; + struct TMH_PendingOrder *po; + struct TMH_MerchantInstance *mi; (void) cls; order_timeout_task = NULL; @@ -157,13 +151,13 @@ order_timeout (void *cls) po->hn = NULL; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Resuming long polled job due to timeout\n"); - GNUNET_CONTAINER_DLL_remove (po_head, - po_tail, + mi = po->mi; + GNUNET_CONTAINER_DLL_remove (mi->po_head, + mi->po_tail, po); json_decref (po->pa); MHD_resume_connection (po->con); TMH_trigger_daemon (); /* we resumed, kick MHD */ - GNUNET_free (po->instance_id); GNUNET_free (po); } order_timeout_task = GNUNET_SCHEDULER_add_at (po->long_poll_timeout, @@ -221,21 +215,16 @@ add_order (void *cls, * There has been a change or addition of a new @a order_id. Wake up * long-polling clients that may have been waiting for this event. * - * FIXME: Here we go over all long polling clients. We should consider moving - * the global DLL into the *instance* data structure (note: that has then - * implications in case an instance is deleted, i.e. we would then need to - * trigger all the long pollers!). - * - * @param instance_id the instance where the order changed + * @param mi the instance where the order changed * @param order_id the order that changed * @param paid is the order paid by the customer? * @param refunded was the order refunded? * @param wire was the merchant paid via wire transfer? - * @param data execution date of the order + * @param date execution date of the order * @param order_serial_id serial ID of the order in the database */ void -TMH_notify_order_change (const char *instance_id, +TMH_notify_order_change (struct TMH_MerchantInstance *mi, const char *order_id, bool paid, bool refunded, @@ -243,9 +232,9 @@ TMH_notify_order_change (const char *instance_id, struct GNUNET_TIME_Absolute date, uint64_t order_serial_id) { - struct PendingOrder *pn; + struct TMH_PendingOrder *pn; - for (struct PendingOrder *po = po_head; + for (struct TMH_PendingOrder *po = mi->po_head; NULL != po; po = pn) { @@ -257,9 +246,6 @@ TMH_notify_order_change (const char *instance_id, ( ((TALER_EXCHANGE_YNA_YES == po->of.wired) == wired) || (TALER_EXCHANGE_YNA_ALL == po->of.wired) ) ) ) continue; - if (0 != strcmp (instance_id, - po->instance_id)) - continue; if (po->of.delta > 0) { if (order_serial_id < po->of.start_row) @@ -280,15 +266,14 @@ TMH_notify_order_change (const char *instance_id, order_id, order_serial_id, date); - GNUNET_CONTAINER_DLL_remove (po_head, - po_tail, + GNUNET_CONTAINER_DLL_remove (mi->po_head, + mi->po_tail, po); GNUNET_assert (po == GNUNET_CONTAINER_heap_remove_node (po->hn)); MHD_resume_connection (po->con); TMH_trigger_daemon (); /* we resumed, kick MHD */ json_decref (po->pa); - GNUNET_free (po->instance_id); GNUNET_free (po); } } @@ -471,7 +456,8 @@ TMH_private_get_orders (const struct TMH_RequestHandler *rh, if ( (0 == qs) && (of.timeout.rel_value_us > 0) ) { - struct PendingOrder *po; + struct TMH_MerchantInstance *mi = hc->instance; + struct TMH_PendingOrder *po; /* setup timeout heap (if not yet exists) */ if (NULL == order_timeout_heap) @@ -479,8 +465,8 @@ TMH_private_get_orders (const struct TMH_RequestHandler *rh, = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); hc->ctx = pa; hc->cc = &json_cleanup; - po = GNUNET_new (struct PendingOrder); - po->instance_id = GNUNET_strdup (hc->instance->settings.id); + po = GNUNET_new (struct TMH_PendingOrder); + po->mi = mi; po->con = connection; po->pa = json_incref (pa); po->hn = GNUNET_CONTAINER_heap_insert (order_timeout_heap, @@ -488,8 +474,8 @@ TMH_private_get_orders (const struct TMH_RequestHandler *rh, po->long_poll_timeout.abs_value_us); po->long_poll_timeout = GNUNET_TIME_relative_to_absolute (of.timeout); po->of = of; - GNUNET_CONTAINER_DLL_insert (po_head, - po_tail, + GNUNET_CONTAINER_DLL_insert (mi->po_head, + mi->po_tail, po); MHD_suspend_connection (connection); /* start timeout task */ diff --git a/src/backend/taler-merchant-httpd_private-get-orders.h b/src/backend/taler-merchant-httpd_private-get-orders.h index 7bb63243..c6f6fbb8 100644 --- a/src/backend/taler-merchant-httpd_private-get-orders.h +++ b/src/backend/taler-merchant-httpd_private-get-orders.h @@ -42,16 +42,16 @@ TMH_private_get_orders (const struct TMH_RequestHandler *rh, * There has been a change or addition of a new @a order_id. Wake up * long-polling clients that may have been waiting for this event. * - * @param instance_id the instance where the order changed + * @param mi the instance where the order changed * @param order_id the order that changed * @param paid is the order paid by the customer? * @param refunded was the order refunded? * @param wire was the merchant paid via wire transfer? - * @param data execution date of the order + * @param date execution date of the order * @param order_serial_id serial ID of the order in the database */ void -TMH_notify_order_change (const char *instance_id, +TMH_notify_order_change (struct TMH_MerchantInstance *mi, const char *order_id, bool paid, bool refunded, @@ -61,10 +61,13 @@ TMH_notify_order_change (const char *instance_id, /** - * We are shutting down, force resume of all GET /orders requests. + * We are shutting down (or an instance is being deleted), force resume of all + * GET /orders requests. + * + * @param mi instance to force resuming for */ void -TMH_force_get_orders_resume (void); +TMH_force_get_orders_resume (struct TMH_MerchantInstance *mi); /* end of taler-merchant-httpd_private-get-orders.h */ diff --git a/src/backend/taler-merchant-httpd_private-post-orders-ID-refund.c b/src/backend/taler-merchant-httpd_private-post-orders-ID-refund.c index 70bce7ff..6db0497a 100644 --- a/src/backend/taler-merchant-httpd_private-post-orders-ID-refund.c +++ b/src/backend/taler-merchant-httpd_private-post-orders-ID-refund.c @@ -24,6 +24,8 @@ #include <taler/taler_signatures.h> #include <taler/taler_json_lib.h> #include "taler-merchant-httpd_private-post-orders-ID-refund.h" +#include "taler-merchant-httpd_private-get-orders.h" + /** * How often do we retry the non-trivial refund INSERT database @@ -136,7 +138,10 @@ TMH_private_post_orders_ID_refund (const struct TMH_RequestHandler *rh, "increase refund")) { GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_REFUND_STORE_DB_ERROR, + "Could not begin DB transaction"); } rs = TMH_db->increase_refund (TMH_db->cls, hc->instance->settings.id, @@ -200,7 +205,32 @@ TMH_private_post_orders_ID_refund (const struct TMH_RequestHandler *rh, TMH_long_poll_resume (hc->infix, hc->instance, &refund); - + { + struct GNUNET_TIME_Absolute timestamp; + uint64_t order_serial; + enum GNUNET_DB_QueryStatus qs; + + qs = TMH_db->lookup_order_summary (TMH_db->cls, + hc->instance->settings.id, + hc->infix, + ×tamp, + &order_serial); + if (0 >= qs) + { + GNUNET_break (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_REFUND_DB_INCONSISTENT, + "Database inconsistent, could not trigger notifications"); + } + TMH_notify_order_change (hc->instance, + hc->infix, + true, /* paid */ + true, /* refunded */ + false, /* wired, cannot be if we could still do refunds */ + timestamp, + order_serial); + } { MHD_RESULT ret; char *taler_refund_uri; diff --git a/src/backend/taler-merchant-httpd_private-post-transfers.c b/src/backend/taler-merchant-httpd_private-post-transfers.c index 23bb08e7..042825be 100644 --- a/src/backend/taler-merchant-httpd_private-post-transfers.c +++ b/src/backend/taler-merchant-httpd_private-post-transfers.c @@ -322,9 +322,9 @@ check_transfer (void *cls, GNUNET_JSON_from_data_auto (&ttd->coin_pub), "h_wire", GNUNET_JSON_from_data_auto (h_wire), - "exchange_sig", + "deposit_exchange_sig", GNUNET_JSON_from_data_auto (exchange_sig), - "exchange_pub", + "deposit_exchange_pub", GNUNET_JSON_from_data_auto (exchange_pub), /* first block of 5 */ "h_contract_terms", @@ -399,15 +399,12 @@ check_wire_fee (struct PostTransfersContext *ptc, return GNUNET_OK; /* expected_fee >= wire_fee */ } /* Wire fee check failed, export proof to client */ - /* FIXME: This is not actually the *full* proof, as we are - not including the exchange's bogus response with the - signature claiming a different wire fee. Also, this - error is not described in the API docs! */ ptc->response_code = MHD_HTTP_ACCEPTED; ptc->response = TALER_MHD_make_json_pack ( - "{s:I, s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o}", + "{s:I, s:s, s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o}", "code", (json_int_t) TALER_EC_POST_TRANSFERS_JSON_BAD_WIRE_FEE, + "hint", "exchange provided conflicting wire fee information", "wire_fee", TALER_JSON_from_amount (wire_fee), "execution_time", GNUNET_JSON_from_time_abs (execution_time), "expected_wire_fee", TALER_JSON_from_amount (&expected_fee), diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c index 831c676a..8e466b70 100644 --- a/src/backenddb/plugin_merchantdb_postgres.c +++ b/src/backenddb/plugin_merchantdb_postgres.c @@ -1116,6 +1116,45 @@ postgres_lookup_order (void *cls, /** + * Retrieve order summary given its @a order_id and the @a instance_id. + * + * @param cls closure + * @param instance_id instance to obtain order of + * @param order_id order id used to perform the lookup + * @param[out] timestamp when was the order created + * @param[out] order_serial under which serial do we keep this order + * @return transaction status + */ +static enum GNUNET_DB_QueryStatus +postgres_lookup_order_summary (void *cls, + const char *instance_id, + const char *order_id, + struct GNUNET_TIME_Absolute *timestamp, + uint64_t *order_serial) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (instance_id), + GNUNET_PQ_query_param_string (order_id), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("order_serial", + order_serial), + GNUNET_PQ_result_spec_absolute_time ("creation_time", + timestamp), + GNUNET_PQ_result_spec_end + }; + + check_connection (pg); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "lookup_order_summary", + params, + rs); +} + + +/** * Context used for postgres_lookup_orders(). */ struct LookupOrdersContext @@ -6052,6 +6091,18 @@ libtaler_plugin_merchantdb_postgres_init (void *cls) " WHERE merchant_id=$1)" " AND merchant_orders.order_id=$2", 2), + /* for postgres_lookup_order_summary() */ + GNUNET_PQ_make_prepare ("lookup_order_summary", + "SELECT" + " creation_time" + ",order_serial" + " FROM merchant_orders" + " WHERE merchant_orders.merchant_serial=" + " (SELECT merchant_serial " + " FROM merchant_instances" + " WHERE merchant_id=$1)" + " AND merchant_orders.order_id=$2", + 2), /* for postgres_lookup_orders() */ GNUNET_PQ_make_prepare ("lookup_orders_inc", "(SELECT" @@ -8157,6 +8208,7 @@ libtaler_plugin_merchantdb_postgres_init (void *cls) plugin->lock_product = &postgres_lock_product; plugin->delete_order = &postgres_delete_order; plugin->lookup_order = &postgres_lookup_order; + plugin->lookup_order_summary = &postgres_lookup_order_summary; plugin->lookup_orders = &postgres_lookup_orders; plugin->insert_order = &postgres_insert_order; plugin->unlock_inventory = &postgres_unlock_inventory; diff --git a/src/include/taler_merchantdb_plugin.h b/src/include/taler_merchantdb_plugin.h index abd1ef03..bcc1ae8d 100644 --- a/src/include/taler_merchantdb_plugin.h +++ b/src/include/taler_merchantdb_plugin.h @@ -942,6 +942,25 @@ struct TALER_MERCHANTDB_Plugin const char *order_id, json_t **contract_terms); + + /** + * Retrieve order summary given its @a order_id and the @a instance_id. + * + * @param cls closure + * @param instance_id instance to obtain order of + * @param order_id order id used to perform the lookup + * @param[out] timestamp when was the order created + * @param[out] order_serial under which serial do we keep this order + * @return transaction status + */ + enum GNUNET_DB_QueryStatus + (*lookup_order_summary)(void *cls, + const char *instance_id, + const char *order_id, + struct GNUNET_TIME_Absolute *timestamp, + uint64_t *order_serial); + + /** * Retrieve orders given the @a instance_id. * diff --git a/src/lib/merchant_api_get_orders.c b/src/lib/merchant_api_get_orders.c index 9d1ac3e7..92d31428 100644 --- a/src/lib/merchant_api_get_orders.c +++ b/src/lib/merchant_api_get_orders.c @@ -86,6 +86,8 @@ parse_orders (const json_t *ia, struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_string ("order_id", &ie->order_id), + // FIXME: also parse and return row_id and timestamp fields! + // (=> needed to enable client to filter by those!) GNUNET_JSON_spec_end () }; |