diff options
author | Christian Grothoff <christian@grothoff.org> | 2020-05-10 20:06:36 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2020-05-10 20:06:36 +0200 |
commit | a5da6d3cec3b090c5aa21255eed37fc7a3ca48ec (patch) | |
tree | 0f2a93abc26c9d53690864a47250035dbb167a14 /src | |
parent | 47811a60b692e575274305d4cac429220d27a328 (diff) | |
download | merchant-a5da6d3cec3b090c5aa21255eed37fc7a3ca48ec.tar.gz merchant-a5da6d3cec3b090c5aa21255eed37fc7a3ca48ec.tar.bz2 merchant-a5da6d3cec3b090c5aa21255eed37fc7a3ca48ec.zip |
GET /transfers implementation
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/Makefile.am | 2 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd.c | 7 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_private-get-instances-ID.c | 4 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_private-get-transfers.c | 47 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_private-get-transfers.h | 25 | ||||
-rw-r--r-- | src/backenddb/plugin_merchantdb_postgres.c | 548 | ||||
-rw-r--r-- | src/include/taler_merchantdb_plugin.h | 106 |
7 files changed, 531 insertions, 208 deletions
diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am index 2512143d..3127ab24 100644 --- a/src/backend/Makefile.am +++ b/src/backend/Makefile.am @@ -41,6 +41,8 @@ taler_merchant_httpd_SOURCES = \ taler-merchant-httpd_private-get-products-ID.h \ taler-merchant-httpd_private-get-orders.c \ taler-merchant-httpd_private-get-orders.h \ + taler-merchant-httpd_private-get-transfers.c \ + taler-merchant-httpd_private-get-transfers.h \ taler-merchant-httpd_private-patch-instances-ID.c \ taler-merchant-httpd_private-patch-instances-ID.h \ taler-merchant-httpd_private-patch-products-ID.c \ diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c index c5dbacd2..e3640112 100644 --- a/src/backend/taler-merchant-httpd.c +++ b/src/backend/taler-merchant-httpd.c @@ -38,6 +38,7 @@ #include "taler-merchant-httpd_private-get-products-ID.h" #include "taler-merchant-httpd_private-get-orders.h" // #include "taler-merchant-httpd_private-get-orders-ID.h" +#include "taler-merchant-httpd_private-get-transfers.h" #include "taler-merchant-httpd_private-patch-instances-ID.h" #include "taler-merchant-httpd_private-patch-products-ID.h" #include "taler-merchant-httpd_private-post-instances.h" @@ -838,6 +839,12 @@ url_handler (void *cls, .method = MHD_HTTP_METHOD_POST, .handler = &TMH_private_post_transfers }, + /* GET /transfers: */ + { + .url_prefix = "/transfers", + .method = MHD_HTTP_METHOD_GET, + .handler = &TMH_private_get_transfers + }, { NULL } diff --git a/src/backend/taler-merchant-httpd_private-get-instances-ID.c b/src/backend/taler-merchant-httpd_private-get-instances-ID.c index b6993791..bf248b15 100644 --- a/src/backend/taler-merchant-httpd_private-get-instances-ID.c +++ b/src/backend/taler-merchant-httpd_private-get-instances-ID.c @@ -51,7 +51,7 @@ TMH_private_get_instances_ID (const struct TMH_RequestHandler *rh, json_array_append_new ( ja, json_pack ( - "{s:O, s:o, s:O, s:o}", + "{s:O, s:o, s:O, s:b}", "payto_uri", json_object_get (wm->j_wire, "payto_uri"), @@ -61,7 +61,7 @@ TMH_private_get_instances_ID (const struct TMH_RequestHandler *rh, json_object_get (wm->j_wire, "salt"), "active", - (wm->active) ? json_true () : json_false ()))); + (wm->active) ? 1 : 0))); } return TALER_MHD_reply_json_pack ( diff --git a/src/backend/taler-merchant-httpd_private-get-transfers.c b/src/backend/taler-merchant-httpd_private-get-transfers.c index 23163129..0bf53f3d 100644 --- a/src/backend/taler-merchant-httpd_private-get-transfers.c +++ b/src/backend/taler-merchant-httpd_private-get-transfers.c @@ -21,13 +21,8 @@ */ #include "platform.h" #include <jansson.h> -#include <taler/taler_signatures.h> #include <taler/taler_json_lib.h> -#include "taler-merchant-httpd.h" -#include "taler-merchant-httpd_mhd.h" -#include "taler-merchant-httpd_auditors.h" -#include "taler-merchant-httpd_exchanges.h" -#include "taler-merchant-httpd_track-transfer.h" +#include "taler-merchant-httpd_private-get-transfers.h" /** @@ -54,11 +49,31 @@ transfer_cb (void *cls, const char *exchange_url, uint64_t transfer_serial_id, struct GNUNET_TIME_Absolute execution_time, - enum TALER_MERCHANTDB_YesNoAll verified) + bool verified, + bool confirmed) { json_t *ja = cls; - - + json_t *r; + + r = json_pack ("{s:o, s:o, s:s, s:s, s:I, s:b, s:b}", + "credit_amount", TALER_JSON_from_amount (credit_amount), + "wtid", GNUNET_JSON_from_data_auto (wtid), + "payto_uri", payto_uri, + "exchange_url", exchange_url, + "transfer_serial_id", (json_int_t) transfer_serial_id, + "verified", verified ? 1 : 0, + "confirmed", confirmed ? 1 : 0); + GNUNET_assert (NULL != r); + if (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us != + execution_time.abs_value_us) + GNUNET_assert (0 == + json_object_set_new ( + r, + "execution_time", + GNUNET_JSON_from_time_abs (execution_time))); + GNUNET_assert (0 == + json_array_append_new (ja, + r)); } @@ -150,7 +165,7 @@ TMH_private_get_transfers (const struct TMH_RequestHandler *rh, unsigned long long o; if (1 != - sscanf (limit_s, + sscanf (offset_s, "%llu%1s", &o, dummy)) @@ -200,7 +215,7 @@ TMH_private_get_transfers (const struct TMH_RequestHandler *rh, "verified"); } - db->preflight (db->cls); + TMH_db->preflight (TMH_db->cls); { json_t *ja; enum GNUNET_DB_QueryStatus qs; @@ -225,13 +240,13 @@ TMH_private_get_transfers (const struct TMH_RequestHandler *rh, GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs); return TALER_MHD_reply_with_error (connection, MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GET_TRANSFERS_DB_FETCH_DEPOSIT_ERROR, + TALER_EC_GET_TRANSFERS_DB_FETCH_ERROR, "Fail to query database about transfers"); } - return MHD_MHD_reply_json_pack (connection, - MHD_HTTP_OK, - "{s:o}", - "transfers", ja); + return TALER_MHD_reply_json_pack (connection, + MHD_HTTP_OK, + "{s:o}", + "transfers", ja); } } diff --git a/src/backend/taler-merchant-httpd_private-get-transfers.h b/src/backend/taler-merchant-httpd_private-get-transfers.h index 0463295e..556e8558 100644 --- a/src/backend/taler-merchant-httpd_private-get-transfers.h +++ b/src/backend/taler-merchant-httpd_private-get-transfers.h @@ -14,36 +14,29 @@ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ /** - * @file backend/taler-merchant-httpd_track-transfer.h - * @brief headers for /track/transfer handler + * @file backend/taler-merchant-httpd_private-get-transfers.h + * @brief headers for GET /transfers handler * @author Christian Grothoff * @author Marcello Stanisci */ -#ifndef TALER_MERCHANT_HTTPD_TRACK_TRANSFER_H -#define TALER_MERCHANT_HTTPD_TRACK_TRANSFER_H +#ifndef TALER_MERCHANT_HTTPD_PRIVATE_GET_TRANSFERS_H +#define TALER_MERCHANT_HTTPD_PRIVATE_GET_TRANSFERS_H #include <microhttpd.h> #include "taler-merchant-httpd.h" + /** - * Manages a /track/transfer call, thus it calls the /wire/transfer - * offered by the exchange in order to return the set of transfers - * (of coins) associated with a given wire transfer + * Manages a GET /private/transfers call. * * @param rh context of the handler * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data - * @param mi merchant backend instance, never NULL + * @param[in,out] hc context with further information about the request * @return MHD result code */ MHD_RESULT -MH_handler_track_transfer (struct TMH_RequestHandler *rh, +TMH_private_get_transfers (const struct TMH_RequestHandler *rh, struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size, - struct MerchantInstance *mi); + struct TMH_HandlerContext *hc); #endif diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c index 8e402d31..8c1646a7 100644 --- a/src/backenddb/plugin_merchantdb_postgres.c +++ b/src/backenddb/plugin_merchantdb_postgres.c @@ -3457,6 +3457,219 @@ postgres_lookup_transfer_details ( } +/** + * Closure for #lookup_transfers_cb(). + */ +struct LookupTransfersContext +{ + /** + * Function to call on results. + */ + TALER_MERCHANTDB_TransferCallback cb; + + /** + * Closure for @e cb. + */ + void *cb_cls; + + /** + * Postgres context. + */ + struct PostgresClosure *pg; + + /** + * Transaction status (set). + */ + enum GNUNET_DB_QueryStatus qs; + + /** + * Filter to apply by verification status. + */ + enum TALER_MERCHANTDB_YesNoAll verified; +}; + + +/** + * Function to be called with the results of a SELECT statement + * that has returned @a num_results results. + * + * @param cls of type `struct LookupTransfersContext *` + * @param result the postgres result + * @param num_result the number of results in @a result + */ +static void +lookup_transfers_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupTransfersContext *ltc = cls; + struct PostgresClosure *pg = ltc->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + struct TALER_Amount credit_amount; + struct TALER_WireTransferIdentifierRawP wtid; + char *payto_uri; + char *exchange_url; + uint64_t transfer_serial_id; + struct GNUNET_TIME_Absolute execution_time; + enum TALER_MERCHANTDB_YesNoAll verified; + uint8_t verified8; + uint8_t confirmed8; + struct GNUNET_PQ_ResultSpec rs[] = { + TALER_PQ_RESULT_SPEC_AMOUNT ("credit_amount", + &credit_amount), + GNUNET_PQ_result_spec_auto_from_type ("wtid", + &wtid), + GNUNET_PQ_result_spec_string ("payto_uri", + &payto_uri), + GNUNET_PQ_result_spec_string ("exchange_url", + &exchange_url), + GNUNET_PQ_result_spec_uint64 ("credit_serial", + &transfer_serial_id), + GNUNET_PQ_result_spec_absolute_time ("execution_time", + &execution_time), + GNUNET_PQ_result_spec_auto_from_type ("verified", + &verified8), + GNUNET_PQ_result_spec_auto_from_type ("confirmed", + &confirmed8), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + ltc->qs = GNUNET_DB_STATUS_HARD_ERROR; + return; + } + if (0 == verified8) + verified = TALER_MERCHANTDB_YNA_NO; + else + verified = TALER_MERCHANTDB_YNA_YES; + if ( (ltc->verified == TALER_MERCHANTDB_YNA_ALL) || + (ltc->verified == verified) ) + { + ltc->qs = i + 1; + ltc->cb (ltc->cb_cls, + &credit_amount, + &wtid, + payto_uri, + exchange_url, + transfer_serial_id, + execution_time, + TALER_MERCHANTDB_YNA_YES == verified, + 0 != confirmed8); + } + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Lookup transfers. Note that filtering by @a verified status is done + * outside of SQL, as we already have 8 prepared statements and adding + * a filter on verified would further double the number of statements for + * a likely rather ineffective filter. So we apply that filter in + * #lookup_transfers_cb(). + * + * @param cls closure + * @param instance_id instance to lookup payments for + * @param payto_uri account that we are interested in transfers to + * @param before timestamp for the earliest transfer we care about + * @param after timestamp for the last transfer we care about + * @param limit number of entries to return, negative for descending in execution time, + * positive for ascending in execution time + * @param offset transfer_serial number of the transfer we want to offset from + * @param verified filter transfers by verification status + * @param cb function to call with detailed transfer data + * @param cb_cls closure for @a cb + * @return transaction status + */ +static enum GNUNET_DB_QueryStatus +postgres_lookup_transfers (void *cls, + const char *instance_id, + const char *payto_uri, + struct GNUNET_TIME_Absolute before, + struct GNUNET_TIME_Absolute after, + int64_t limit, + uint64_t offset, + enum TALER_MERCHANTDB_YesNoAll verified, + TALER_MERCHANTDB_TransferCallback cb, + void *cb_cls) +{ + struct PostgresClosure *pg = cls; + uint64_t plimit = (uint64_t) ((limit < 0) ? -limit : limit); + struct GNUNET_PQ_QueryParam params_payto_et[] = { + GNUNET_PQ_query_param_string (instance_id), + GNUNET_PQ_query_param_absolute_time (&before), + GNUNET_PQ_query_param_absolute_time (&after), + GNUNET_PQ_query_param_uint64 (&offset), + GNUNET_PQ_query_param_uint64 (&plimit), + GNUNET_PQ_query_param_string (payto_uri), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_QueryParam params_et[] = { + GNUNET_PQ_query_param_string (instance_id), + GNUNET_PQ_query_param_absolute_time (&before), + GNUNET_PQ_query_param_absolute_time (&after), + GNUNET_PQ_query_param_uint64 (&offset), + GNUNET_PQ_query_param_uint64 (&plimit), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_QueryParam params_payto[] = { + GNUNET_PQ_query_param_string (instance_id), + GNUNET_PQ_query_param_uint64 (&offset), + GNUNET_PQ_query_param_uint64 (&plimit), + GNUNET_PQ_query_param_string (payto_uri), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_QueryParam params_none[] = { + GNUNET_PQ_query_param_string (instance_id), + GNUNET_PQ_query_param_uint64 (&offset), + GNUNET_PQ_query_param_uint64 (&plimit), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_QueryParam *params; + struct LookupTransfersContext ltc = { + .cb = cb, + .cb_cls = cb_cls, + .pg = pg, + .verified = verified + }; + enum GNUNET_DB_QueryStatus qs; + char stmt[128]; + bool by_time; + + by_time = ( (before.abs_value_us != + GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) || + (after.abs_value_us != GNUNET_TIME_UNIT_ZERO_ABS.abs_value_us) ); + + check_connection (pg); + GNUNET_snprintf (stmt, + sizeof (stmt), + "lookup_transfers%s%s%s", + (by_time) ? "_time" : "", + (NULL != payto_uri) ? "_payto" : "", + (limit > 0) ? "_asc" : "_desc"); + params = (by_time) + ? ( (NULL != payto_uri) ? params_payto_et : params_et) + : ( (NULL != payto_uri) ? params_payto : params_none); + + // FIXME: write SQL (_desc-variant!) + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + stmt, + params, + &lookup_transfers_cb, + <c); + if (0 >= qs) + return qs; + return ltc.qs; +} + + /* ********************* OLD API ************************** */ /** @@ -3672,131 +3885,6 @@ postgres_get_authorized_tip_amount (void *cls, /** - * Closure for #find_transfers_cb(). - */ -struct FindTransfersContext -{ - /** - * Function to call on results. - */ - TALER_MERCHANTDB_TransferCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Hash of the contract we are looking under. - */ - const struct GNUNET_HashCode *h_contract_terms; - - /** - * Transaction status (set). - */ - enum GNUNET_DB_QueryStatus qs; -}; - - -/** - * Function to be called with the results of a SELECT statement - * that has returned @a num_results results. - * - * @param cls of type `struct FindTransfersContext *` - * @param result the postgres result - * @param num_result the number of results in @a result - */ -static void -find_transfers_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct FindTransfersContext *ftc = cls; - - for (unsigned int i = 0; i<num_results; i++) - { - struct TALER_CoinSpendPublicKeyP coin_pub; - struct TALER_WireTransferIdentifierRawP wtid; - struct GNUNET_TIME_Absolute execution_time; - json_t *proof; - - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("coin_pub", - &coin_pub), - GNUNET_PQ_result_spec_auto_from_type ("wtid", - &wtid), - GNUNET_PQ_result_spec_absolute_time ("execution_time", - &execution_time), - TALER_PQ_result_spec_json ("proof", - &proof), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - ftc->qs = GNUNET_DB_STATUS_HARD_ERROR; - return; - } - ftc->qs = i + 1; - ftc->cb (ftc->cb_cls, - ftc->h_contract_terms, - &coin_pub, - &wtid, - execution_time, - proof); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Lookup information about a transfer by @a h_contract_terms. Note - * that in theory there could be multiple wire transfers for a - * single @a h_contract_terms, as the transaction may have involved - * multiple coins and the coins may be spread over different wire - * transfers. - * - * @param cls closure - * @param h_contract_terms key for the search - * @param cb function to call with transfer data - * @param cb_cls closure for @a cb - * @return transaction status - */ -static enum GNUNET_DB_QueryStatus -postgres_find_transfers_by_hash (void *cls, - const struct GNUNET_HashCode *h_contract_terms, - TALER_MERCHANTDB_TransferCallback cb, - void *cb_cls) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_contract_terms), - GNUNET_PQ_query_param_end - }; - struct FindTransfersContext ftc = { - .h_contract_terms = h_contract_terms, - .cb = cb, - .cb_cls = cb_cls - }; - enum GNUNET_DB_QueryStatus qs; - - check_connection (pg); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "find_transfers_by_hash", - params, - &find_transfers_cb, - &ftc); - if (0 >= qs) - return qs; - return ftc.qs; -} - - -/** * Store information about wire fees charged by an exchange, * including signature (so we have proof). * @@ -6007,6 +6095,214 @@ libtaler_plugin_merchantdb_postgres_init (void *cls) " WHERE merchant_transfers.wtid=$2" " AND merchant_transfers.exchange_url=$1", 2), + /* for postgres_lookup_transfers() */ + GNUNET_PQ_make_prepare ("lookup_transfers_time_payto_asc", + "SELECT" + " credit_amount_val" + ",credit_amount_frac" + ",wtid" + ",merchant_accounts.payto_uri" + ",exchange_url" + ",credit_serial" + ",merchant_transfer_signatures.execution_time" + ",verified" + ",confirmed" + " FROM merchant_transfers" + " JOIN merchant_accounts USING (account_serial)" + " JOIN merchant_transfer_signatures USING (credit_serial)" + " WHERE execution_time < $2" + " AND execution_time >= $3" + " AND credit_serial > $4" + " AND payto_uri = $6" + " AND merchant_serial =" + " (SELECT merchant_serial" + " FROM merchant_instances" + " WHERE merchant_id=$1)" + " ORDER BY credit_serial ASC" + " LIMIT $5", + 6), + /* for postgres_lookup_transfers() */ + GNUNET_PQ_make_prepare ("lookup_transfers_time_asc", + "SELECT" + " credit_amount_val" + ",credit_amount_frac" + ",wtid" + ",merchant_accounts.payto_uri" + ",exchange_url" + ",credit_serial" + ",merchant_transfer_signatures.execution_time" + ",verified" + ",confirmed" + " FROM merchant_transfers" + " JOIN merchant_accounts USING (account_serial)" + " JOIN merchant_transfer_signatures USING (credit_serial)" + " WHERE execution_time < $2" + " AND execution_time >= $3" + " AND credit_serial > $4" + " AND merchant_serial =" + " (SELECT merchant_serial" + " FROM merchant_instances" + " WHERE merchant_id=$1)" + " ORDER BY credit_serial ASC" + " LIMIT $5", + 5), + /* for postgres_lookup_transfers() */ + GNUNET_PQ_make_prepare ("lookup_transfers_payto_asc", + "SELECT" + " credit_amount_val" + ",credit_amount_frac" + ",wtid" + ",merchant_accounts.payto_uri" + ",exchange_url" + ",credit_serial" + ",CASE WHEN (merchant_transfer_signatures.execution_time) IS NULL" + " THEN 9223372036854775807" /* largest BIGINT possible */ + " ELSE merchant_transfer_signatures.execution_time" + " END AS execution_time" + ",verified" + ",confirmed" + " FROM merchant_transfers" + " JOIN merchant_accounts USING (account_serial)" + " LEFT JOIN merchant_transfer_signatures USING (credit_serial)" + " WHERE credit_serial > $2" + " AND payto_uri = $4" + " AND merchant_serial =" + " (SELECT merchant_serial" + " FROM merchant_instances" + " WHERE merchant_id=$1)" + " ORDER BY credit_serial ASC" + " LIMIT $3", + 4), + /* for postgres_lookup_transfers() */ + GNUNET_PQ_make_prepare ("lookup_transfers_asc", + "SELECT" + " credit_amount_val" + ",credit_amount_frac" + ",wtid" + ",merchant_accounts.payto_uri" + ",exchange_url" + ",credit_serial" + ",CASE WHEN (merchant_transfer_signatures.execution_time) IS NULL" + " THEN 9223372036854775807" /* largest BIGINT possible */ + " ELSE merchant_transfer_signatures.execution_time" + " END AS execution_time" + ",verified" + ",confirmed" + " FROM merchant_transfers" + " JOIN merchant_accounts USING (account_serial)" + " LEFT JOIN merchant_transfer_signatures USING (credit_serial)" + " WHERE credit_serial > $2" + " AND merchant_serial =" + " (SELECT merchant_serial" + " FROM merchant_instances" + " WHERE merchant_id=$1)" + " ORDER BY credit_serial ASC" + " LIMIT $3", + 3), + /* for postgres_lookup_transfers() */ + GNUNET_PQ_make_prepare ("lookup_transfers_time_payto_desc", + "SELECT" + " credit_amount_val" + ",credit_amount_frac" + ",wtid" + ",merchant_accounts.payto_uri" + ",exchange_url" + ",credit_serial" + ",merchant_transfer_signatures.execution_time" + ",verified" + ",confirmed" + " FROM merchant_transfers" + " JOIN merchant_accounts USING (account_serial)" + " JOIN merchant_transfer_signatures USING (credit_serial)" + " WHERE execution_time < $2" + " AND execution_time >= $3" + " AND credit_serial < $4" + " AND payto_uri = $6" + " AND merchant_serial =" + " (SELECT merchant_serial" + " FROM merchant_instances" + " WHERE merchant_id=$1)" + " ORDER BY credit_serial DESC" + " LIMIT $5", + 6), + /* for postgres_lookup_transfers() */ + GNUNET_PQ_make_prepare ("lookup_transfers_time_desc", + "SELECT" + " credit_amount_val" + ",credit_amount_frac" + ",wtid" + ",merchant_accounts.payto_uri" + ",exchange_url" + ",credit_serial" + ",merchant_transfer_signatures.execution_time" + ",verified" + ",confirmed" + " FROM merchant_transfers" + " JOIN merchant_accounts USING (account_serial)" + " JOIN merchant_transfer_signatures USING (credit_serial)" + " WHERE execution_time < $2" + " AND execution_time >= $3" + " AND credit_serial < $4" + " AND merchant_serial =" + " (SELECT merchant_serial" + " FROM merchant_instances" + " WHERE merchant_id=$1)" + " ORDER BY credit_serial DESC" + " LIMIT $5", + 5), + /* for postgres_lookup_transfers() */ + GNUNET_PQ_make_prepare ("lookup_transfers_payto_desc", + "SELECT" + " credit_amount_val" + ",credit_amount_frac" + ",wtid" + ",merchant_accounts.payto_uri" + ",exchange_url" + ",credit_serial" + ",CASE WHEN (merchant_transfer_signatures.execution_time) IS NULL" + " THEN 9223372036854775807" /* largest BIGINT possible */ + " ELSE merchant_transfer_signatures.execution_time" + " END AS execution_time" + ",verified" + ",confirmed" + " FROM merchant_transfers" + " JOIN merchant_accounts USING (account_serial)" + " LEFT JOIN merchant_transfer_signatures USING (credit_serial)" + " WHERE credit_serial < $2" + " AND payto_uri = $4" + " AND merchant_serial =" + " (SELECT merchant_serial" + " FROM merchant_instances" + " WHERE merchant_id=$1)" + " ORDER BY credit_serial DESC" + " LIMIT $3", + 4), + /* for postgres_lookup_transfers() */ + GNUNET_PQ_make_prepare ("lookup_transfers_desc", + "SELECT" + " credit_amount_val" + ",credit_amount_frac" + ",wtid" + ",merchant_accounts.payto_uri" + ",exchange_url" + ",credit_serial" + ",CASE WHEN (merchant_transfer_signatures.execution_time) IS NULL" + " THEN 9223372036854775807" /* largest BIGINT possible */ + " ELSE merchant_transfer_signatures.execution_time" + " END AS execution_time" + ",verified" + ",confirmed" + " FROM merchant_transfers" + " JOIN merchant_accounts USING (account_serial)" + " LEFT JOIN merchant_transfer_signatures USING (credit_serial)" + " WHERE credit_serial < $2" + " AND merchant_serial =" + " (SELECT merchant_serial" + " FROM merchant_instances" + " WHERE merchant_id=$1)" + " ORDER BY credit_serial DESC" + " LIMIT $3", + 3), /* OLD API: */ #if 0 @@ -6333,12 +6629,12 @@ libtaler_plugin_merchantdb_postgres_init (void *cls) &postgres_set_transfer_status_to_verified; plugin->lookup_transfer_summary = &postgres_lookup_transfer_summary; plugin->lookup_transfer_details = &postgres_lookup_transfer_details; + plugin->lookup_transfers = &postgres_lookup_transfers; /* OLD API: */ plugin->store_coin_to_transfer = &postgres_store_coin_to_transfer; plugin->store_transfer_to_proof = &postgres_store_transfer_to_proof; plugin->store_wire_fee_by_exchange = &postgres_store_wire_fee_by_exchange; - plugin->find_transfers_by_hash = &postgres_find_transfers_by_hash; plugin->find_proof_by_wtid = &postgres_find_proof_by_wtid; plugin->get_authorized_tip_amount = &postgres_get_authorized_tip_amount; plugin->enable_tip_reserve_TR = &postgres_enable_tip_reserve_TR; diff --git a/src/include/taler_merchantdb_plugin.h b/src/include/taler_merchantdb_plugin.h index a9816a0f..5321b574 100644 --- a/src/include/taler_merchantdb_plugin.h +++ b/src/include/taler_merchantdb_plugin.h @@ -425,6 +425,35 @@ typedef void const struct TALER_TrackTransferDetails *ttd); +/** + * Function called with information about a wire transfer. + * + * @param cls closure with a `json_t *` array to build up the response + * @param credit_amount how much was wired to the merchant (minus fees) + * @param wtid wire transfer identifier + * @param payto_uri target account that received the wire transfer + * @param exchange_url base URL of the exchange that made the wire transfer + * @param transfer_serial_id serial number identifying the transfer in the backend + * @param execution_time when did the exchange make the transfer, #GNUNET_TIME_UNIT_FOREVER_ABS + * if it did not yet happen + * @param verified true if we checked the exchange's answer and liked it, + * false there is a problem (verification failed or did not yet happen) + * @param confirmed true if the merchant confirmed this wire transfer + * false if it is so far only claimed to have been made by the exchange + */ +typedef void +(*TALER_MERCHANTDB_TransferCallback)( + void *cls, + const struct TALER_Amount *credit_amount, + const struct TALER_WireTransferIdentifierRawP *wtid, + const char *payto_uri, + const char *exchange_url, + uint64_t transfer_serial_id, + struct GNUNET_TIME_Absolute execution_time, + bool verified, + bool confirmed); + + /* **************** OLD: ******************** */ /** @@ -495,33 +524,6 @@ typedef void /** - * Information about the wire transfer corresponding to - * a deposit operation. Note that it is in theory possible - * that we have a @a h_contract_terms and @a coin_pub in the - * result that do not match a deposit that we know about, - * for example because someone else deposited funds into - * our account. - * - * @param cls closure - * @param h_contract_terms hashcode of the proposal data - * @param coin_pub public key of the coin - * @param wtid identifier of the wire transfer in which the exchange - * send us the money for the coin deposit - * @param execution_time when was the wire transfer executed? - * @param exchange_proof proof from exchange about what the deposit was for - * NULL if we have not asked for this signature - */ -typedef void -(*TALER_MERCHANTDB_TransferCallback)( - void *cls, - const struct GNUNET_HashCode *h_contract_terms, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_WireTransferIdentifierRawP *wtid, - struct GNUNET_TIME_Absolute execution_time, - const json_t *exchange_proof); - - -/** * Function called with information about a wire transfer identifier. * * @param cls closure @@ -1346,7 +1348,6 @@ struct TALER_MERCHANTDB_Plugin * Lookup transfer status. * * @param cls closure - * @param instance_id instance to lookup payments for * @param exchange_url the exchange that made the transfer * @param payto_uri account that received the transfer * @param wtid wire transfer subject @@ -1426,6 +1427,35 @@ struct TALER_MERCHANTDB_Plugin void *cb_cls); + /** + * Lookup transfers. + * + * @param cls closure + * @param instance_id instance to lookup payments for + * @param payto_uri account that we are interested in transfers to + * @param before timestamp for the earliest transfer we care about + * @param after timestamp for the last transfer we care about + * @param limit number of entries to return, negative for descending in execution time, + * positive for ascending in execution time + * @param offset transfer_serial number of the transfer we want to offset from + * @param verified filter transfers by verification status + * @param cb function to call with detailed transfer data + * @param cb_cls closure for @a cb + * @return transaction status + */ + enum GNUNET_DB_QueryStatus + (*lookup_transfers)(void *cls, + const char *instance_id, + const char *payto_uri, + struct GNUNET_TIME_Absolute before, + struct GNUNET_TIME_Absolute after, + int64_t limit, + uint64_t offset, + enum TALER_MERCHANTDB_YesNoAll yna, + TALER_MERCHANTDB_TransferCallback cb, + void *cb_cls); + + /* ****************** OLD API ******************** */ @@ -1605,26 +1635,6 @@ struct TALER_MERCHANTDB_Plugin /** - * Lookup information about a transfer by @a h_contract_terms. Note - * that in theory there could be multiple wire transfers for a - * single @a h_contract_terms, as the transaction may have involved - * multiple coins and the coins may be spread over different wire - * transfers. - * - * @param cls closure - * @param h_contract_terms proposal data's hashcode - * @param cb function to call with transfer data - * @param cb_cls closure for @a cb - * @return transaction status - */ - enum GNUNET_DB_QueryStatus - (*find_transfers_by_hash)(void *cls, - const struct GNUNET_HashCode *h_contract_terms, - TALER_MERCHANTDB_TransferCallback cb, - void *cb_cls); - - - /** * Lookup proof information about a wire transfer. * * @param cls closure |