summaryrefslogtreecommitdiff
path: root/src/exchange/taler-exchange-httpd_db.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/exchange/taler-exchange-httpd_db.c')
-rw-r--r--src/exchange/taler-exchange-httpd_db.c289
1 files changed, 11 insertions, 278 deletions
diff --git a/src/exchange/taler-exchange-httpd_db.c b/src/exchange/taler-exchange-httpd_db.c
index 298f6c35a..9e95ff40a 100644
--- a/src/exchange/taler-exchange-httpd_db.c
+++ b/src/exchange/taler-exchange-httpd_db.c
@@ -280,279 +280,6 @@ TEH_DB_calculate_transaction_list_totals (struct TALER_EXCHANGEDB_TransactionLis
/**
- * Execute a "/refund". Returns a confirmation that the refund
- * was successful, or a failure if we are not aware of a matching
- * /deposit or if it is too late to do the refund.
- *
- * @param connection the MHD connection to handle
- * @param refund refund details
- * @return MHD result code
- */
-int
-TEH_DB_execute_refund (struct MHD_Connection *connection,
- const struct TALER_EXCHANGEDB_Refund *refund)
-{
- struct TALER_EXCHANGEDB_Session *session;
- struct TALER_EXCHANGEDB_TransactionList *tl;
- struct TALER_EXCHANGEDB_TransactionList *tlp;
- const struct TALER_EXCHANGEDB_Deposit *dep;
- const struct TALER_EXCHANGEDB_Refund *ref;
- struct TEH_KS_StateHandle *mks;
- struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
- struct TALER_Amount expect_fee;
- enum GNUNET_DB_QueryStatus qs;
- int ret;
- int deposit_found;
- int refund_found;
- int done;
- int fee_cmp;
-
- if (NULL == (session = TEH_plugin->get_session (TEH_plugin->cls)))
- {
- GNUNET_break (0);
- return TEH_RESPONSE_reply_internal_db_error (connection,
- TALER_EC_DB_SETUP_FAILED);
- }
- dep = NULL;
- ref = NULL;
- START_TRANSACTION (session, connection);
- tl = TEH_plugin->get_coin_transactions (TEH_plugin->cls,
- session,
- &refund->coin.coin_pub);
- if (NULL == tl)
- {
- TEH_plugin->rollback (TEH_plugin->cls,
- session);
- return TEH_RESPONSE_reply_refund_failure (connection,
- MHD_HTTP_NOT_FOUND,
- TALER_EC_REFUND_COIN_NOT_FOUND);
- }
- deposit_found = GNUNET_NO;
- refund_found = GNUNET_NO;
- for (tlp = tl; NULL != tlp; tlp = tlp->next)
- {
- switch (tlp->type)
- {
- case TALER_EXCHANGEDB_TT_DEPOSIT:
- if (GNUNET_NO == deposit_found)
- {
- if ( (0 == memcmp (&tlp->details.deposit->merchant_pub,
- &refund->merchant_pub,
- sizeof (struct TALER_MerchantPublicKeyP))) &&
- (0 == memcmp (&tlp->details.deposit->h_contract_terms,
- &refund->h_contract_terms,
- sizeof (struct GNUNET_HashCode))) )
- {
- dep = tlp->details.deposit;
- deposit_found = GNUNET_YES;
- break;
- }
- }
- break;
- case TALER_EXCHANGEDB_TT_REFRESH_MELT:
- /* Melts cannot be refunded, ignore here */
- break;
- case TALER_EXCHANGEDB_TT_REFUND:
- if (GNUNET_NO == refund_found)
- {
- /* First, check if existing refund request is identical */
- if ( (0 == memcmp (&tlp->details.refund->merchant_pub,
- &refund->merchant_pub,
- sizeof (struct TALER_MerchantPublicKeyP))) &&
- (0 == memcmp (&tlp->details.refund->h_contract_terms,
- &refund->h_contract_terms,
- sizeof (struct GNUNET_HashCode))) &&
- (tlp->details.refund->rtransaction_id == refund->rtransaction_id) )
- {
- ref = tlp->details.refund;
- refund_found = GNUNET_YES;
- break;
- }
- /* Second, check if existing refund request conflicts */
- if ( (0 == memcmp (&tlp->details.refund->merchant_pub,
- &refund->merchant_pub,
- sizeof (struct TALER_MerchantPublicKeyP))) &&
- (0 == memcmp (&tlp->details.refund->h_contract_terms,
- &refund->h_contract_terms,
- sizeof (struct GNUNET_HashCode))) &&
- (tlp->details.refund->rtransaction_id != refund->rtransaction_id) )
- {
- GNUNET_break_op (0); /* conflicting refund found */
- refund_found = GNUNET_SYSERR;
- /* NOTE: Alternatively we could total up all existing
- refunds and check if the sum still permits the
- refund requested (thus allowing multiple, partial
- refunds). Fow now, we keep it simple. */
- break;
- }
- }
- break;
- case TALER_EXCHANGEDB_TT_PAYBACK:
- /* Paybacks cannot be refunded, ignore here */
- break;
- }
- }
- /* handle if deposit was NOT found */
- if (GNUNET_NO == deposit_found)
- {
- TEH_plugin->rollback (TEH_plugin->cls,
- session);
- TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
- tl);
- return TEH_RESPONSE_reply_transaction_unknown (connection,
- TALER_EC_REFUND_DEPOSIT_NOT_FOUND);
- }
- /* handle if conflicting refund found */
- if (GNUNET_SYSERR == refund_found)
- {
- TEH_plugin->rollback (TEH_plugin->cls,
- session);
- ret = TEH_RESPONSE_reply_refund_conflict (connection,
- tl);
- TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
- tl);
- return ret;
- }
- /* handle if identical refund found */
- if (GNUNET_YES == refund_found)
- {
- /* /refund already done, simply re-transmit confirmation */
- TEH_plugin->rollback (TEH_plugin->cls,
- session);
- ret = TEH_RESPONSE_reply_refund_success (connection,
- ref);
- TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
- tl);
- return ret;
- }
-
- /* check currency is compatible */
- if ( (GNUNET_YES !=
- TALER_amount_cmp_currency (&refund->refund_amount,
- &dep->amount_with_fee)) ||
- (GNUNET_YES !=
- TALER_amount_cmp_currency (&refund->refund_fee,
- &dep->deposit_fee)) )
- {
- GNUNET_break_op (0); /* currency missmatch */
- TEH_plugin->rollback (TEH_plugin->cls,
- session);
- return TEH_RESPONSE_reply_refund_failure (connection,
- MHD_HTTP_PRECONDITION_FAILED,
- TALER_EC_REFUND_CURRENCY_MISSMATCH);
- }
-
- /* check if we already send the money for the /deposit */
- done = TEH_plugin->test_deposit_done (TEH_plugin->cls,
- session,
- dep);
- if (GNUNET_SYSERR == done)
- {
- /* Internal error, we first had the deposit in the history,
- but now it is gone? */
- GNUNET_break (0);
- TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
- tl);
- TEH_plugin->rollback (TEH_plugin->cls,
- session);
- return TEH_RESPONSE_reply_internal_error (connection,
- TALER_EC_REFUND_DB_INCONSISTENT,
- "database inconsistent");
- }
- if (GNUNET_YES == done)
- {
- /* money was already transferred to merchant, can no longer refund */
- TEH_plugin->rollback (TEH_plugin->cls,
- session);
- TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
- tl);
- return TEH_RESPONSE_reply_refund_failure (connection,
- MHD_HTTP_GONE,
- TALER_EC_REFUND_MERCHANT_ALREADY_PAID);
- }
-
- /* check refund amount is sufficiently low */
- if (1 == TALER_amount_cmp (&refund->refund_amount,
- &dep->amount_with_fee) )
- {
- GNUNET_break_op (0); /* cannot refund more than original value */
- TEH_plugin->rollback (TEH_plugin->cls,
- session);
- TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
- tl);
- return TEH_RESPONSE_reply_refund_failure (connection,
- MHD_HTTP_PRECONDITION_FAILED,
- TALER_EC_REFUND_INSUFFICIENT_FUNDS);
- }
-
- /* Check refund fee matches fee of denomination key! */
- mks = TEH_KS_acquire ();
- dki = TEH_KS_denomination_key_lookup (mks,
- &dep->coin.denom_pub,
- TEH_KS_DKU_DEPOSIT);
- if (NULL == dki)
- {
- /* DKI not found, but we do have a coin with this DK in our database;
- not good... */
- GNUNET_break (0);
- TEH_plugin->rollback (TEH_plugin->cls,
- session);
- TEH_KS_release (mks);
- TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
- tl);
- return TEH_RESPONSE_reply_internal_error (connection,
- TALER_EC_REFUND_DENOMINATION_KEY_NOT_FOUND,
- "denomination key not found");
- }
- TALER_amount_ntoh (&expect_fee,
- &dki->issue.properties.fee_refund);
- fee_cmp = TALER_amount_cmp (&refund->refund_fee,
- &expect_fee);
- TEH_KS_release (mks);
-
- if (-1 == fee_cmp)
- {
- TEH_plugin->rollback (TEH_plugin->cls,
- session);
- TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
- tl);
- return TEH_RESPONSE_reply_arg_invalid (connection,
- TALER_EC_REFUND_FEE_TOO_LOW,
- "refund_fee");
- }
- if (1 == fee_cmp)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Refund fee proposed by merchant is higher than necessary.\n");
- }
- TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
- tl);
-
- /* Finally, store new refund data */
- qs = TEH_plugin->insert_refund (TEH_plugin->cls,
- session,
- refund);
- if (GNUNET_DB_STATUS_HARD_ERROR == qs)
- {
- TALER_LOG_WARNING ("Failed to store /refund information in database\n");
- TEH_plugin->rollback (TEH_plugin->cls,
- session);
- return TEH_RESPONSE_reply_internal_db_error (connection,
- TALER_EC_REFUND_STORE_DB_ERROR);
- }
- if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
- {
- /* FIXME: #5010: retry! */
- }
-
- COMMIT_TRANSACTION (session, connection);
-
- return TEH_RESPONSE_reply_refund_success (connection,
- refund);
-}
-
-
-/**
* Parse coin melt requests from a JSON object and write them to
* the database.
*
@@ -581,6 +308,7 @@ refresh_check_melt (struct MHD_Connection *connection,
struct TALER_Amount coin_residual;
struct TALER_Amount spent;
int res;
+ enum GNUNET_DB_QueryStatus qs;
dk = TEH_KS_denomination_key_lookup (key_state,
&coin_details->coin_info.denom_pub,
@@ -597,9 +325,11 @@ refresh_check_melt (struct MHD_Connection *connection,
/* fee for THIS transaction; the melt amount includes the fee! */
spent = coin_details->melt_amount_with_fee;
/* add historic transaction costs of this coin */
- tl = TEH_plugin->get_coin_transactions (TEH_plugin->cls,
+ qs = TEH_plugin->get_coin_transactions (TEH_plugin->cls,
session,
- &coin_details->coin_info.coin_pub);
+ &coin_details->coin_info.coin_pub,
+ &tl);
+ (void) qs; /* FIXME #5010 */
if (GNUNET_OK !=
TEH_DB_calculate_transaction_list_totals (tl,
&spent,
@@ -1921,7 +1651,8 @@ TEH_DB_execute_payback (struct MHD_Connection *connection,
struct TALER_Amount amount;
struct TALER_Amount spent;
struct GNUNET_TIME_Absolute now;
-
+ enum GNUNET_DB_QueryStatus qs;
+
if (NULL == (session = TEH_plugin->get_session (TEH_plugin->cls)))
{
GNUNET_break (0);
@@ -1955,9 +1686,11 @@ TEH_DB_execute_payback (struct MHD_Connection *connection,
}
/* Calculate remaining balance. */
- tl = TEH_plugin->get_coin_transactions (TEH_plugin->cls,
+ qs = TEH_plugin->get_coin_transactions (TEH_plugin->cls,
session,
- &coin->coin_pub);
+ &coin->coin_pub,
+ &tl);
+ (void) qs; /* FIXME #5010 */
TALER_amount_get_zero (value->currency,
&spent);
if (GNUNET_OK !=