diff options
author | Christian Grothoff <christian@grothoff.org> | 2020-05-06 21:41:59 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2020-05-06 21:41:59 +0200 |
commit | 02faacad3cd56e3266be625980920e420f61250f (patch) | |
tree | 87cdea74319d0fe822e0cabe481114409973791a /src | |
parent | c84339de2d37076cfd114ae1a097cf084d36b7a0 (diff) | |
download | merchant-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.c | 18 | ||||
-rw-r--r-- | src/backenddb/merchant-0001.sql | 2 | ||||
-rw-r--r-- | src/backenddb/plugin_merchantdb_postgres.c | 255 | ||||
-rw-r--r-- | src/include/taler_merchantdb_plugin.h | 22 |
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); |