summaryrefslogtreecommitdiff
path: root/src/exchange/taler-exchange-httpd_transfers_get.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/exchange/taler-exchange-httpd_transfers_get.c')
-rw-r--r--src/exchange/taler-exchange-httpd_transfers_get.c222
1 files changed, 162 insertions, 60 deletions
diff --git a/src/exchange/taler-exchange-httpd_transfers_get.c b/src/exchange/taler-exchange-httpd_transfers_get.c
index e63acdc2a..18d96f955 100644
--- a/src/exchange/taler-exchange-httpd_transfers_get.c
+++ b/src/exchange/taler-exchange-httpd_transfers_get.c
@@ -51,7 +51,7 @@ struct AggregatedDepositDetail
/**
* Hash of the contract terms.
*/
- struct TALER_PrivateContractHash h_contract_terms;
+ struct TALER_PrivateContractHashP h_contract_terms;
/**
* Coin's public key of the deposited coin.
@@ -59,14 +59,20 @@ struct AggregatedDepositDetail
struct TALER_CoinSpendPublicKeyP coin_pub;
/**
- * Total value of the coin in the deposit.
+ * Total value of the coin in the deposit (after
+ * refunds).
*/
struct TALER_Amount deposit_value;
/**
- * Fees charged by the exchange for the deposit of this coin.
+ * Fees charged by the exchange for the deposit of this coin (possibly after reduction due to refunds).
*/
struct TALER_Amount deposit_fee;
+
+ /**
+ * Total amount refunded for this coin.
+ */
+ struct TALER_Amount refund_total;
};
@@ -89,17 +95,16 @@ reply_transfer_details (struct MHD_Connection *connection,
const struct TALER_MerchantPublicKeyP *merchant_pub,
const char *payto_uri,
const struct TALER_Amount *wire_fee,
- struct GNUNET_TIME_Absolute exec_time,
+ struct GNUNET_TIME_Timestamp exec_time,
const struct AggregatedDepositDetail *wdd_head)
{
json_t *deposits;
- struct TALER_WireDepositDetailP dd;
struct GNUNET_HashContext *hash_context;
- struct TALER_WireDepositDataPS wdp;
+ struct GNUNET_HashCode h_details;
struct TALER_ExchangePublicKeyP pub;
struct TALER_ExchangeSignatureP sig;
+ struct TALER_PaytoHashP h_payto;
- GNUNET_TIME_round_abs (&exec_time);
deposits = json_array ();
GNUNET_assert (NULL != deposits);
hash_context = GNUNET_CRYPTO_hash_context_start ();
@@ -107,16 +112,12 @@ reply_transfer_details (struct MHD_Connection *connection,
NULL != wdd_pos;
wdd_pos = wdd_pos->next)
{
- dd.h_contract_terms = wdd_pos->h_contract_terms;
- dd.execution_time = GNUNET_TIME_absolute_hton (exec_time);
- dd.coin_pub = wdd_pos->coin_pub;
- TALER_amount_hton (&dd.deposit_value,
- &wdd_pos->deposit_value);
- TALER_amount_hton (&dd.deposit_fee,
- &wdd_pos->deposit_fee);
- GNUNET_CRYPTO_hash_context_read (hash_context,
- &dd,
- sizeof (struct TALER_WireDepositDetailP));
+ TALER_exchange_online_wire_deposit_append (hash_context,
+ &wdd_pos->h_contract_terms,
+ exec_time,
+ &wdd_pos->coin_pub,
+ &wdd_pos->deposit_value,
+ &wdd_pos->deposit_fee);
if (0 !=
json_array_append_new (
deposits,
@@ -125,6 +126,13 @@ reply_transfer_details (struct MHD_Connection *connection,
&wdd_pos->h_contract_terms),
GNUNET_JSON_pack_data_auto ("coin_pub",
&wdd_pos->coin_pub),
+
+ GNUNET_JSON_pack_allow_null (
+ TALER_JSON_pack_amount ("refund_total",
+ TALER_amount_is_zero (
+ &wdd_pos->refund_total)
+ ? NULL
+ : &wdd_pos->refund_total)),
TALER_JSON_pack_amount ("deposit_value",
&wdd_pos->deposit_value),
TALER_JSON_pack_amount ("deposit_fee",
@@ -138,24 +146,21 @@ reply_transfer_details (struct MHD_Connection *connection,
"json_array_append_new() failed");
}
}
- wdp.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT);
- wdp.purpose.size = htonl (sizeof (struct TALER_WireDepositDataPS));
- TALER_amount_hton (&wdp.total,
- total);
- TALER_amount_hton (&wdp.wire_fee,
- wire_fee);
- wdp.merchant_pub = *merchant_pub;
- TALER_payto_hash (payto_uri,
- &wdp.h_payto);
GNUNET_CRYPTO_hash_context_finish (hash_context,
- &wdp.h_details);
+ &h_details);
{
enum TALER_ErrorCode ec;
if (TALER_EC_NONE !=
- (ec = TEH_keys_exchange_sign (&wdp,
- &pub,
- &sig)))
+ (ec = TALER_exchange_online_wire_deposit_sign (
+ &TEH_keys_exchange_sign_,
+ total,
+ wire_fee,
+ merchant_pub,
+ payto_uri,
+ &h_details,
+ &pub,
+ &sig)))
{
json_decref (deposits);
return TALER_MHD_reply_with_ec (connection,
@@ -164,6 +169,8 @@ reply_transfer_details (struct MHD_Connection *connection,
}
}
+ TALER_payto_hash (payto_uri,
+ &h_payto);
return TALER_MHD_REPLY_JSON_PACK (
connection,
MHD_HTTP_OK,
@@ -174,9 +181,9 @@ reply_transfer_details (struct MHD_Connection *connection,
GNUNET_JSON_pack_data_auto ("merchant_pub",
merchant_pub),
GNUNET_JSON_pack_data_auto ("h_payto",
- &wdp.h_payto),
- GNUNET_JSON_pack_time_abs ("execution_time",
- exec_time),
+ &h_payto),
+ GNUNET_JSON_pack_timestamp ("execution_time",
+ exec_time),
GNUNET_JSON_pack_array_steal ("deposits",
deposits),
GNUNET_JSON_pack_data_auto ("exchange_sig",
@@ -212,14 +219,14 @@ struct WtidTransactionContext
struct TALER_MerchantPublicKeyP merchant_pub;
/**
- * Wire fee applicable at @e exec_time.
+ * Wire fees applicable at @e exec_time.
*/
- struct TALER_Amount wire_fee;
+ struct TALER_WireFeeSet fees;
/**
* Execution time of the wire transfer
*/
- struct GNUNET_TIME_Absolute exec_time;
+ struct GNUNET_TIME_Timestamp exec_time;
/**
* Head of DLL with deposit details for transfers GET response.
@@ -254,6 +261,31 @@ struct WtidTransactionContext
/**
+ * Callback that totals up the applicable refunds.
+ *
+ * @param cls a `struct TALER_Amount` where we keep the total
+ * @param amount_with_fee amount being refunded
+ */
+static enum GNUNET_GenericReturnValue
+add_refunds (void *cls,
+ const struct TALER_Amount *amount_with_fee)
+
+{
+ struct TALER_Amount *total = cls;
+
+ if (0 >
+ TALER_amount_add (total,
+ total,
+ amount_with_fee))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+
+/**
* Function called with the results of the lookup of the individual deposits
* that were aggregated for the given wire transfer.
*
@@ -261,31 +293,101 @@ struct WtidTransactionContext
* @param rowid which row in the DB is the information from (for diagnostics), ignored
* @param merchant_pub public key of the merchant (should be same for all callbacks with the same @e cls)
* @param account_payto_uri where the funds were sent
+ * @param h_payto hash over @a account_payto_uri as it is in the DB
* @param exec_time execution time of the wire transfer (should be same for all callbacks with the same @e cls)
* @param h_contract_terms which proposal was this payment about
* @param denom_pub denomination public key of the @a coin_pub (ignored)
* @param coin_pub which public key was this payment about
- * @param deposit_value amount contributed by this coin in total
+ * @param deposit_value amount contributed by this coin in total (including fee)
* @param deposit_fee deposit fee charged by exchange for this coin
*/
static void
-handle_deposit_data (void *cls,
- uint64_t rowid,
- const struct TALER_MerchantPublicKeyP *merchant_pub,
- const char *account_payto_uri,
- struct GNUNET_TIME_Absolute exec_time,
- const struct TALER_PrivateContractHash *h_contract_terms,
- const struct TALER_DenominationPublicKey *denom_pub,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- const struct TALER_Amount *deposit_value,
- const struct TALER_Amount *deposit_fee)
+handle_deposit_data (
+ void *cls,
+ uint64_t rowid,
+ const struct TALER_MerchantPublicKeyP *merchant_pub,
+ const char *account_payto_uri,
+ const struct TALER_PaytoHashP *h_payto,
+ struct GNUNET_TIME_Timestamp exec_time,
+ const struct TALER_PrivateContractHashP *h_contract_terms,
+ const struct TALER_DenominationPublicKey *denom_pub,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ const struct TALER_Amount *deposit_value,
+ const struct TALER_Amount *deposit_fee)
{
struct WtidTransactionContext *ctx = cls;
+ struct TALER_Amount total_refunds;
+ struct TALER_Amount dval;
+ struct TALER_Amount dfee;
+ enum GNUNET_DB_QueryStatus qs;
(void) rowid;
(void) denom_pub;
+ (void) h_payto;
if (GNUNET_SYSERR == ctx->is_valid)
return;
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (deposit_value->currency,
+ &total_refunds));
+ qs = TEH_plugin->select_refunds_by_coin (TEH_plugin->cls,
+ coin_pub,
+ merchant_pub,
+ h_contract_terms,
+ &add_refunds,
+ &total_refunds);
+ if (qs < 0)
+ {
+ GNUNET_break (0);
+ ctx->is_valid = GNUNET_SYSERR;
+ return;
+ }
+ if (1 ==
+ TALER_amount_cmp (&total_refunds,
+ deposit_value))
+ {
+ /* Refunds exceeded total deposit? not OK! */
+ GNUNET_break (0);
+ ctx->is_valid = GNUNET_SYSERR;
+ return;
+ }
+ if (0 ==
+ TALER_amount_cmp (&total_refunds,
+ deposit_value))
+ {
+ /* total_refunds == deposit_value;
+ in this case, the total contributed to the
+ wire transfer is zero (as are fees) */
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (deposit_value->currency,
+ &dval));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (deposit_value->currency,
+ &dfee));
+
+ }
+ else
+ {
+ /* Compute deposit value by subtracting refunds */
+ GNUNET_assert (0 <
+ TALER_amount_subtract (&dval,
+ deposit_value,
+ &total_refunds));
+ if (-1 ==
+ TALER_amount_cmp (&dval,
+ deposit_fee))
+ {
+ /* dval < deposit_fee, so after refunds less than
+ the deposit fee remains; reduce deposit fee to
+ the remaining value of the coin */
+ dfee = dval;
+ }
+ else
+ {
+ /* Partial refund, deposit fee remains */
+ dfee = *deposit_fee;
+ }
+ }
+
if (GNUNET_NO == ctx->is_valid)
{
/* First one we encounter, setup general information in 'ctx' */
@@ -295,8 +397,8 @@ handle_deposit_data (void *cls,
ctx->is_valid = GNUNET_YES;
if (0 >
TALER_amount_subtract (&ctx->total,
- deposit_value,
- deposit_fee))
+ &dval,
+ &dfee))
{
GNUNET_break (0);
ctx->is_valid = GNUNET_SYSERR;
@@ -320,8 +422,8 @@ handle_deposit_data (void *cls,
}
if (0 >
TALER_amount_subtract (&delta,
- deposit_value,
- deposit_fee))
+ &dval,
+ &dfee))
{
GNUNET_break (0);
ctx->is_valid = GNUNET_SYSERR;
@@ -342,8 +444,9 @@ handle_deposit_data (void *cls,
struct AggregatedDepositDetail *wdd;
wdd = GNUNET_new (struct AggregatedDepositDetail);
- wdd->deposit_value = *deposit_value;
- wdd->deposit_fee = *deposit_fee;
+ wdd->deposit_value = dval;
+ wdd->deposit_fee = dfee;
+ wdd->refund_total = total_refunds;
wdd->h_contract_terms = *h_contract_terms;
wdd->coin_pub = *coin_pub;
GNUNET_CONTAINER_DLL_insert (ctx->wdd_head,
@@ -397,10 +500,9 @@ get_transfer_deposits (void *cls,
{
struct WtidTransactionContext *ctx = cls;
enum GNUNET_DB_QueryStatus qs;
- struct GNUNET_TIME_Absolute wire_fee_start_date;
- struct GNUNET_TIME_Absolute wire_fee_end_date;
+ struct GNUNET_TIME_Timestamp wire_fee_start_date;
+ struct GNUNET_TIME_Timestamp wire_fee_end_date;
struct TALER_MasterSignatureP wire_fee_master_sig;
- struct TALER_Amount closing_fee;
/* resetting to NULL/0 in case transaction was repeated after
serialization failure */
@@ -456,8 +558,7 @@ get_transfer_deposits (void *cls,
ctx->exec_time,
&wire_fee_start_date,
&wire_fee_end_date,
- &ctx->wire_fee,
- &closing_fee,
+ &ctx->fees,
&wire_fee_master_sig);
GNUNET_free (wire_method);
}
@@ -477,7 +578,7 @@ get_transfer_deposits (void *cls,
if (0 >
TALER_amount_subtract (&ctx->total,
&ctx->total,
- &ctx->wire_fee))
+ &ctx->fees.wire))
{
GNUNET_break (0);
*mhd_ret = TALER_MHD_reply_with_error (connection,
@@ -515,6 +616,7 @@ TEH_handler_transfers_get (struct TEH_RequestContext *rc,
if (GNUNET_OK !=
TEH_DB_run_transaction (rc->connection,
"run transfers GET",
+ TEH_MT_REQUEST_OTHER,
&mhd_ret,
&get_transfer_deposits,
&ctx))
@@ -526,7 +628,7 @@ TEH_handler_transfers_get (struct TEH_RequestContext *rc,
&ctx.total,
&ctx.merchant_pub,
ctx.payto_uri,
- &ctx.wire_fee,
+ &ctx.fees.wire,
ctx.exec_time,
ctx.wdd_head);
free_ctx (&ctx);