summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/taler-merchant-httpd.c7
-rw-r--r--src/backend/taler-merchant-httpd.h16
-rw-r--r--src/backend/taler-merchant-httpd_post-orders-ID-pay.c33
-rw-r--r--src/backend/taler-merchant-httpd_private-get-orders-ID.c28
-rw-r--r--src/backend/taler-merchant-httpd_private-get-orders.c82
-rw-r--r--src/backend/taler-merchant-httpd_private-get-orders.h13
-rw-r--r--src/backend/taler-merchant-httpd_private-post-orders-ID-refund.c34
-rw-r--r--src/backend/taler-merchant-httpd_private-post-transfers.c11
-rw-r--r--src/backenddb/plugin_merchantdb_postgres.c52
-rw-r--r--src/include/taler_merchantdb_plugin.h19
-rw-r--r--src/lib/merchant_api_get_orders.c2
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",
+ &timestamp),
+ 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,
+ &timestamp,
+ &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 ()
};