diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/taler-merchant-httpd_get-orders-ID.c | 10 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_post-orders-ID-abort.c | 3 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_private-post-transfers.c | 106 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_private-post-transfers.h | 26 | ||||
-rw-r--r-- | src/backenddb/merchant-0001.sql | 13 | ||||
-rw-r--r-- | src/backenddb/plugin_merchantdb_postgres.c | 595 | ||||
-rw-r--r-- | src/include/taler_merchantdb_plugin.h | 2 |
7 files changed, 313 insertions, 442 deletions
diff --git a/src/backend/taler-merchant-httpd_get-orders-ID.c b/src/backend/taler-merchant-httpd_get-orders-ID.c index 0fae0a98..f22ac8a3 100644 --- a/src/backend/taler-merchant-httpd_get-orders-ID.c +++ b/src/backend/taler-merchant-httpd_get-orders-ID.c @@ -75,6 +75,12 @@ struct CoinRefund json_t *exchange_reply; /** + * When did the merchant grant the refund. To be used to group events + * in the wallet. + */ + struct GNUNET_TIME_Absolute execution_time; + + /** * Coin to refund. */ struct TALER_CoinSpendPublicKeyP coin_pub; @@ -435,12 +441,14 @@ check_resume_god (struct GetOrderData *god) * * @param cls a `struct CoinRefund` * @param hr HTTP response data + * @param refund_fee fee the exchange charged * @param exchange_pub exchange key used to sign refund confirmation * @param exchange_sig exchange's signature over refund */ static void refund_cb (void *cls, const struct TALER_EXCHANGE_HttpResponse *hr, + const struct TALER_Amount *refund_fee, const struct TALER_ExchangePublicKeyP *exchange_pub, const struct TALER_ExchangeSignatureP *exchange_sig) { @@ -465,6 +473,7 @@ refund_cb (void *cls, cr->exchange_sig = *exchange_sig; qs = TMH_db->insert_refund_proof (TMH_db->cls, cr->refund_serial, + refund_fee, exchange_sig, exchange_pub); if (0 >= qs) @@ -557,6 +566,7 @@ process_refunds_cb (void *cls, cr->coin_pub = *coin_pub; cr->rtransaction_id = rtransaction_id; cr->refund_amount = *refund_amount; + cr->execution_time = timestamp; GNUNET_CONTAINER_DLL_insert (god->cr_head, god->cr_tail, cr); diff --git a/src/backend/taler-merchant-httpd_post-orders-ID-abort.c b/src/backend/taler-merchant-httpd_post-orders-ID-abort.c index 4c7960ef..564f0e3c 100644 --- a/src/backend/taler-merchant-httpd_post-orders-ID-abort.c +++ b/src/backend/taler-merchant-httpd_post-orders-ID-abort.c @@ -438,12 +438,14 @@ find_next_exchange (struct AbortContext *ac); * * @param cls closure * @param hr HTTP response data + * @param refund_fee fee the exchange charged * @param sign_key exchange key used to sign @a obj, or NULL * @param signature the actual signature, or NULL on error */ static void refund_cb (void *cls, const struct TALER_EXCHANGE_HttpResponse *hr, + const struct TALER_Amount *refund_fee, const struct TALER_ExchangePublicKeyP *sign_key, const struct TALER_ExchangeSignatureP *signature) { @@ -452,6 +454,7 @@ refund_cb (void *cls, (void) sign_key; (void) signature; + (void) refund_fee; rd->rh = NULL; rd->http_status = hr->http_status; rd->exchange_reply = json_incref ((json_t*) hr->reply); diff --git a/src/backend/taler-merchant-httpd_private-post-transfers.c b/src/backend/taler-merchant-httpd_private-post-transfers.c index 6304761f..ce76a6f2 100644 --- a/src/backend/taler-merchant-httpd_private-post-transfers.c +++ b/src/backend/taler-merchant-httpd_private-post-transfers.c @@ -258,12 +258,12 @@ build_deposits_response (void *cls, json_t *contract_terms; json_t *order_id; - db->preflight (db->cls); + TMH_db->preflight (TMH_db->cls); if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != - db->find_contract_terms_from_hash (db->cls, - &contract_terms, - key, - &rctx->mi->pubkey)) + TMH_db->find_contract_terms_from_hash (TMH_db->cls, + &contract_terms, + key, + &rctx->mi->pubkey)) { GNUNET_break_op (0); return GNUNET_NO; @@ -541,16 +541,16 @@ check_wire_fee (struct TrackTransferContext *rctx, char *wire_method; wire_method = TALER_payto_get_method (rctx->payto_uri); - db->preflight (db->cls); - qs = db->lookup_wire_fee (db->cls, - &rctx->master_pub, - wire_method, - execution_time, - &expected_fee, - &closing_fee, - &start_date, - &end_date, - &master_sig); + TMH_db->preflight (TMH_db->cls); + qs = TMH_db->lookup_wire_fee (TMH_db->cls, + &rctx->master_pub, + wire_method, + execution_time, + &expected_fee, + &closing_fee, + &start_date, + &end_date, + &master_sig); if (0 >= qs) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, @@ -636,16 +636,16 @@ wire_transfer_cb (void *cls, "exchange_reply", hr->reply)); return; } - db->preflight (db->cls); - qs = db->insert_transfer_details (db->cls, - rctx->exchange_url, - rctx->payto_uri, - &rctx->wtid, - total_amount, - wire_fee, - execution_time, - details_length, - details); + TMH_db->preflight (TMH_db->cls); + qs = TMH_db->insert_transfer_details (TMH_db->cls, + rctx->exchange_url, + rctx->payto_uri, + &rctx->wtid, + total_amount, + wire_fee, + execution_time, + details_length, + details); if (0 > qs) { /* Special report if retries insufficient */ @@ -685,13 +685,13 @@ wire_transfer_cb (void *cls, rctx->current_detail = &details[i]; /* Set the coin as "never seen" before. */ rctx->check_transfer_result = GNUNET_NO; - db->preflight (db->cls); - qs = db->find_payments_by_hash_and_coin (db->cls, - &details[i].h_contract_terms, - &rctx->mi->pubkey, - &details[i].coin_pub, - &check_transfer, - rctx); + TMH_db->preflight (TMH_db->cls); + qs = TMH_db->find_payments_by_hash_and_coin (TMH_db->cls, + &details[i].h_contract_terms, + &rctx->mi->pubkey, + &details[i].coin_pub, + &check_transfer, + rctx); if (0 > qs) { /* single, read-only SQL statements should never cause @@ -752,11 +752,11 @@ wire_transfer_cb (void *cls, remember it for future reference */ for (unsigned int r = 0; r<MAX_RETRIES; r++) { - db->preflight (db->cls); - qs = db->store_coin_to_transfer (db->cls, - &details[i].h_contract_terms, - &details[i].coin_pub, - &rctx->wtid); + TMH_db->preflight (TMH_db->cls); + qs = TMH_db->store_coin_to_transfer (TMH_db->cls, + &details[i].h_contract_terms, + &details[i].coin_pub, + &rctx->wtid); if (GNUNET_DB_STATUS_SOFT_ERROR != qs) break; } @@ -918,7 +918,7 @@ handle_track_transfer_timeout (void *cls) /** - * Manages a POST /private/transfers call. It calls the /track/wtid + * Manages a POST /private/transfers call. It calls the GET /transfers/$WTID * offered by the exchange in order to obtain the set of transfers * (of coins) associated with a given wire transfer. * @@ -1015,16 +1015,16 @@ TMH_private_post_transfers (const struct TMH_RequestHandler *rh, deposit_sums = json_array (); GNUNET_assert (NULL != deposit_sums); - db->preflight (db->cls); - qs = db->lookup_transfer_details (db->cls, - rctx->exchange_url, - rctx->payto_uri, - &rctx->wtid, - &total_amount, - &wire_fee, - &execution_time, - &transfer_details_cb, - deposit_sums); + TMH_db->preflight (TMH_db->cls); + qs = TMH_db->lookup_transfer_details (TMH_db->cls, + rctx->exchange_url, + rctx->payto_uri, + &rctx->wtid, + &total_amount, + &wire_fee, + &execution_time, + &transfer_details_cb, + deposit_sums); if (0 > qs) { /* Simple select queries should not cause serialization issues */ @@ -1053,11 +1053,11 @@ 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 = db->insert_transfer (db->cls, - rctx->exchange_url, - &rctx->wtid, - &rctx->amount, - rctx->payto_uri); + qs = TMH_db->insert_transfer (TMH_db->cls, + rctx->exchange_url, + &rctx->wtid, + &rctx->amount, + rctx->payto_uri); if (0 > qs) { /* Simple select queries should not cause serialization issues */ diff --git a/src/backend/taler-merchant-httpd_private-post-transfers.h b/src/backend/taler-merchant-httpd_private-post-transfers.h index 0463295e..2c548f77 100644 --- a/src/backend/taler-merchant-httpd_private-post-transfers.h +++ b/src/backend/taler-merchant-httpd_private-post-transfers.h @@ -14,36 +14,30 @@ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ /** - * @file backend/taler-merchant-httpd_track-transfer.h + * @file backend/taler-merchant-httpd_private-post-transfers.h * @brief headers for /track/transfer 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_POST_TRANSFERS_H +#define TALER_MERCHANT_HTTPD_PRIVATE_POST_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 POST /private/transfers call. It calls the GET /transfers/$WTID + * offered by the exchange in order to obtain the set of transfers + * (of coins) associated with a given wire transfer. * * @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, - struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size, - struct MerchantInstance *mi); +TMH_private_post_transfers (const struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + struct TMH_HandlerContext *hc); #endif diff --git a/src/backenddb/merchant-0001.sql b/src/backenddb/merchant-0001.sql index 6abc0554..3feb3470 100644 --- a/src/backenddb/merchant-0001.sql +++ b/src/backenddb/merchant-0001.sql @@ -334,20 +334,15 @@ CREATE TABLE IF NOT EXISTS merchant_refund_proofs (refund_serial BIGINT PRIMARY KEY REFERENCES merchant_refunds (refund_serial) ON DELETE CASCADE ,exchange_sig BYTEA NOT NULL CHECK (LENGTH(exchange_sig)=64) - ,execution_time INT8 NOT NULL - ,total_amount_val INT8 NOT NULL - ,total_amount_frac INT4 NOT NULL - ,wire_fee_val INT8 NOT NULL - ,wire_fee_frac INT4 NOT NULL + ,refund_fee_val INT8 NOT NULL + ,refund_fee_frac INT4 NOT NULL ,signkey_serial BIGINT NOT NULL REFERENCES merchant_exchange_signing_keys (signkey_serial) ON DELETE CASCADE ); COMMENT ON TABLE merchant_refund_proofs IS 'Refunds confirmed by the exchange (not all approved refunds are grabbed by the wallet)'; -COMMENT ON COLUMN merchant_refund_proofs.execution_time - IS 'When did the exchange claim to execute the wire transfer'; -COMMENT ON COLUMN merchant_refund_proofs.total_amount_val - IS 'Amount the exchange claims to have deducted from the merchant balance; actual transfer amount is this minus the wire fee'; +COMMENT ON COLUMN merchant_refund_proofs.refund_fee_val + IS 'Refund fee exchange charged'; -------------------- Wire transfers --------------------------- diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c index 15996425..ef7deabb 100644 --- a/src/backenddb/plugin_merchantdb_postgres.c +++ b/src/backenddb/plugin_merchantdb_postgres.c @@ -2445,159 +2445,255 @@ postgres_increase_refund (void *cls, /** - * Retrieve the order ID that was used to pay for a resource within a session. + * Closure for #lookup_refunds_detailed_cb(). + */ +struct LookupRefundsDetailedContext +{ + /** + * Function to call for each refund. + */ + TALER_MERCHANTDB_RefundDetailCallback rc; + + /** + * Closure for @e rc. + */ + void *rc_cls; + + /** + * Plugin context. + */ + struct PostgresClosure *pg; + + /** + * Transaction result. + */ + 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 closure - * @param instance_id identifying the instance - * @param fulfillment_url URL that canonically identifies the resource - * being paid for - * @param session_id session id - * @param[out] order_id where to store the order ID that was used when - * paying for the resource URL + * @param cls of type `struct GetRefundsContext *` + * @param result the postgres result + * @param num_result the number of results in @a result + */ +static void +lookup_refunds_detailed_cb (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRefundsDetailedContext *lrdc = cls; + struct PostgresClosure *pg = lrdc->pg; + + for (unsigned int i = 0; i<num_results; i++) + { + uint64_t refund_serial; + struct GNUNET_TIME_Absolute timestamp; + struct TALER_CoinSpendPublicKeyP coin_pub; + uint64_t rtransaction_id; + struct TALER_Amount refund_amount; + char *reason; + char *exchange_url; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("refund_serial", + &refund_serial), + GNUNET_PQ_result_spec_absolute_time ("refund_timestamp", + ×tamp), + GNUNET_PQ_result_spec_auto_from_type ("coin_pub", + &coin_pub), + GNUNET_PQ_result_spec_string ("exchange_url", + &exchange_url), + GNUNET_PQ_result_spec_uint64 ("rtransaction_id", + &rtransaction_id), + GNUNET_PQ_result_spec_string ("reason", + &reason), + TALER_PQ_RESULT_SPEC_AMOUNT ("refund_amount", + &refund_amount), + GNUNET_PQ_result_spec_end + }; + + if (GNUNET_OK != + GNUNET_PQ_extract_result (result, + rs, + i)) + { + GNUNET_break (0); + lrdc->qs = GNUNET_DB_STATUS_HARD_ERROR; + return; + } + lrdc->qs = i + 1; + lrdc->rc (lrdc->rc_cls, + refund_serial, + timestamp, + &coin_pub, + exchange_url, + rtransaction_id, + reason, + &refund_amount); + GNUNET_PQ_cleanup_result (rs); + } +} + + +/** + * Obtain detailed refund data associated with a contract. + * + * @param cls closure, typically a connection to the db + * @param instance_id instance to lookup refunds for + * @param h_contract_terms hash code of the contract + * @param rc function to call for each coin on which there is a refund + * @param rc_cls closure for @a rc * @return transaction status */ -enum GNUNET_DB_QueryStatus -postgres_lookup_order_by_fulfillment (void *cls, - const char *instance_id, - const char *fulfillment_url, - const char *session_id, - char **order_id) +static enum GNUNET_DB_QueryStatus +postgres_lookup_refunds_detailed ( + void *cls, + const char *instance_id, + const struct GNUNET_HashCode *h_contract_terms, + TALER_MERCHANTDB_RefundDetailCallback rc, + void *rc_cls) { struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (instance_id), - GNUNET_PQ_query_param_string (fulfillment_url), - GNUNET_PQ_query_param_string (session_id), + GNUNET_PQ_query_param_auto_from_type (instance_id), + GNUNET_PQ_query_param_auto_from_type (h_contract_terms), GNUNET_PQ_query_param_end }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_string ("order_id", - order_id), - GNUNET_PQ_result_spec_end + struct LookupRefundsDetailedContext lrdc = { + .rc = rc, + .rc_cls = rc_cls, + .pg = pg }; - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "lookup_order_by_fulfillment", - params, - rs); -} + enum GNUNET_DB_QueryStatus qs; + /* no preflight check here, run in transaction by caller! */ + TALER_LOG_DEBUG ("Looking for refund %s + %s\n", + GNUNET_h2s (h_contract_terms), + instance_id); + check_connection (pg); + qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, + "lookup_refunds_detailed", + params, + &lookup_refunds_detailed_cb, + &lrdc); + if (0 >= qs) + return qs; + return lrdc.qs; +} -/* ********************* OLD API ************************** */ /** - * Retrieve proposal data given its proposal data's hashcode + * Insert refund proof data from the exchange into the database. * * @param cls closure - * @param contract_terms where to store the retrieved proposal data - * @param h_contract_terms proposal data's hashcode that will be used to - * perform the lookup + * @param refund_serial serial number of the refund + * @param refund_fee refund fee the exchange said it charged + * @param exchange_sig signature from exchange that coin was refunded + * @param exchange_pub signing key that was used for @a exchange_sig * @return transaction status */ static enum GNUNET_DB_QueryStatus -postgres_find_contract_terms_from_hash ( +postgres_insert_refund_proof ( void *cls, - json_t **contract_terms, - const struct GNUNET_HashCode *h_contract_terms, - const struct TALER_MerchantPublicKeyP *merchant_pub) + uint64_t refund_serial, + const struct TALER_Amount *refund_fee, + const struct TALER_ExchangeSignatureP *exchange_sig, + const struct TALER_ExchangePublicKeyP *exchange_pub) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_contract_terms), - GNUNET_PQ_query_param_auto_from_type (merchant_pub), + GNUNET_PQ_query_param_uint64 (&refund_serial), + GNUNET_PQ_query_param_auto_from_type (exchange_sig), + TALER_PQ_query_param_amount (refund_fee), + GNUNET_PQ_query_param_auto_from_type (exchange_pub), GNUNET_PQ_query_param_end }; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_result_spec_json ("contract_terms", - contract_terms), - GNUNET_PQ_result_spec_end - }; - check_connection (pg); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "find_contract_terms_from_hash", - params, - rs); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_refund_proof", + params); } /** - * Retrieve proposal data given its proposal data's hashcode + * Lookup refund proof data. * * @param cls closure - * @param contract_terms where to store the retrieved proposal data - * @param h_contract_terms proposal data's hashcode that will be used to - * perform the lookup + * @param refund_serial serial number of the refund + * @param[out] exchange_sig set to signature from exchange + * @param[out] exchange_pub signing key that was used for @a exchange_sig * @return transaction status */ static enum GNUNET_DB_QueryStatus -postgres_find_paid_contract_terms_from_hash (void *cls, - json_t **contract_terms, - const struct - GNUNET_HashCode *h_contract_terms, - const struct - TALER_MerchantPublicKeyP * - merchant_pub) +postgres_lookup_refund_proof (void *cls, + uint64_t refund_serial, + struct TALER_ExchangeSignatureP *exchange_sig, + struct TALER_ExchangePublicKeyP *exchange_pub) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_contract_terms), - GNUNET_PQ_query_param_auto_from_type (merchant_pub), + GNUNET_PQ_query_param_uint64 (&refund_serial), GNUNET_PQ_query_param_end }; struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_result_spec_json ("contract_terms", - contract_terms), + GNUNET_PQ_result_spec_auto_from_type ("exchange_sig", + exchange_sig), + GNUNET_PQ_result_spec_auto_from_type ("exchange_pub", + exchange_pub), GNUNET_PQ_result_spec_end }; - /* no preflight check here, runs in its own transaction from - caller (in /pay case) */ check_connection (pg); return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "find_paid_contract_terms_from_hash", + "lookup_refund_proof", params, rs); } /** - * Store the order ID that was used to pay for a resource within a session. + * Retrieve the order ID that was used to pay for a resource within a session. * * @param cls closure - * @param session_id session id + * @param instance_id identifying the instance * @param fulfillment_url URL that canonically identifies the resource * being paid for - * @param order_id the order ID that was used when paying for the resource URL - * @param merchant_pub public key of the merchant, identifying the instance + * @param session_id session id + * @param[out] order_id where to store the order ID that was used when + * paying for the resource URL * @return transaction status */ enum GNUNET_DB_QueryStatus -postgres_insert_session_info (void *cls, - const char *session_id, - const char *fulfillment_url, - const char *order_id, - const struct - TALER_MerchantPublicKeyP *merchant_pub) +postgres_lookup_order_by_fulfillment (void *cls, + const char *instance_id, + const char *fulfillment_url, + const char *session_id, + char **order_id) { struct PostgresClosure *pg = cls; - struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (session_id), + GNUNET_PQ_query_param_string (instance_id), GNUNET_PQ_query_param_string (fulfillment_url), - GNUNET_PQ_query_param_string (order_id), - GNUNET_PQ_query_param_auto_from_type (merchant_pub), - GNUNET_PQ_query_param_absolute_time (&now), + GNUNET_PQ_query_param_string (session_id), GNUNET_PQ_query_param_end }; - - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_session_info", - params); + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_string ("order_id", + order_id), + GNUNET_PQ_result_spec_end + }; + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "lookup_order_by_fulfillment", + params, + rs); } +/* ********************* OLD API ************************** */ + /** * Insert mapping of @a coin_pub and @a h_contract_terms to * corresponding @a wtid. @@ -3373,233 +3469,6 @@ postgres_find_deposits_by_wtid (void *cls, /** - * Closure for #get_refunds_cb(). - */ -struct GetRefundsContext -{ - /** - * Function to call for each refund. - */ - TALER_MERCHANTDB_CoinRefundCallback rc; - - /** - * Closure for @e rc. - */ - void *rc_cls; - - /** - * Plugin context. - */ - struct PostgresClosure *pg; - - /** - * Transaction result. - */ - 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 GetRefundsContext *` - * @param result the postgres result - * @param num_result the number of results in @a result - */ -static void -get_refunds_cb (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct GetRefundsContext *grc = cls; - struct PostgresClosure *pg = grc->pg; - - for (unsigned int i = 0; i<num_results; i++) - { - struct TALER_CoinSpendPublicKeyP coin_pub; - uint64_t rtransaction_id; - struct TALER_Amount refund_amount; - struct TALER_Amount refund_fee; - char *reason; - char *exchange_url; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("coin_pub", - &coin_pub), - GNUNET_PQ_result_spec_string ("exchange_url", - &exchange_url), - GNUNET_PQ_result_spec_uint64 ("rtransaction_id", - &rtransaction_id), - TALER_PQ_RESULT_SPEC_AMOUNT ("refund_amount", - &refund_amount), - TALER_PQ_RESULT_SPEC_AMOUNT ("refund_fee", - &refund_fee), - GNUNET_PQ_result_spec_string ("reason", - &reason), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - i)) - { - GNUNET_break (0); - grc->qs = GNUNET_DB_STATUS_HARD_ERROR; - return; - } - grc->qs = i + 1; - grc->rc (grc->rc_cls, - &coin_pub, - exchange_url, - rtransaction_id, - reason, - &refund_amount, - &refund_fee); - GNUNET_PQ_cleanup_result (rs); - } -} - - -/** - * Obtain refunds associated with a contract. - * - * @param cls closure, typically a connection to the db - * @param merchant_pub public key of the merchant instance - * @param h_contract_terms hash code of the contract - * @param rc function to call for each coin on which there is a refund - * @param rc_cls closure for @a rc - * @return transaction status - */ -enum GNUNET_DB_QueryStatus -postgres_get_refunds_from_contract_terms_hash ( - void *cls, - const struct TALER_MerchantPublicKeyP *merchant_pub, - const struct GNUNET_HashCode *h_contract_terms, - TALER_MERCHANTDB_CoinRefundCallback rc, - void *rc_cls) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (merchant_pub), - GNUNET_PQ_query_param_auto_from_type (h_contract_terms), - GNUNET_PQ_query_param_end - }; - struct GetRefundsContext grc = { - .rc = rc, - .rc_cls = rc_cls, - .pg = pg - }; - enum GNUNET_DB_QueryStatus qs; - - /* no preflight check here, run in transaction by caller! */ - TALER_LOG_DEBUG ("Looking for refund %s + %s\n", - GNUNET_h2s (h_contract_terms), - TALER_B2S (merchant_pub)); - check_connection (pg); - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - "find_refunds_from_contract_terms_hash", - params, - &get_refunds_cb, - &grc); - if (0 >= qs) - return qs; - return grc.qs; -} - - -/** - * Obtain refund proofs associated with a refund operation on a - * coin. - * - * @param cls closure, typically a connection to the db - * @param merchant_pub public key of the merchant instance - * @param h_contract_terms hash code of the contract - * @param coin_pub public key of the coin - * @param rtransaction_id identificator of the refund - * @param[out] exchange_pub public key of the exchange affirming the refund - * @param[out] exchange_sig signature of the exchange affirming the refund - * @return transaction status - */ -static enum GNUNET_DB_QueryStatus -postgres_get_refund_proof ( - void *cls, - const struct TALER_MerchantPublicKeyP *merchant_pub, - const struct GNUNET_HashCode *h_contract_terms, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - uint64_t rtransaction_id, - struct TALER_ExchangePublicKeyP *exchange_pub, - struct TALER_ExchangeSignatureP *exchange_sig) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (h_contract_terms), - GNUNET_PQ_query_param_auto_from_type (merchant_pub), - GNUNET_PQ_query_param_auto_from_type (coin_pub), - GNUNET_PQ_query_param_uint64 (&rtransaction_id), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("exchange_sig", - exchange_sig), - GNUNET_PQ_result_spec_auto_from_type ("exchange_pub", - exchange_pub), - GNUNET_PQ_result_spec_end - }; - - check_connection (pg); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "get_refund_proof", - params, - rs); -} - - -/** - * Store refund proofs associated with a refund operation on a - * coin. - * - * @param cls closure, typically a connection to the db - * @param merchant_pub public key of the merchant instance - * @param h_contract_terms hash code of the contract - * @param coin_pub public key of the coin - * @param rtransaction_id identificator of the refund - * @param exchange_pub public key of the exchange affirming the refund - * @param exchange_sig signature of the exchange affirming the refund - * @return transaction status - */ -static enum GNUNET_DB_QueryStatus -postgres_put_refund_proof ( - void *cls, - const struct TALER_MerchantPublicKeyP *merchant_pub, - const struct GNUNET_HashCode *h_contract_terms, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - uint64_t rtransaction_id, - const struct TALER_ExchangePublicKeyP *exchange_pub, - const struct TALER_ExchangeSignatureP *exchange_sig) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&rtransaction_id), - GNUNET_PQ_query_param_auto_from_type (merchant_pub), - GNUNET_PQ_query_param_auto_from_type (h_contract_terms), - GNUNET_PQ_query_param_auto_from_type (coin_pub), - GNUNET_PQ_query_param_auto_from_type (exchange_sig), - GNUNET_PQ_query_param_auto_from_type (exchange_pub), - GNUNET_PQ_query_param_end - }; - - TALER_LOG_DEBUG ("Inserting refund proof %s + %s\n", - GNUNET_h2s (h_contract_terms), - TALER_B2S (coin_pub)); - check_connection (pg); - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "insert_refund_proof", - params); -} - - -/** * Store information about wire fees charged by an exchange, * including signature (so we have proof). * @@ -5630,6 +5499,53 @@ libtaler_plugin_merchantdb_postgres_init (void *cls) " FROM merchant_instances" " WHERE merchant_id=$1))", 2), + /* for postgres_lookup_refunds_detailed() */ + GNUNET_PQ_make_prepare ("lookup_refunds_detailed", + "SELECT" + " refund_serial" + ",refund_timestamp" + ",coin_pub" + ",merchant_deposits.exchange_url" + ",rtransaction_id" + ",reason" + ",refund_amount_val" + ",refund_amount_frac" + " FROM merchant_refunds" + " JOIN merchant_deposits USING (order_serial, coin_pub)" + " WHERE order_serial=" + " (SELECT order_serial" + " FROM merchant_contract_terms" + " WHERE h_contract_terms=$2" + " AND merchant_serial=" + " (SELECT merchant_serial" + " FROM merchant_instances" + " WHERE merchant_id=$1))", + 2), + /* for postgres_insert_refund_proof() */ + GNUNET_PQ_make_prepare ("insert_refund_proof", + "INSERT INTO merchant_refund_proofs" + "(refund_serial" + ",exchange_sig" + ",refund_fee_val" + ",refund_fee_frac" + ",signkey_serial)" + "SELECT $1, $2, $3, $4, signkey_serial" + " FROM merchant_exchange_signing_keys" + " WHERE exchange_pub=$5" + " ORDER BY start_date DESC" + " LIMIT 1", + 5), + /* for postgres_lookup_refund_proof() */ + GNUNET_PQ_make_prepare ("lookup_refund_proof", + "SELECT" + " merchant_exchange_signing_keys.exchange_pub" + ",exchange_sig" + " FROM merchant_refund_proofs" + " JOIN merchant_exchange_signing_keys" + " USING (signkey_serial)" + " WHERE" + " refund_serial=$1", + 1), /* for postgres_lookup_order_by_fulfillment() */ GNUNET_PQ_make_prepare ("lookup_order_by_fulfillment", "SELECT" @@ -5653,15 +5569,6 @@ libtaler_plugin_merchantdb_postgres_init (void *cls) ",wtid) VALUES " "($1, $2, $3)", 3), - GNUNET_PQ_make_prepare ("insert_proof", - "INSERT INTO merchant_proofs" - "(exchange_url" - ",wtid" - ",execution_time" - ",signkey_pub" - ",proof) VALUES " - "($1, $2, $3, $4, $5)", - 5), GNUNET_PQ_make_prepare ("insert_contract_terms", "INSERT INTO merchant_contract_terms" "(order_id" @@ -5733,43 +5640,6 @@ libtaler_plugin_merchantdb_postgres_init (void *cls) " FROM merchant_refunds" " WHERE coin_pub=$1", 1), - GNUNET_PQ_make_prepare ("find_refunds_from_contract_terms_hash", - "SELECT" - " coin_pub" - ",merchant_deposits.exchange_url" - ",rtransaction_id" - ",refund_amount_val" - ",refund_amount_frac" - ",merchant_deposits.refund_fee_val" - ",merchant_deposits.refund_fee_frac" - ",reason" - " FROM merchant_refunds" - " JOIN merchant_deposits USING (merchant_pub, coin_pub)" - " WHERE merchant_refunds.merchant_pub=$1" - " AND merchant_refunds.h_contract_terms=$2", - 2), - GNUNET_PQ_make_prepare ("get_refund_proof", - "SELECT" - " exchange_pub" - ",exchange_sig" - " FROM merchant_refund_proofs" - " WHERE" - " h_contract_terms=$1" - " AND merchant_pub=$2" - " AND coin_pub=$3" - " AND rtransaction_id=$4", - 4), - GNUNET_PQ_make_prepare ("insert_refund_proof", - "INSERT INTO merchant_refund_proofs" - "(rtransaction_id" - ",merchant_pub" - ",h_contract_terms" - ",coin_pub" - ",exchange_sig" - ",exchange_pub)" - " VALUES " - "($1, $2, $3, $4, $5, $6)", - 6), GNUNET_PQ_make_prepare ("find_deposits", "SELECT" " coin_pub" @@ -6022,12 +5892,11 @@ libtaler_plugin_merchantdb_postgres_init (void *cls) plugin->refund_coin = &postgres_refund_coin; plugin->lookup_order_status = &postgres_lookup_order_status; plugin->increase_refund = &postgres_increase_refund; + plugin->lookup_refunds_detailed = &postgres_lookup_refunds_detailed; + 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; /* OLD API: */ - plugin->find_contract_terms_from_hash = - &postgres_find_contract_terms_from_hash; - plugin->find_paid_contract_terms_from_hash = - &postgres_find_paid_contract_terms_from_hash; 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; @@ -6038,8 +5907,6 @@ libtaler_plugin_merchantdb_postgres_init (void *cls) plugin->find_proof_by_wtid = &postgres_find_proof_by_wtid; plugin->get_authorized_tip_amount = &postgres_get_authorized_tip_amount; plugin->lookup_wire_fee = &postgres_lookup_wire_fee; - plugin->get_refund_proof = &postgres_get_refund_proof; - plugin->put_refund_proof = &postgres_put_refund_proof; plugin->enable_tip_reserve_TR = &postgres_enable_tip_reserve_TR; plugin->authorize_tip_TR = &postgres_authorize_tip_TR; plugin->lookup_tip_by_id = &postgres_lookup_tip_by_id; diff --git a/src/include/taler_merchantdb_plugin.h b/src/include/taler_merchantdb_plugin.h index eb4b272d..6e2f8005 100644 --- a/src/include/taler_merchantdb_plugin.h +++ b/src/include/taler_merchantdb_plugin.h @@ -1146,6 +1146,7 @@ struct TALER_MERCHANTDB_Plugin * * @param cls closure * @param refund_serial serial number of the refund + * @param refund_fee refund fee the exchange said it charged * @param exchange_sig signature from exchange that coin was refunded * @param exchange_pub signing key that was used for @a exchange_sig * @return transaction status @@ -1153,6 +1154,7 @@ struct TALER_MERCHANTDB_Plugin enum GNUNET_DB_QueryStatus (*insert_refund_proof)(void *cls, uint64_t refund_serial, + const struct TALER_Amount *refund_fee, const struct TALER_ExchangeSignatureP *exchange_sig, const struct TALER_ExchangePublicKeyP *exchange_pub); |