summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2020-05-06 21:41:59 +0200
committerChristian Grothoff <christian@grothoff.org>2020-05-06 21:41:59 +0200
commit02faacad3cd56e3266be625980920e420f61250f (patch)
tree87cdea74319d0fe822e0cabe481114409973791a /src
parentc84339de2d37076cfd114ae1a097cf084d36b7a0 (diff)
downloadmerchant-02faacad3cd56e3266be625980920e420f61250f.tar.gz
merchant-02faacad3cd56e3266be625980920e420f61250f.tar.bz2
merchant-02faacad3cd56e3266be625980920e420f61250f.zip
db work for POST /transfers
Diffstat (limited to 'src')
-rw-r--r--src/backend/taler-merchant-httpd_private-post-transfers.c18
-rw-r--r--src/backenddb/merchant-0001.sql2
-rw-r--r--src/backenddb/plugin_merchantdb_postgres.c255
-rw-r--r--src/include/taler_merchantdb_plugin.h22
4 files changed, 284 insertions, 13 deletions
diff --git a/src/backend/taler-merchant-httpd_private-post-transfers.c b/src/backend/taler-merchant-httpd_private-post-transfers.c
index 2f22d051..5c3a0e3e 100644
--- a/src/backend/taler-merchant-httpd_private-post-transfers.c
+++ b/src/backend/taler-merchant-httpd_private-post-transfers.c
@@ -1013,6 +1013,7 @@ TMH_private_post_transfers (const struct TMH_RequestHandler *rh,
/* reply not in database, ensure the POST is in the database, and
start work to obtain the reply from the exchange */
qs = TMH_db->insert_transfer (TMH_db->cls,
+ rctx->hc->instance->settings.id,
rctx->exchange_url,
&rctx->wtid,
&rctx->amount,
@@ -1029,6 +1030,23 @@ TMH_private_post_transfers (const struct TMH_RequestHandler *rh,
TALER_EC_POST_TRANSFER_DB_STORE_ERROR,
"Fail to update database with transfer record");
}
+ if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+ {
+ uint64_t account_serial;
+
+ /* Either the record already exists (we should ignore this), or
+ the INSERT failed because we did not find the account based on
+ the given payto-URI and the instance. */
+ qs = TMH_db->lookup_account (TMH_db->cls,
+ rctx->hc->instance->settings.id,
+ rctx->payto_uri,
+ &account_serial);
+ if (0 >= qs)
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_NOT_FOUND,
+ TALER_EC_POST_TRANSFER_ACCOUNT_NOT_FOUND,
+ "Instance does not have this bank account");
+ }
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Suspending POST /private/transfers handling while working with exchange\n");
diff --git a/src/backenddb/merchant-0001.sql b/src/backenddb/merchant-0001.sql
index 3feb3470..55cef426 100644
--- a/src/backenddb/merchant-0001.sql
+++ b/src/backenddb/merchant-0001.sql
@@ -368,8 +368,6 @@ COMMENT ON COLUMN merchant_transfers.confirmed
CREATE TABLE IF NOT EXISTS merchant_transfer_signatures
(credit_serial BIGINT PRIMARY KEY
REFERENCES merchant_transfers (credit_serial) ON DELETE CASCADE
- ,account_serial BIGINT NOT NULL
- REFERENCES merchant_accounts (account_serial) ON DELETE CASCADE
,signkey_serial BIGINT NOT NULL
REFERENCES merchant_exchange_signing_keys (signkey_serial) ON DELETE CASCADE
,execution_time INT8 NOT NULL
diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c
index e6bc5306..acb32e9b 100644
--- a/src/backenddb/plugin_merchantdb_postgres.c
+++ b/src/backenddb/plugin_merchantdb_postgres.c
@@ -2696,6 +2696,7 @@ postgres_lookup_order_by_fulfillment (void *cls,
* Insert information about a wire transfer the merchant has received.
*
* @param cls closure
+ * @param instance_id the instance that received the transfer
* @param exchange_url which exchange made the transfer
* @param wtid identifier of the wire transfer
* @param credit_amount how much did we receive
@@ -2707,12 +2708,64 @@ postgres_lookup_order_by_fulfillment (void *cls,
static enum GNUNET_DB_QueryStatus
postgres_insert_transfer (
void *cls,
+ const char *instance_id,
const char *exchange_url,
const struct TALER_WireTransferIdentifierRawP *wtid,
const struct TALER_Amount *credit_amount,
const char *payto_uri,
bool confirmed)
{
+ struct PostgresClosure *pg = cls;
+ uint8_t confirmed8 = confirmed;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (exchange_url),
+ GNUNET_PQ_query_param_auto_from_type (wtid),
+ TALER_PQ_query_param_amount (credit_amount),
+ GNUNET_PQ_query_param_string (payto_uri),
+ GNUNET_PQ_query_param_auto_from_type (&confirmed8),
+ GNUNET_PQ_query_param_string (instance_id),
+ GNUNET_PQ_query_param_end
+ };
+
+ check_connection (pg);
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_transfer",
+ params);
+}
+
+
+/**
+ * Lookup account serial by payto URI.
+ *
+ * @param cls closure
+ * @param instance_id instance to lookup the account from
+ * @param payto_uri what is the merchant's bank account to lookup
+ * @param[out] account_serial serial number of the account
+ * @return transaction status
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_lookup_account (void *cls,
+ const char *instance_id,
+ const char *payto_uri,
+ uint64_t *account_serial)
+{
+ struct PostgresClosure *pg = cls;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
+ GNUNET_PQ_query_param_string (payto_uri),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("account_serial",
+ account_serial),
+ GNUNET_PQ_result_spec_end
+ };
+
+ check_connection (pg);
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "lookup_account",
+ params,
+ rs);
}
@@ -2720,6 +2773,7 @@ postgres_insert_transfer (
* Insert information about a wire transfer the merchant has received.
*
* @param cls closure
+ * @param instance_id instance to provide transfer details for
* @param exchange_url which exchange made the transfer
* @param payto_uri what is the merchant's bank account that received the transfer
* @param wtid identifier of the wire transfer
@@ -2729,11 +2783,123 @@ postgres_insert_transfer (
static enum GNUNET_DB_QueryStatus
postgres_insert_transfer_details (
void *cls,
- const char *exchange_url, // FIXME: do we need the URL? We have exchange_pub!
+ const char *instance_id,
+ const char *exchange_url,
const char *payto_uri,
const struct TALER_WireTransferIdentifierRawP *wtid,
const struct TALER_EXCHANGE_TransferData *td)
{
+ struct PostgresClosure *pg = cls;
+ enum GNUNET_DB_QueryStatus qs;
+ uint64_t credit_serial;
+ unsigned int retries;
+
+ retries = 0;
+ check_connection (pg);
+RETRY:
+ if (MAX_RETRIES < ++retries)
+ return GNUNET_DB_STATUS_SOFT_ERROR;
+ if (GNUNET_OK !=
+ postgres_start (pg,
+ "insert transfer details"))
+ {
+ GNUNET_break (0);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+
+ /* lookup credit serial */
+ {
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (exchange_url),
+ GNUNET_PQ_query_param_string (payto_uri),
+ GNUNET_PQ_query_param_string (instance_id),
+ GNUNET_PQ_query_param_auto_from_type (wtid),
+ TALER_PQ_query_param_amount (&td->total_amount),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("credit_serial",
+ &credit_serial),
+ GNUNET_PQ_result_spec_end
+ };
+
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "lookup_credit_serial",
+ params,
+ rs);
+ if (0 > qs)
+ {
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+ postgres_rollback (pg);
+ if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+ goto RETRY;
+ return qs;
+ }
+ if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+ {
+ /* account does not exists, fail! */
+ postgres_rollback (pg);
+ return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+ }
+ }
+
+ /* update merchant_transfer_signatures table */
+ {
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&credit_serial),
+ GNUNET_PQ_query_param_absolute_time (&td->execution_time),
+ GNUNET_PQ_query_param_auto_from_type (&td->exchange_sig),
+ GNUNET_PQ_query_param_auto_from_type (&td->exchange_pub),
+ GNUNET_PQ_query_param_end
+ };
+
+ qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_transfer_signature",
+ params);
+ if (0 > qs)
+ {
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+ postgres_rollback (pg);
+ if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+ goto RETRY;
+ return qs;
+ }
+ }
+
+ /* Update transfer-coin association table */
+ for (unsigned int i = 0; i<td->details_length; i++)
+ {
+ const struct TALER_TrackTransferDetails *d = &td->details[i];
+ uint32_t i32 = (uint32_t) i;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&credit_serial),
+ GNUNET_PQ_query_param_uint32 (&i32),
+ TALER_PQ_query_param_amount (&d->coin_value),
+ TALER_PQ_query_param_amount (&d->coin_fee), /* deposit fee */
+ GNUNET_PQ_query_param_auto_from_type (&d->coin_pub),
+ GNUNET_PQ_query_param_auto_from_type (&d->h_contract_terms),
+ GNUNET_PQ_query_param_end
+ };
+
+ qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_transfer_to_coin_mapping",
+ params);
+ if (0 > qs)
+ {
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+ postgres_rollback (pg);
+ if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+ goto RETRY;
+ return qs;
+ }
+ }
+ qs = postgres_commit (pg);
+ if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+ return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+ if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+ goto RETRY;
+ return qs;
}
@@ -5604,17 +5770,86 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
" FROM merchant_instances"
" WHERE merchant_id=$1)",
3),
-
+ /* for postgres_insert_transfer() */
+ GNUNET_PQ_make_prepare ("insert_transfer",
+ "INSERT INTO merchant_transfers"
+ "(exchange_url"
+ ",wtid"
+ ",credit_amount_val"
+ ",credit_amount_frac"
+ ",account_serial"
+ ",confirmed)"
+ "SELECT"
+ " $1, $2, $3, $4, account_serial, $6"
+ " FROM merchant_accounts"
+ " WHERE payto_uri=$5"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$7)",
+ 7),
+ /* for postgres_lookup_account() */
+ GNUNET_PQ_make_prepare ("lookup_account",
+ "SELECT"
+ " account_serial"
+ " FROM merchant_accounts"
+ " WHERE payto_uri=$2"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)",
+ 2),
+ /* for postgres_insert_transfer_details() */
+ GNUNET_PQ_make_prepare ("lookup_credit_serial",
+ "SELECT"
+ " credit_serial"
+ " FROM merchant_transfers"
+ " WHERE exchange_url=$1"
+ " AND wtid=$4"
+ " AND credit_account_val=$5"
+ " AND credit_account_frac=$6"
+ " AND account_serial="
+ " (SELECT account_serial"
+ " FROM merchant_accounts"
+ " WHERE payto_uri=$2"
+ " AND exchange_url=$1"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$3))",
+ 2),
+ /* for postgres_insert_transfer_details() */
+ GNUNET_PQ_make_prepare ("insert_transfer_signature",
+ "INSERT INTO merchant_transfer_signatures"
+ "(credit_serial"
+ ",signkey_serial"
+ ",execution_time"
+ ",exchange_sig) "
+ "SELECT $1, signkey_serial, $2, $3"
+ " FROM merchant_exchange_signing_keys"
+ " WHERE exchange_pub=$4"
+ " ORDER BY start_date DESC"
+ " LIMIT 1",
+ 4),
+ /* for postgres_insert_transfer_details() */
+ GNUNET_PQ_make_prepare ("insert_transfer_to_coin_mapping",
+ "INSERT INTO merchant_transfer_to_coin"
+ "(deposit_serial"
+ ",credit_serial"
+ ",offset_in_exchange_list"
+ ",exchange_deposit_value_val"
+ ",exchange_deposit_value_frac"
+ ",exchange_deposit_fee_val"
+ ",exchange_deposit_fee_frac) "
+ "SELECT deposit_serial, $1, $2, $3, $4, $5, $6"
+ " FROM merchant_deposits"
+ " JOIN merchant_contract_terms USING (order_serial)"
+ " WHERE coin_pub=$7"
+ " AND h_contract_terms=$8",
+ 8),
/* OLD API: */
#if 0
- GNUNET_PQ_make_prepare ("insert_transfer",
- "INSERT INTO merchant_transfers"
- "(h_contract_terms"
- ",coin_pub"
- ",wtid) VALUES "
- "($1, $2, $3)",
- 3),
GNUNET_PQ_make_prepare ("insert_contract_terms",
"INSERT INTO merchant_contract_terms"
"(order_id"
@@ -5942,8 +6177,8 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
plugin->insert_refund_proof = &postgres_insert_refund_proof;
plugin->lookup_refund_proof = &postgres_lookup_refund_proof;
plugin->lookup_order_by_fulfillment = &postgres_lookup_order_by_fulfillment;
- /* WIP: */
plugin->insert_transfer = &postgres_insert_transfer;
+ plugin->lookup_account = &postgres_lookup_account;
plugin->insert_transfer_details = &postgres_insert_transfer_details;
plugin->lookup_wire_fee = &postgres_lookup_wire_fee;
diff --git a/src/include/taler_merchantdb_plugin.h b/src/include/taler_merchantdb_plugin.h
index e0f76999..94fe6188 100644
--- a/src/include/taler_merchantdb_plugin.h
+++ b/src/include/taler_merchantdb_plugin.h
@@ -1199,6 +1199,7 @@ struct TALER_MERCHANTDB_Plugin
* Insert information about a wire transfer the merchant has received.
*
* @param cls closure
+ * @param instance_id instance to lookup the order from
* @param exchange_url which exchange made the transfer
* @param wtid identifier of the wire transfer
* @param credit_amount how much did we receive
@@ -1210,6 +1211,7 @@ struct TALER_MERCHANTDB_Plugin
enum GNUNET_DB_QueryStatus
(*insert_transfer)(
void *cls,
+ const char *instance_id,
const char *exchange_url,
const struct TALER_WireTransferIdentifierRawP *wtid,
const struct TALER_Amount *credit_amount,
@@ -1218,9 +1220,26 @@ struct TALER_MERCHANTDB_Plugin
/**
+ * Lookup account serial by payto URI.
+ *
+ * @param cls closure
+ * @param instance_id instance to lookup the account from
+ * @param payto_uri what is the merchant's bank account to lookup
+ * @param[out] account_serial serial number of the account
+ * @return transaction status
+ */
+ enum GNUNET_DB_QueryStatus
+ (*lookup_account)(void *cls,
+ const char *instance_id,
+ const char *payto_uri,
+ uint64_t *account_serial);
+
+
+ /**
* Insert information about a wire transfer the merchant has received.
*
* @param cls closure
+ * @param instance_id instance to provide transfer details for
* @param exchange_url which exchange made the transfer
* @param payto_uri what is the merchant's bank account that received the transfer
* @param wtid identifier of the wire transfer
@@ -1230,7 +1249,8 @@ struct TALER_MERCHANTDB_Plugin
enum GNUNET_DB_QueryStatus
(*insert_transfer_details)(
void *cls,
- const char *exchange_url, // FIXME: do we need the URL? We have exchange_pub!
+ const char *instance_id,
+ const char *exchange_url,
const char *payto_uri,
const struct TALER_WireTransferIdentifierRawP *wtid,
const struct TALER_EXCHANGE_TransferData *td);