From d17e571f782a6c9c178f8aa6232524af867eb1cb Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 4 Apr 2020 13:35:32 +0200 Subject: update to latest exchange API, some better error handling --- src/backend/taler-merchant-httpd_exchanges.c | 253 +++++++++++++-------- src/backend/taler-merchant-httpd_exchanges.h | 11 +- src/backend/taler-merchant-httpd_order.c | 2 +- src/backend/taler-merchant-httpd_pay.c | 9 +- src/backend/taler-merchant-httpd_tip-pickup.c | 9 +- .../taler-merchant-httpd_tip-reserve-helper.c | 9 +- .../taler-merchant-httpd_track-transaction.c | 19 +- src/backend/taler-merchant-httpd_track-transfer.c | 9 +- 8 files changed, 214 insertions(+), 107 deletions(-) diff --git a/src/backend/taler-merchant-httpd_exchanges.c b/src/backend/taler-merchant-httpd_exchanges.c index ac899c12..a9871519 100644 --- a/src/backend/taler-merchant-httpd_exchanges.c +++ b/src/backend/taler-merchant-httpd_exchanges.c @@ -1,6 +1,6 @@ /* This file is part of TALER - (C) 2014-2018 Taler Systems SA + (C) 2014-2020 Taler Systems SA 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 @@ -87,7 +87,7 @@ struct TMH_EXCHANGES_FindOperation struct Exchange *my_exchange; /** - * Wire method we care about for fees. + * Wire method we care about for fees, NULL if we do not care about wire fees. */ char *wire_method; @@ -196,6 +196,11 @@ struct Exchange */ struct GNUNET_TIME_Relative retry_delay; + /** + * How long should we wait between the next retry for /wire? + */ + struct GNUNET_TIME_Relative wire_retry_delay; + /** * Task where we retry fetching /keys from the exchange. */ @@ -242,7 +247,7 @@ static struct Exchange *exchange_tail; /** * List of our trusted exchanges for inclusion in contracts. */ -json_t *trusted_exchanges; +json_t *TMH_trusted_exchanges; /** @@ -259,11 +264,17 @@ json_t *trusted_exchanges; * @param keys information about the various keys used * by the exchange * @param compat version compatibility data + * @param ec error code, #TALER_EC_NONE on success + * @param http_status status returned by /keys, #MHD_HTTP_OK on success + * @param full_reply JSON body of /keys request, NULL if reply was not in JSON */ static void keys_mgmt_cb (void *cls, const struct TALER_EXCHANGE_Keys *keys, - enum TALER_EXCHANGE_VersionCompatibility compat); + enum TALER_EXCHANGE_VersionCompatibility compat, + enum TALER_ErrorCode ec, + unsigned int http_status, + const json_t *full_reply); /** @@ -305,9 +316,9 @@ retry_exchange (void *cls) * @param cls closure * @param wire_method name of the wire method (i.e. "sepa") * @param fees fee structure for this method - * @return #GNUNET_OK on success + * @return #TALER_EC_NONE on success */ -static int +static enum TALER_ErrorCode process_wire_fees (struct Exchange *exchange, const struct TALER_MasterPublicKeyP *master_pub, const char *wire_method, @@ -341,7 +352,7 @@ process_wire_fees (struct Exchange *exchange, { /* Hole in the fee structure, not allowed! */ GNUNET_break_op (0); - return GNUNET_SYSERR; + return TALER_EC_HOLE_IN_WIRE_FEE_STRUCTURE; } while (NULL != fees) { @@ -365,9 +376,10 @@ process_wire_fees (struct Exchange *exchange, "store wire fee")) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to start database transaction!\n"); + "Failed to start database transaction to store exchange wire fees (will try to continue anyway)!\n"); GNUNET_free (af); - return GNUNET_SYSERR; + fees = fees->next; + continue; } qs = db->store_wire_fee_by_exchange (db->cls, master_pub, @@ -380,7 +392,7 @@ process_wire_fees (struct Exchange *exchange, if (0 > qs) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to persist exchange wire fees in merchant DB!\n"); + "Failed to persist exchange wire fees in merchant DB (will try to continue anyway)!\n"); GNUNET_free (af); fees = fees->next; db->rollback (db->cls); @@ -389,7 +401,7 @@ process_wire_fees (struct Exchange *exchange, if (0 == qs) { /* Entry was already in DB, fine, continue as if we had succeeded */ - GNUNET_log (GNUNET_ERROR_TYPE_INFO, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Fees already in DB, rolling back transaction attempt!\n"); db->rollback (db->cls); } @@ -400,13 +412,12 @@ process_wire_fees (struct Exchange *exchange, if (0 > qs) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to persist exchange wire fees in merchant DB!\n"); + "Failed to persist exchange wire fees in merchant DB (will try to continue anyway)!\n"); GNUNET_free (af); fees = fees->next; continue; } } - af->next = NULL; if (NULL == endp) f->af = af; @@ -415,7 +426,7 @@ process_wire_fees (struct Exchange *exchange, endp = af; fees = fees->next; } - return GNUNET_OK; + return TALER_EC_NONE; } @@ -428,9 +439,9 @@ process_wire_fees (struct Exchange *exchange, * @param master_pub public key of the exchange * @param accounts_len length of the @a accounts array * @param accounts list of wire accounts of the exchange - * @return #GNUNET_OK on success + * @return #TALER_EC_NONE on success */ -static int +static enum TALER_ErrorCode process_wire_accounts (struct Exchange *exchange, const struct TALER_MasterPublicKeyP *master_pub, unsigned int accounts_len, @@ -438,23 +449,25 @@ process_wire_accounts (struct Exchange *exchange, { for (unsigned int i = 0; ifo_head, - exchange->fo_tail, - fo); fo->fc (fo->fc_cls, exchange->conn, wire_fee, - exchange->trusted); - GNUNET_free_non_null (fo->wire_method); - if (NULL != fo->at) - { - GNUNET_SCHEDULER_cancel (fo->at); - fo->at = NULL; - } - GNUNET_free (fo); + exchange->trusted, + TALER_EC_NONE, + MHD_HTTP_OK, + NULL); + TMH_EXCHANGES_find_exchange_cancel (fo); } return need_wire; } @@ -585,39 +592,59 @@ wire_task_cb (void *cls); * If the request fails to generate a valid response from the * exchange, @a http_status will also be zero. * + * Must only be called if 'exchange->pending' is #GNUNET_NO, + * that is #TALER_EXCHANGE_get_keys() will succeed. + * * @param cls closure, a `struct Exchange` * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful request; * 0 if the exchange's reply is bogus (fails to follow the protocol) * @param ec taler-specific error code, #TALER_EC_NONE on success * @param accounts_len length of the @a accounts array * @param accounts list of wire accounts of the exchange, NULL on error + * @param full_reply the complete response from the exchange (if it was in JSON) */ static void handle_wire_data (void *cls, unsigned int http_status, enum TALER_ErrorCode ec, unsigned int accounts_len, - const struct TALER_EXCHANGE_WireAccount *accounts) + const struct TALER_EXCHANGE_WireAccount *accounts, + const json_t *full_reply) { struct Exchange *exchange = cls; const struct TALER_EXCHANGE_Keys *keys; + enum TALER_ErrorCode ecx; exchange->wire_request = NULL; if (MHD_HTTP_OK != http_status) { + struct TMH_EXCHANGES_FindOperation *fo; + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Failed to obtain /wire details from `%s': %d\n", + "Failed to obtain /wire details from `%s': %u/%d\n", exchange->url, + http_status, ec); + while (NULL != (fo = exchange->fo_head)) + { + fo->fc (fo->fc_cls, + NULL, + NULL, + GNUNET_NO, + ec, + http_status, + full_reply); + TMH_EXCHANGES_find_exchange_cancel (fo); + } return; } keys = TALER_EXCHANGE_get_keys (exchange->conn); - if ( (NULL == keys) || - (GNUNET_OK != - process_wire_accounts (exchange, + GNUNET_assert (NULL != keys); + ecx = process_wire_accounts (exchange, &keys->master_pub, accounts_len, - accounts)) ) + accounts); + if (TALER_EC_NONE != ecx) { /* Report hard failure to all callbacks! */ struct TMH_EXCHANGES_FindOperation *fo; @@ -625,39 +652,38 @@ handle_wire_data (void *cls, GNUNET_break_op (0); while (NULL != (fo = exchange->fo_head)) { - GNUNET_CONTAINER_DLL_remove (exchange->fo_head, - exchange->fo_tail, - fo); - /* TODO: report more precise error, this ultimately generates - "exchange not supported" instead of "exchange violated - protocol"; we should ideally generate a reply with - a specific TALER_EC-code, boxing 'obj' within it. */ fo->fc (fo->fc_cls, NULL, NULL, - GNUNET_NO); - GNUNET_free_non_null (fo->wire_method); - if (NULL != fo->at) - { - GNUNET_SCHEDULER_cancel (fo->at); - fo->at = NULL; - } - GNUNET_free (fo); + GNUNET_NO, + ecx, + 0, + full_reply); + TMH_EXCHANGES_find_exchange_cancel (fo); } return; } - if (GNUNET_YES == - process_find_operations (exchange)) + if ( (GNUNET_YES == + process_find_operations (exchange)) && + (NULL == exchange->wire_task) && + (NULL == exchange->wire_request) ) { - /* need to run /wire again, with some delay */ - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Do not have sufficient wire data. Will re-request /wire in 1 minute\n"); - - GNUNET_assert (NULL == exchange->wire_task); - exchange->wire_task = GNUNET_SCHEDULER_add_delayed ( + /* need to run /wire again. But as we DID get a successful reply, + and as the exchange is unlikely to offer new wire methods very + frequently, start with some significant delay */ + exchange->wire_retry_delay = GNUNET_TIME_relative_max ( GNUNET_TIME_UNIT_MINUTES, - &wire_task_cb, - exchange); + exchange->wire_retry_delay); + exchange->wire_retry_delay = RETRY_BACKOFF (exchange->wire_retry_delay); + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Exchange does not support our wire method. Retrying in %s\n", + GNUNET_STRINGS_relative_time_to_string ( + exchange->wire_retry_delay, + GNUNET_YES)); + exchange->wire_task + = GNUNET_SCHEDULER_add_delayed (exchange->wire_retry_delay, + &wire_task_cb, + exchange); } } @@ -668,6 +694,9 @@ handle_wire_data (void *cls, * the callback. If requests without /wire data remain, * retry the /wire request after some delay. * + * Must only be called if 'exchange->pending' is #GNUNET_NO, + * that is #TALER_EXCHANGE_get_keys() will succeed. + * * @param cls a `struct Exchange` to check */ static void @@ -676,6 +705,7 @@ wire_task_cb (void *cls) struct Exchange *exchange = cls; exchange->wire_task = NULL; + GNUNET_assert (GNUNET_NO == exchange->pending); if (GNUNET_YES != process_find_operations (exchange)) return; /* no more need */ @@ -700,11 +730,17 @@ wire_task_cb (void *cls) * @param keys information about the various keys used * by the exchange * @param compat version compatibility data + * @param ec error code, #TALER_EC_NONE on success + * @param http_status status returned by /keys, #MHD_HTTP_OK on success + * @param full_reply JSON body of /keys request, NULL if reply was not in JSON */ static void keys_mgmt_cb (void *cls, const struct TALER_EXCHANGE_Keys *keys, - enum TALER_EXCHANGE_VersionCompatibility compat) + enum TALER_EXCHANGE_VersionCompatibility compat, + enum TALER_ErrorCode ec, + unsigned int http_status, + const json_t *full_reply) { struct Exchange *exchange = cls; struct GNUNET_TIME_Absolute expire; @@ -712,6 +748,8 @@ keys_mgmt_cb (void *cls, if (NULL == keys) { + struct TMH_EXCHANGES_FindOperation *fo; + exchange->pending = GNUNET_YES; if (NULL != exchange->wire_request) { @@ -723,18 +761,35 @@ keys_mgmt_cb (void *cls, GNUNET_SCHEDULER_cancel (exchange->wire_task); exchange->wire_task = NULL; } + while (NULL != (fo = exchange->fo_head)) + { + fo->fc (fo->fc_cls, + NULL, + NULL, + GNUNET_NO, + ec, + http_status, + full_reply); + TMH_EXCHANGES_find_exchange_cancel (fo); + } if (TALER_EXCHANGE_VC_INCOMPATIBLE_NEWER == compat) { - /* Give up, log hard error. */ + /* Log hard error: we likely need admin help! */ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Exchange `%s' runs an incompatible more recent version of the Taler protocol. Will not retry. This client may need to be updated.\n", exchange->url); - return; + /* Theoretically, the exchange could downgrade, + but let's not be too aggressive about retries + on this one. */ + exchange->retry_delay = GNUNET_TIME_relative_max (GNUNET_TIME_UNIT_HOURS, + exchange->retry_delay); } exchange->retry_delay = RETRY_BACKOFF (exchange->retry_delay); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Failed to fetch /keys from `%s', retrying in %s\n", + "Failed to fetch /keys from `%s': %d/%u, retrying in %s\n", exchange->url, + (int) ec, + http_status, GNUNET_STRINGS_relative_time_to_string (exchange->retry_delay, GNUNET_YES)); GNUNET_assert (NULL == exchange->retry_task); @@ -743,6 +798,19 @@ keys_mgmt_cb (void *cls, exchange); return; } + if ( (GNUNET_YES == exchange->trusted) && + (0 != GNUNET_memcmp (&exchange->master_pub, + &keys->master_pub)) ) + { + /* master pub differs => do not trust the exchange (without auditor) */ + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Master public key of exchange `%s' differs from our configuration. Not trusting exchange.\n", + exchange->url); + exchange->trusted = GNUNET_NO; + } + if (GNUNET_NO == exchange->trusted) + exchange->master_pub = keys->master_pub; + if (0 != (TALER_EXCHANGE_VC_NEWER & compat)) { /* Warn user exactly once about need to upgrade */ @@ -763,8 +831,7 @@ keys_mgmt_cb (void *cls, delay = RELOAD_DELAY; else delay = GNUNET_TIME_absolute_get_remaining (expire); - exchange->retry_delay - = GNUNET_TIME_UNIT_ZERO; + exchange->retry_delay = GNUNET_TIME_UNIT_ZERO; if (NULL != exchange->retry_task) GNUNET_SCHEDULER_cancel (exchange->retry_task); exchange->retry_task @@ -772,13 +839,13 @@ keys_mgmt_cb (void *cls, &retry_exchange, exchange); exchange->pending = GNUNET_NO; - if (GNUNET_YES == - process_find_operations (exchange)) + if ( (GNUNET_YES == + process_find_operations (exchange)) && + (NULL == exchange->wire_request) && + (NULL == exchange->wire_task) ) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Got key data, but do not have current wire data. Will request /wire now\n"); - GNUNET_assert (NULL == exchange->wire_request); - GNUNET_assert (NULL == exchange->wire_task); + "Got key data, but also need wire data. Will request /wire now\n"); exchange->wire_request = TALER_EXCHANGE_wire (exchange->conn, &handle_wire_data, exchange); @@ -840,27 +907,25 @@ TMH_EXCHANGES_find_exchange (const char *chosen_exchange, GNUNET_break (0); return NULL; } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to find chosen exchange `%s'\n", chosen_exchange); - /* Check if the exchange is known */ for (exchange = exchange_head; NULL != exchange; exchange = exchange->next) - /* test it by checking public key --- FIXME: hostname or public key!? - Should probably be URL, not hostname anyway! */ { + /* test it by checking URL */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Comparing chosen exchange url '%s' with known url '%s'.\n", + chosen_exchange, + exchange->url); if (0 == strcmp (exchange->url, chosen_exchange)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "The exchange `%s' is already known\n", + "The exchange `%s' is already known (good)\n", chosen_exchange); break; } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Comparing chosen exchange url '%s' with known url '%s'.\n", - chosen_exchange, exchange->url); } if (NULL == exchange) { @@ -901,13 +966,13 @@ TMH_EXCHANGES_find_exchange (const char *chosen_exchange, return fo; } - /* If new or resumed, retry fetching /keys */ + /* If new or resumed, (re)try fetching /keys */ if ( (NULL == exchange->conn) && + (NULL == exchange->retry_task) && (GNUNET_YES == exchange->pending) ) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Do not have current key data. Will request /keys now\n"); - GNUNET_assert (NULL == exchange->retry_task); exchange->retry_task = GNUNET_SCHEDULER_add_now (&retry_exchange, exchange); } @@ -916,7 +981,7 @@ TMH_EXCHANGES_find_exchange (const char *chosen_exchange, (NULL == exchange->wire_request) ) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Do not have current wire data. Will re-request /wire now\n"); + "Do not have required wire data. Will re-request /wire now\n"); exchange->wire_task = GNUNET_SCHEDULER_add_now (&wire_task_cb, exchange); } @@ -1007,7 +1072,7 @@ accept_exchanges (void *cls, else { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "MASTER_KEY not given in section '%s', not trusting exchange\n", + "MASTER_KEY missing in section '%s', not trusting exchange\n", section); } @@ -1047,7 +1112,7 @@ TMH_EXCHANGES_init (const struct GNUNET_CONFIGURATION_Handle *cfg) &accept_exchanges, (void *) cfg); /* build JSON with list of trusted exchanges (will be included in contracts) */ - trusted_exchanges = json_array (); + TMH_trusted_exchanges = json_array (); for (struct Exchange *exchange = exchange_head; NULL != exchange; exchange = exchange->next) @@ -1061,7 +1126,7 @@ TMH_EXCHANGES_init (const struct GNUNET_CONFIGURATION_Handle *cfg) "master_pub", GNUNET_JSON_from_data_auto ( &exchange->master_pub)); GNUNET_assert (0 == - json_array_append_new (trusted_exchanges, + json_array_append_new (TMH_trusted_exchanges, j_exchange)); } return GNUNET_OK; @@ -1125,8 +1190,8 @@ TMH_EXCHANGES_done () merchant_curl_ctx = NULL; GNUNET_CURL_gnunet_rc_destroy (merchant_curl_rc); merchant_curl_rc = NULL; - json_decref (trusted_exchanges); - trusted_exchanges = NULL; + json_decref (TMH_trusted_exchanges); + TMH_trusted_exchanges = NULL; } diff --git a/src/backend/taler-merchant-httpd_exchanges.h b/src/backend/taler-merchant-httpd_exchanges.h index 7523e840..61a5c79f 100644 --- a/src/backend/taler-merchant-httpd_exchanges.h +++ b/src/backend/taler-merchant-httpd_exchanges.h @@ -33,7 +33,7 @@ /** * List of our trusted exchanges in JSON format for inclusion in contracts. */ -extern json_t *trusted_exchanges; +extern json_t *TMH_trusted_exchanges; /** @@ -62,12 +62,19 @@ TMH_EXCHANGES_done (void); * @param eh handle to the exchange context * @param wire_fee current applicable wire fee for dealing with @a eh, NULL if not available * @param exchange_trusted #GNUNET_YES if this exchange is trusted by config + * @param ec error code, #TALER_EC_NONE on success + * @param http_status the HTTP status we got from the exchange + * @param error_reply the full reply from the exchange, NULL if + * the response was NOT in JSON or on success */ typedef void (*TMH_EXCHANGES_FindContinuation)(void *cls, struct TALER_EXCHANGE_Handle *eh, const struct TALER_Amount *wire_fee, - int exchange_trusted); + int exchange_trusted, + enum TALER_ErrorCode ec, + unsigned int http_status, + const json_t *error_reply); /** diff --git a/src/backend/taler-merchant-httpd_order.c b/src/backend/taler-merchant-httpd_order.c index 8426ef90..2c1dcbaa 100644 --- a/src/backend/taler-merchant-httpd_order.c +++ b/src/backend/taler-merchant-httpd_order.c @@ -517,7 +517,7 @@ proposal_put (struct MHD_Connection *connection, /* add fields to the contract that the backend should provide */ json_object_set (order, "exchanges", - trusted_exchanges); + TMH_trusted_exchanges); json_object_set (order, "auditors", diff --git a/src/backend/taler-merchant-httpd_pay.c b/src/backend/taler-merchant-httpd_pay.c index 821724ea..b0178cdc 100644 --- a/src/backend/taler-merchant-httpd_pay.c +++ b/src/backend/taler-merchant-httpd_pay.c @@ -1139,12 +1139,19 @@ deposit_cb (void *cls, * NULL if not available * @param exchange_trusted #GNUNET_YES if this exchange is * trusted by config + * @param ec error code, #TALER_EC_NONE on success + * @param http_status the HTTP status we got from the exchange + * @param error_reply the full reply from the exchange, NULL if + * the response was NOT in JSON or on success */ static void process_pay_with_exchange (void *cls, struct TALER_EXCHANGE_Handle *mh, const struct TALER_Amount *wire_fee, - int exchange_trusted) + int exchange_trusted, + enum TALER_ErrorCode ec, + unsigned int http_status, + const json_t *error_reply) { struct PayContext *pc = cls; const struct TALER_EXCHANGE_Keys *keys; diff --git a/src/backend/taler-merchant-httpd_tip-pickup.c b/src/backend/taler-merchant-httpd_tip-pickup.c index 9c2adea3..3ad062dd 100644 --- a/src/backend/taler-merchant-httpd_tip-pickup.c +++ b/src/backend/taler-merchant-httpd_tip-pickup.c @@ -278,12 +278,19 @@ run_pickup (struct MHD_Connection *connection, * @param eh handle to the exchange context * @param wire_fee current applicable wire fee for dealing with @a eh, NULL if not available * @param exchange_trusted #GNUNET_YES if this exchange is trusted by config + * @param ec error code, #TALER_EC_NONE on success + * @param http_status the HTTP status we got from the exchange + * @param error_reply the full reply from the exchange, NULL if + * the response was NOT in JSON or on success */ static void exchange_found_cb (void *cls, struct TALER_EXCHANGE_Handle *eh, const struct TALER_Amount *wire_fee, - int exchange_trusted) + int exchange_trusted, + enum TALER_ErrorCode ec, + unsigned int http_status, + const json_t *error_reply) { struct PickupContext *pc = cls; const struct TALER_EXCHANGE_Keys *keys; diff --git a/src/backend/taler-merchant-httpd_tip-reserve-helper.c b/src/backend/taler-merchant-httpd_tip-reserve-helper.c index 28c491b0..67ba574b 100644 --- a/src/backend/taler-merchant-httpd_tip-reserve-helper.c +++ b/src/backend/taler-merchant-httpd_tip-reserve-helper.c @@ -339,12 +339,19 @@ handle_status (void *cls, * @param eh handle to the exchange context * @param wire_fee current applicable wire fee for dealing with @a eh, NULL if not available * @param exchange_trusted #GNUNET_YES if this exchange is trusted by config + * @param ec error code, #TALER_EC_NONE on success + * @param http_status the HTTP status we got from the exchange + * @param error_reply the full reply from the exchange, NULL if + * the response was NOT in JSON or on success */ static void exchange_cont (void *cls, struct TALER_EXCHANGE_Handle *eh, const struct TALER_Amount *wire_fee, - int exchange_trusted) + int exchange_trusted, + enum TALER_ErrorCode ec, + unsigned int http_status, + const json_t *error_reply) { struct TMH_CheckTipReserve *ctr = cls; struct TALER_ReservePublicKeyP reserve_pub; diff --git a/src/backend/taler-merchant-httpd_track-transaction.c b/src/backend/taler-merchant-httpd_track-transaction.c index 4ce5aa3d..e0900888 100644 --- a/src/backend/taler-merchant-httpd_track-transaction.c +++ b/src/backend/taler-merchant-httpd_track-transaction.c @@ -884,12 +884,19 @@ trace_coins (struct TrackTransactionContext *tctx) * @param eh NULL if exchange was not found to be acceptable * @param wire_fee NULL (we did not specify a wire method) * @param exchange_trusted #GNUNET_YES if this exchange is trusted by config + * @param ec error code, #TALER_EC_NONE on success + * @param http_status the HTTP status we got from the exchange + * @param error_reply the full reply from the exchange, NULL if + * the response was NOT in JSON or on success */ static void process_track_transaction_with_exchange (void *cls, struct TALER_EXCHANGE_Handle *eh, const struct TALER_Amount *wire_fee, - int exchange_trusted) + int exchange_trusted, + enum TALER_ErrorCode ec, + unsigned int http_status, + const json_t *error_reply) { struct TrackTransactionContext *tctx = cls; @@ -1032,11 +1039,11 @@ find_exchange (struct TrackTransactionContext *tctx) if (NULL != tcc) { tctx->current_exchange = tcc->exchange_url; - tctx->fo = TMH_EXCHANGES_find_exchange (tctx->current_exchange, - NULL, - & - process_track_transaction_with_exchange, - tctx); + tctx->fo = TMH_EXCHANGES_find_exchange ( + tctx->current_exchange, + NULL, + &process_track_transaction_with_exchange, + tctx); } else diff --git a/src/backend/taler-merchant-httpd_track-transfer.c b/src/backend/taler-merchant-httpd_track-transfer.c index 415401ed..6ebd80c8 100644 --- a/src/backend/taler-merchant-httpd_track-transfer.c +++ b/src/backend/taler-merchant-httpd_track-transfer.c @@ -818,12 +818,19 @@ wire_transfer_cb (void *cls, * @param eh NULL if exchange was not found to be acceptable * @param wire_fee NULL (we did not specify a wire method) * @param exchange_trusted #GNUNET_YES if this exchange is trusted by config + * @param ec error code, #TALER_EC_NONE on success + * @param http_status the HTTP status we got from the exchange + * @param error_reply the full reply from the exchange, NULL if + * the response was NOT in JSON or on success */ static void process_track_transfer_with_exchange (void *cls, struct TALER_EXCHANGE_Handle *eh, const struct TALER_Amount *wire_fee, - int exchange_trusted) + int exchange_trusted, + enum TALER_ErrorCode ec, + unsigned int http_status, + const json_t *error_reply) { struct TrackTransferContext *rctx = cls; -- cgit v1.2.3