diff options
Diffstat (limited to 'src/backend/taler-merchant-httpd_pay.c')
-rw-r--r-- | src/backend/taler-merchant-httpd_pay.c | 121 |
1 files changed, 73 insertions, 48 deletions
diff --git a/src/backend/taler-merchant-httpd_pay.c b/src/backend/taler-merchant-httpd_pay.c index 91860ca2..090ae144 100644 --- a/src/backend/taler-merchant-httpd_pay.c +++ b/src/backend/taler-merchant-httpd_pay.c @@ -1,6 +1,6 @@ /* This file is part of TALER - (C) 2014, 2015, 2016 GNUnet e.V. and INRIA + (C) 2014, 2015, 2016, 2017 GNUnet e.V. and INRIA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software @@ -165,6 +165,34 @@ struct PayContext struct TALER_Amount max_fee; /** + * Maximum wire fee the merchant is willing to pay, from @e root. + * Note that IF the total fee of the exchange is higher, that is + * acceptable to the merchant if the customer is willing to + * pay the amorized difference. Wire fees are charged over an + * aggregate of several translations, hence unlike the deposit + * fees, they are amortized over several customer's transactions. + * The contract specifies under @e wire_fee_amortization how many + * customer's transactions he expects the wire fees to be amortized + * over on average. Thus, if the wire fees are larger than + * @e max_wire_fee, each customer is expected to contribute + * $\frac{actual-wire-fee - max_wire_fee}{wire_fee_amortization}$. + * The customer's contribution may be further reduced by the + * difference between @e max_fee and the sum of the deposit fees. + * + * Default is that the merchant is unwilling to pay any wire fees. + */ + struct TALER_Amount max_wire_fee; + + /** + * Number of transactions that the wire fees are expected to be + * amortized over. Never zero, defaults (conservateively) to 1. + * May be higher if merchants expect many small transactions to + * be aggregated and thus wire fees to be reasonably amortized + * due to aggregation. + */ + uint32_t wire_fee_amortization; + + /** * Amount from @e root. This is the amount the merchant expects * to make, minus @e max_fee. */ @@ -526,11 +554,13 @@ pay_context_cleanup (struct TM_HandlerContext *hc) * * @param cls the `struct PayContext` * @param mh NULL if exchange was not found to be acceptable + * @param wire_fee current applicable fee for dealing with @a mh, NULL if not available * @param exchange_trusted #GNUNET_YES if this exchange is trusted by config */ static void process_pay_with_exchange (void *cls, struct TALER_EXCHANGE_Handle *mh, + const struct TALER_Amount *wire_fee, int exchange_trusted) { struct PayContext *pc = cls; @@ -552,7 +582,6 @@ process_pay_with_exchange (void *cls, return; } pc->mh = mh; - keys = TALER_EXCHANGE_get_keys (mh); if (NULL == keys) { @@ -874,40 +903,13 @@ check_transaction_exists (void *cls, } } + +// FIXME: declare in proper header! extern struct MerchantInstance * get_instance (struct json_t *json); /** - * Just a stub used to double-check if a transaction - * has been correctly inserted into db. - * - * @param cls closure - * @param transaction_id of the contract - * @param merchant's public key - * @param exchange_uri URI of the exchange - * @param h_contract hash of the contract - * @param h_wire hash of our wire details - * @param timestamp time of the confirmation - * @param refund refund deadline - * @param total_amount total amount we receive for the contract after fees - */ -static void -transaction_double_check (void *cls, - const struct TALER_MerchantPublicKeyP *merchant_pub, - const char *exchange_uri, - const struct GNUNET_HashCode *h_proposal_data, - const struct GNUNET_HashCode *h_wire, - struct GNUNET_TIME_Absolute timestamp, - struct GNUNET_TIME_Absolute refund, - const struct TALER_Amount *total_amount) -{ - return; -} - - - -/** * Try to parse the pay request into the given pay context. * * Schedules an error response in the connection on failure. @@ -968,7 +970,7 @@ parse_pay (struct MHD_Connection *connection, GNUNET_JSON_parse_free (spec); if (MHD_YES != TMH_RESPONSE_reply_internal_error (connection, - TALER_EC_NONE, + TALER_EC_PAY_FAILED_COMPUTE_PROPOSAL_HASH, "Can not hash proposal")) { GNUNET_break (0); @@ -984,10 +986,9 @@ parse_pay (struct MHD_Connection *connection, GNUNET_JSON_parse_free (spec); /* invalid contract */ GNUNET_break (0); - // FIXME: define proper EC for this! if (MHD_YES != TMH_RESPONSE_reply_internal_error (connection, - TALER_EC_NONE, + TALER_EC_PAY_MERCHANT_FIELD_MISSING, "No merchant field in contract")) { GNUNET_break (0); @@ -1015,12 +1016,10 @@ parse_pay (struct MHD_Connection *connection, GNUNET_log (GNUNET_ERROR_TYPE_INFO, "/pay: picked instance %s with key %s\n", pc->mi->id, - GNUNET_STRINGS_data_to_string_alloc (&pc->mi->pubkey, sizeof (pc->mi->pubkey))); + GNUNET_STRINGS_data_to_string_alloc (&pc->mi->pubkey, + sizeof (pc->mi->pubkey))); pc->chosen_exchange = GNUNET_strdup (chosen_exchange); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Parsed JSON for /pay.\n"); - { struct GNUNET_JSON_Specification espec[] = { GNUNET_JSON_spec_absolute_time ("refund_deadline", @@ -1060,9 +1059,42 @@ parse_pay (struct MHD_Connection *connection, } } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "parsed timestamps\n"); + /* parse optional details */ + { + struct GNUNET_JSON_Specification espec[] = { + TALER_JSON_spec_amount ("max_wire_fee", + &pc->max_wire_fee), + GNUNET_JSON_spec_end() + }; + + res = TMH_PARSE_json_data (connection, + pc->proposal_data, + espec); + if (GNUNET_YES != res) + { + /* default is we cover no fee */ + GNUNET_assert (GNUNET_OK == + TALER_amount_get_zero (pc->max_fee.currency, + &pc->max_wire_fee)); + } + } + { + struct GNUNET_JSON_Specification espec[] = { + GNUNET_JSON_spec_uint32 ("wire_fee_amortization", + &pc->wire_fee_amortization), + GNUNET_JSON_spec_end() + }; + res = TMH_PARSE_json_data (connection, + pc->proposal_data, + espec); + if ( (GNUNET_YES != res) || + (0 == pc->wire_fee_amortization) ) + { + /* default is no amortization */ + pc->wire_fee_amortization = 1; + } + } pc->coins_cnt = json_array_size (coins); if (0 == pc->coins_cnt) @@ -1140,8 +1172,6 @@ handler_pay_json (struct MHD_Connection *connection, if (GNUNET_OK != ret) return ret; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "parsed '/pay' body\n"); - /* Check if this payment attempt has already succeeded */ if (GNUNET_SYSERR == db->find_payments (db->cls, @@ -1232,18 +1262,13 @@ handler_pay_json (struct MHD_Connection *connection, TALER_EC_PAY_DB_STORE_TRANSACTION_ERROR, "Merchant database error"); } - if (GNUNET_OK != db->find_transaction (db->cls, - &pc->h_proposal_data, - &pc->mi->pubkey, - &transaction_double_check, - NULL)) - GNUNET_break (0); } MHD_suspend_connection (connection); /* Find the responsible exchange, this may take a while... */ pc->fo = TMH_EXCHANGES_find_exchange (pc->chosen_exchange, + NULL, /* FIXME: wire method! */ &process_pay_with_exchange, pc); |