aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2023-05-03 23:13:51 +0200
committerChristian Grothoff <christian@grothoff.org>2023-05-03 23:13:51 +0200
commit8535f1e81939e87258ad9d2503ad25df9cfb021d (patch)
tree6a01388ace0fcd23f57eb3bf19ea7d756b8401b7
parent63960574154ca1615fb095a71b958ec5d00df4ae (diff)
simplify POST /private/transfers implementation to match new situation with taler-merchant-exchange (incomplete)
-rw-r--r--src/backend/taler-merchant-httpd.c1
-rw-r--r--src/backend/taler-merchant-httpd_private-post-transfers.c1368
-rw-r--r--src/backend/taler-merchant-httpd_private-post-transfers.h9
-rw-r--r--src/backend/taler-merchant-httpd_private-post-webhooks.c5
-rw-r--r--src/backenddb/Makefile.am1
-rw-r--r--src/backenddb/merchant-0001.sql6
-rw-r--r--src/backenddb/pg_set_transfer_status_to_confirmed.c66
-rw-r--r--src/backenddb/pg_set_transfer_status_to_confirmed.h48
-rw-r--r--src/backenddb/plugin_merchantdb_postgres.c46
-rw-r--r--src/backenddb/test_merchantdb.c30
-rw-r--r--src/include/taler_merchant_service.h57
-rw-r--r--src/include/taler_merchantdb_plugin.h10
-rw-r--r--src/lib/merchant_api_post_transfers.c91
-rw-r--r--src/testing/test_kyc_api.c4
-rw-r--r--src/testing/test_merchant_api.c6
-rw-r--r--src/testing/testing_api_cmd_get_transfers.c23
-rw-r--r--src/testing/testing_api_cmd_post_transfers.c151
17 files changed, 242 insertions, 1680 deletions
diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c
index a676a009..15f67d04 100644
--- a/src/backend/taler-merchant-httpd.c
+++ b/src/backend/taler-merchant-httpd.c
@@ -289,7 +289,6 @@ do_shutdown (void *cls)
TMH_force_kyc_resume ();
TMH_force_rc_resume ();
TMH_force_gorc_resume ();
- TMH_force_post_transfers_resume ();
TMH_force_tip_pickup_resume ();
TMH_force_wallet_get_order_resume ();
TMH_force_wallet_refund_order_resume ();
diff --git a/src/backend/taler-merchant-httpd_private-post-transfers.c b/src/backend/taler-merchant-httpd_private-post-transfers.c
index af1ca844..2d99f35e 100644
--- a/src/backend/taler-merchant-httpd_private-post-transfers.c
+++ b/src/backend/taler-merchant-httpd_private-post-transfers.c
@@ -28,951 +28,53 @@
#include "taler-merchant-httpd_helper.h"
#include "taler-merchant-httpd_private-post-transfers.h"
-/**
- * How long to wait before giving up processing with the exchange?
- */
-#define TRANSFER_GENERIC_TIMEOUT (GNUNET_TIME_relative_multiply ( \
- GNUNET_TIME_UNIT_SECONDS, \
- 15))
/**
* How often do we retry the simple INSERT database transaction?
*/
#define MAX_RETRIES 3
-/**
- * Context used for handing POST /private/transfers requests.
- */
-struct PostTransfersContext
-{
-
- /**
- * Kept in a DLL.
- */
- struct PostTransfersContext *next;
-
- /**
- * Kept in a DLL.
- */
- struct PostTransfersContext *prev;
-
- /**
- * Argument for the /wire/transfers request.
- */
- struct TALER_WireTransferIdentifierRawP wtid;
-
- /**
- * Amount of the wire transfer.
- */
- struct TALER_Amount amount;
-
- /**
- * URL of the exchange.
- */
- const char *exchange_url;
-
- /**
- * payto:// URI used for the transfer.
- */
- const char *payto_uri;
-
- /**
- * Master public key of the exchange at @e exchange_url.
- */
- struct TALER_MasterPublicKeyP master_pub;
-
- /**
- * Handle for the /wire/transfers request.
- */
- struct TALER_EXCHANGE_TransfersGetHandle *wdh;
-
- /**
- * For which merchant instance is this tracking request?
- */
- struct TMH_HandlerContext *hc;
-
- /**
- * HTTP connection we are handling.
- */
- struct MHD_Connection *connection;
-
- /**
- * Response to return upon resume.
- */
- struct MHD_Response *response;
-
- /**
- * Handle for operation to lookup /keys (and auditors) from
- * the exchange used for this transaction; NULL if no operation is
- * pending.
- */
- struct TMH_EXCHANGES_FindOperation *fo;
-
- /**
- * Task run on timeout.
- */
- struct GNUNET_SCHEDULER_Task *timeout_task;
-
- /**
- * Pointer to the detail that we are currently
- * checking in #check_transfer().
- */
- const struct TALER_TrackTransferDetails *current_detail;
-
- /**
- * Which transaction detail are we currently looking at?
- */
- unsigned int current_offset;
-
- /**
- * Response code to return.
- */
- unsigned int response_code;
-
- /**
- * #GNUNET_NO if we did not find a matching coin.
- * #GNUNET_SYSERR if we found a matching coin, but the amounts do not match.
- * #GNUNET_OK if we did find a matching coin.
- */
- enum GNUNET_GenericReturnValue check_transfer_result;
-
- /**
- * Did we suspend @a connection and are thus in
- * the #ptc_head DLL (#GNUNET_YES). Set to
- * #GNUNET_NO if we are not suspended, and to
- * #GNUNET_SYSERR if we should close the connection
- * without a response due to shutdown.
- */
- enum GNUNET_GenericReturnValue suspended;
-
- /**
- * Should we retry the transaction due to a serialization error?
- */
- bool soft_retry;
-
- /**
- * Did we just download the exchange reply?
- */
- bool downloaded;
-
-};
-
-
-/**
- * Head of list of suspended requests.
- */
-static struct PostTransfersContext *ptc_head;
-
-/**
- * Tail of list of suspended requests.
- */
-static struct PostTransfersContext *ptc_tail;
-
-
-void
-TMH_force_post_transfers_resume ()
-{
- struct PostTransfersContext *ptc;
-
- while (NULL != (ptc = ptc_head))
- {
- GNUNET_CONTAINER_DLL_remove (ptc_head,
- ptc_tail,
- ptc);
- ptc->suspended = GNUNET_SYSERR;
- MHD_resume_connection (ptc->connection);
- if (NULL != ptc->timeout_task)
- {
- GNUNET_SCHEDULER_cancel (ptc->timeout_task);
- ptc->timeout_task = NULL;
- }
- }
-}
-
-
-/**
- * Resume the given /track/transfer operation and send the given response.
- * Stores the response in the @a ptc and signals MHD to resume
- * the connection. Also ensures MHD runs immediately.
- *
- * @param ptc transfer tracking context
- * @param response_code response code to use
- * @param response response data to send back
- */
-static void
-resume_transfer_with_response (struct PostTransfersContext *ptc,
- unsigned int response_code,
- struct MHD_Response *response)
-{
- ptc->response_code = response_code;
- ptc->response = response;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Resuming POST /transfers handling as exchange interaction is done (%u)\n",
- response_code);
- if (NULL != ptc->timeout_task)
- {
- GNUNET_SCHEDULER_cancel (ptc->timeout_task);
- ptc->timeout_task = NULL;
- }
- GNUNET_CONTAINER_DLL_remove (ptc_head,
- ptc_tail,
- ptc);
- ptc->suspended = GNUNET_NO;
- MHD_resume_connection (ptc->connection);
- TALER_MHD_daemon_trigger (); /* we resumed, kick MHD */
-}
-
-
-/**
- * Resume the given POST /transfers operation with an error.
- *
- * @param ptc transfer tracking context
- * @param response_code response code to use
- * @param ec error code to use
- * @param hint hint text to provide
- */
-static void
-resume_transfer_with_error (struct PostTransfersContext *ptc,
- unsigned int response_code,
- enum TALER_ErrorCode ec,
- const char *hint)
-{
- resume_transfer_with_response (ptc,
- response_code,
- TALER_MHD_make_error (ec,
- hint));
-}
-
-
-/**
- * Custom cleanup routine for a `struct PostTransfersContext`.
- *
- * @param cls the `struct PostTransfersContext` to clean up.
- */
-static void
-transfer_cleanup (void *cls)
-{
- struct PostTransfersContext *ptc = cls;
-
- if (NULL != ptc->fo)
- {
- TMH_EXCHANGES_find_exchange_cancel (ptc->fo);
- ptc->fo = NULL;
- }
- if (NULL != ptc->timeout_task)
- {
- GNUNET_SCHEDULER_cancel (ptc->timeout_task);
- ptc->timeout_task = NULL;
- }
- if (NULL != ptc->wdh)
- {
- TALER_EXCHANGE_transfers_get_cancel (ptc->wdh);
- ptc->wdh = NULL;
- }
- if (NULL != ptc->response)
- {
- MHD_destroy_response (ptc->response);
- ptc->response = NULL;
- }
- GNUNET_free (ptc);
-}
-
-
-/**
- * This function checks that the information about the coin which
- * was paid back by _this_ wire transfer matches what _we_ (the merchant)
- * knew about this coin.
- *
- * @param cls closure with our `struct PostTransfersContext *`
- * @param exchange_url URL of the exchange that issued @a coin_pub
- * @param amount_with_fee amount the exchange will transfer for this coin
- * @param deposit_fee fee the exchange will charge for this coin
- * @param refund_fee fee the exchange will charge for refunding this coin
- * @param wire_fee paid wire fee
- * @param h_wire hash of merchant's wire details
- * @param deposit_timestamp when did the exchange receive the deposit
- * @param refund_deadline until when are refunds allowed
- * @param exchange_sig signature by the exchange
- * @param exchange_pub exchange signing key used for @a exchange_sig
- */
-static void
-check_transfer (void *cls,
- const char *exchange_url,
- const struct TALER_Amount *amount_with_fee,
- const struct TALER_Amount *deposit_fee,
- const struct TALER_Amount *refund_fee,
- const struct TALER_Amount *wire_fee,
- const struct TALER_MerchantWireHashP *h_wire,
- struct GNUNET_TIME_Timestamp deposit_timestamp,
- struct GNUNET_TIME_Timestamp refund_deadline,
- const struct TALER_ExchangeSignatureP *exchange_sig,
- const struct TALER_ExchangePublicKeyP *exchange_pub)
-{
- struct PostTransfersContext *ptc = cls;
- const struct TALER_TrackTransferDetails *ttd = ptc->current_detail;
-
- if (GNUNET_SYSERR == ptc->check_transfer_result)
- return; /* already had a serious issue; odd that we're called more than once as well... */
- if ( (0 != TALER_amount_cmp (amount_with_fee,
- &ttd->coin_value)) ||
- (0 != TALER_amount_cmp (deposit_fee,
- &ttd->coin_fee)) )
- {
- /* Disagreement between the exchange and us about how much this
- coin is worth! */
- GNUNET_break_op (0);
- ptc->check_transfer_result = GNUNET_SYSERR;
- /* Build the `TrackTransferConflictDetails` */
- ptc->response_code = MHD_HTTP_ACCEPTED;
- ptc->response
- = TALER_MHD_MAKE_JSON_PACK (
- TALER_JSON_pack_ec (
- TALER_EC_MERCHANT_PRIVATE_POST_TRANSFERS_CONFLICTING_REPORTS),
- GNUNET_JSON_pack_string ("exchange_url",
- exchange_url),
- GNUNET_JSON_pack_timestamp ("deposit_timestamp",
- deposit_timestamp),
- GNUNET_JSON_pack_timestamp ("refund_deadline",
- refund_deadline),
- GNUNET_JSON_pack_uint64 ("conflict_offset",
- ptc->current_offset),
- GNUNET_JSON_pack_data_auto ("coin_pub",
- &ttd->coin_pub),
- GNUNET_JSON_pack_data_auto ("h_wire",
- h_wire),
- GNUNET_JSON_pack_data_auto ("deposit_exchange_sig",
- exchange_sig),
- GNUNET_JSON_pack_data_auto ("deposit_exchange_pub",
- exchange_pub),
- GNUNET_JSON_pack_data_auto ("h_contract_terms",
- &ttd->h_contract_terms),
- TALER_JSON_pack_amount ("amount_with_fee",
- amount_with_fee),
- TALER_JSON_pack_amount ("coin_value",
- &ttd->coin_value),
- TALER_JSON_pack_amount ("coin_fee",
- &ttd->coin_fee),
- TALER_JSON_pack_amount ("deposit_fee",
- deposit_fee));
- return;
- }
- ptc->check_transfer_result = GNUNET_OK;
-}
-
-
-/**
- * Check that the given @a wire_fee is what the @a exchange_pub should charge
- * at the @a execution_time. If the fee is correct (according to our
- * database), return #GNUNET_OK. If we do not have the fee structure in our
- * DB, we just accept it and return #GNUNET_NO; if we have proof that the fee
- * is bogus, we respond with the proof to the client and return
- * #GNUNET_SYSERR.
- *
- * @param ptc context of the transfer to respond to
- * @param execution_time time of the wire transfer
- * @param wire_fee fee claimed by the exchange
- * @return #GNUNET_SYSERR if we returned hard proof of
- * missbehavior from the exchange to the client
- */
-static enum GNUNET_GenericReturnValue
-check_wire_fee (struct PostTransfersContext *ptc,
- struct GNUNET_TIME_Timestamp execution_time,
- const struct TALER_Amount *wire_fee)
-{
- struct TALER_WireFeeSet fees;
- struct TALER_MasterSignatureP master_sig;
- struct GNUNET_TIME_Timestamp start_date;
- struct GNUNET_TIME_Timestamp end_date;
- enum GNUNET_DB_QueryStatus qs;
- char *wire_method;
-
- wire_method = TALER_payto_get_method (ptc->payto_uri);
- qs = TMH_db->lookup_wire_fee (TMH_db->cls,
- &ptc->master_pub,
- wire_method,
- execution_time,
- &fees,
- &start_date,
- &end_date,
- &master_sig);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- ptc->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
- ptc->response = TALER_MHD_make_error (TALER_EC_GENERIC_DB_FETCH_FAILED,
- "lookup_wire_fee");
- return GNUNET_SYSERR;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- ptc->soft_retry = true;
- return GNUNET_NO;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to find wire fee for `%s' and method `%s' at %s in DB, accepting blindly that the fee is %s\n",
- TALER_B2S (&ptc->master_pub),
- wire_method,
- GNUNET_TIME_timestamp2s (execution_time),
- TALER_amount2s (wire_fee));
- GNUNET_free (wire_method);
- return GNUNET_NO;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- break;
- }
- if (0 <= TALER_amount_cmp (&fees.wire,
- wire_fee))
- {
- GNUNET_free (wire_method);
- return GNUNET_OK; /* expected_fee >= wire_fee */
- }
- /* Wire fee check failed, export proof to client */
- ptc->response_code = MHD_HTTP_ACCEPTED;
- ptc->response =
- TALER_MHD_MAKE_JSON_PACK (
- TALER_JSON_pack_ec (
- TALER_EC_MERCHANT_PRIVATE_POST_TRANSFERS_BAD_WIRE_FEE),
- TALER_JSON_pack_amount ("wire_fee",
- wire_fee),
- GNUNET_JSON_pack_timestamp ("execution_time",
- execution_time),
- TALER_JSON_pack_amount ("expected_wire_fee",
- &fees.wire),
- TALER_JSON_pack_amount ("expected_closing_fee",
- &fees.closing),
- GNUNET_JSON_pack_timestamp ("start_date",
- start_date),
- GNUNET_JSON_pack_timestamp ("end_date",
- end_date),
- GNUNET_JSON_pack_data_auto ("master_sig",
- &master_sig),
- GNUNET_JSON_pack_data_auto ("master_pub",
- &ptc->master_pub));
- GNUNET_free (wire_method);
- return GNUNET_SYSERR;
-}
-
-
-/**
- * Function called with detailed wire transfer data, including all
- * of the coin transactions that were combined into the wire transfer.
- *
- * @param cls closure
- * @param tgr response details
- */
-static void
-wire_transfer_cb (void *cls,
- const struct TALER_EXCHANGE_TransfersGetResponse *tgr)
-{
- struct PostTransfersContext *ptc = cls;
- const struct TALER_EXCHANGE_HttpResponse *hr = &tgr->hr;
- const char *instance_id = ptc->hc->instance->settings.id;
- enum GNUNET_DB_QueryStatus qs;
-
- ptc->wdh = NULL;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Got response code %u from exchange for GET /transfers/$WTID\n",
- hr->http_status);
- switch (hr->http_status)
- {
- case MHD_HTTP_OK:
- break;
- case MHD_HTTP_NOT_FOUND:
- resume_transfer_with_response (
- ptc,
- MHD_HTTP_BAD_GATEWAY,
- TALER_MHD_MAKE_JSON_PACK (
- TALER_JSON_pack_ec (
- TALER_EC_MERCHANT_PRIVATE_POST_TRANSFERS_EXCHANGE_UNKNOWN),
- TMH_pack_exchange_reply (hr)));
- return;
- default:
- resume_transfer_with_response (
- ptc,
- MHD_HTTP_BAD_GATEWAY,
- TALER_MHD_MAKE_JSON_PACK (
- TALER_JSON_pack_ec (
- TALER_EC_MERCHANT_GENERIC_EXCHANGE_UNEXPECTED_STATUS),
- TMH_pack_exchange_reply (hr)));
- return;
- }
- TMH_db->preflight (TMH_db->cls);
- /* Ok, exchange answer is acceptable, store it */
- qs = TMH_db->insert_transfer_details (TMH_db->cls,
- instance_id,
- ptc->exchange_url,
- ptc->payto_uri,
- &ptc->wtid,
- &tgr->details.ok.td);
- if (0 > qs)
- {
- /* Always report on DB error as well to enable diagnostics */
- GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
- resume_transfer_with_error (
- ptc,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- (GNUNET_DB_STATUS_HARD_ERROR == qs)
- ? TALER_EC_GENERIC_DB_COMMIT_FAILED
- : TALER_EC_GENERIC_DB_SOFT_FAILURE,
- NULL);
- return;
- }
- if (0 == qs)
- {
- GNUNET_break (0);
- resume_transfer_with_error (
- ptc,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_STORE_FAILED,
- "insert-transfer-details");
- return;
- }
- if (0 !=
- TALER_amount_cmp (&tgr->details.ok.td.total_amount,
- &ptc->amount))
- {
- resume_transfer_with_error (
- ptc,
- MHD_HTTP_CONFLICT,
- TALER_EC_MERCHANT_PRIVATE_POST_TRANSFERS_CONFLICTING_TRANSFERS,
- NULL);
- return;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Transfer details inserted, resuming request...\n");
- /* resume processing, main function will build the response */
- resume_transfer_with_response (ptc,
- 0,
- NULL);
-}
-
-
-/**
- * Function called with the result of our exchange lookup.
- *
- * @param cls the `struct PostTransfersContext`
- * @param hr HTTP response details
- * @param eh NULL if exchange was not found to be acceptable
- * @param ih internal handle to the exchange
- */
-static void
-process_transfer_with_exchange (void *cls,
- const struct TALER_EXCHANGE_HttpResponse *hr,
- struct TALER_EXCHANGE_Handle *eh,
- struct TMH_Exchange *ih)
-{
- struct PostTransfersContext *ptc = cls;
-
- (void) ih;
- ptc->fo = NULL;
- if (NULL == hr)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Exchange failed to respond!\n");
- resume_transfer_with_response (
- ptc,
- MHD_HTTP_GATEWAY_TIMEOUT,
- TALER_MHD_MAKE_JSON_PACK (
- TALER_JSON_pack_ec (TALER_EC_MERCHANT_GENERIC_EXCHANGE_TIMEOUT)));
- return;
- }
- if (NULL == eh)
- {
- /* The request failed somehow */
- GNUNET_break_op (0);
- resume_transfer_with_response (
- ptc,
- MHD_HTTP_BAD_GATEWAY,
- TALER_MHD_MAKE_JSON_PACK (
- TALER_JSON_pack_ec (
- TALER_EC_MERCHANT_GENERIC_EXCHANGE_CONNECT_FAILURE),
- TMH_pack_exchange_reply (hr)));
- return;
- }
-
- /* keep master key for later */
- {
- const struct TALER_EXCHANGE_Keys *keys;
-
- keys = TALER_EXCHANGE_get_keys (eh);
- if (NULL == keys)
- {
- GNUNET_break (0);
- resume_transfer_with_error (ptc,
- MHD_HTTP_BAD_GATEWAY,
- TALER_EC_MERCHANT_GENERIC_EXCHANGE_KEYS_FAILURE,
- NULL);
- return;
- }
- ptc->master_pub = keys->master_pub;
- }
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Requesting transfer details from exchange\n");
- ptc->wdh = TALER_EXCHANGE_transfers_get (eh,
- &ptc->wtid,
- &wire_transfer_cb,
- ptc);
- if (NULL == ptc->wdh)
- {
- GNUNET_break (0);
- resume_transfer_with_error (ptc,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_MERCHANT_PRIVATE_POST_TRANSFERS_REQUEST_ERROR,
- "failed to run GET /transfers/ on exchange");
- }
-}
-
-
-/**
- * Now we want to double-check that any (Taler coin) deposit which is
- * accounted into _this_ wire transfer, does exist into _our_ database. This
- * is the rationale: if the exchange paid us for it, we must have received it
- * _beforehands_!
- *
- * @param cls a `struct PostTransfersContext`
- * @param current_offset at which offset in the exchange's reply are the @a ttd
- * @param ttd details about an aggregated transfer (to check)
- */
-static void
-verify_exchange_claim_cb (void *cls,
- unsigned int current_offset,
- const struct TALER_TrackTransferDetails *ttd)
-{
- struct PostTransfersContext *ptc = cls;
- enum GNUNET_DB_QueryStatus qs;
-
- if (0 != ptc->response_code)
- return; /* already encountered an error */
- if (ptc->soft_retry)
- return; /* already encountered an error */
- ptc->current_offset = current_offset;
- ptc->current_detail = ttd;
- /* Set the coin as "never seen" before. */
- ptc->check_transfer_result = GNUNET_NO;
- qs = TMH_db->lookup_deposits_by_contract_and_coin (
- TMH_db->cls,
- ptc->hc->instance->settings.id,
- &ttd->h_contract_terms,
- &ttd->coin_pub,
- &check_transfer,
- ptc);
- switch (qs)
- {
- case GNUNET_DB_STATUS_SOFT_ERROR:
- ptc->soft_retry = true;
- return;
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- ptc->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
- ptc->response
- = TALER_MHD_make_error (TALER_EC_GENERIC_DB_FETCH_FAILED,
- "deposit by contract and coin");
- return;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- /* The exchange says we made this deposit, but WE do not
- recall making it (corrupted / unreliable database?)!
- Well, let's say thanks and accept the money! */
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to find payment data in DB\n");
- ptc->check_transfer_result = GNUNET_OK;
- break;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- break;
- }
- switch (ptc->check_transfer_result)
- {
- case GNUNET_NO:
- /* Internal error: how can we have called #check_transfer()
- but still have no result? */
- GNUNET_break (0);
- ptc->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
- ptc->response =
- TALER_MHD_make_error (TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
- "check_transfer_result must not be GNUNET_NO");
- return;
- case GNUNET_SYSERR:
- /* #check_transfer() failed, report conflict! */
- GNUNET_break_op (0);
- GNUNET_assert (NULL != ptc->response);
- return;
- case GNUNET_OK:
- break;
- }
-}
-
-
-/**
- * Represents an entry in the table used to sum up
- * individual deposits for each h_contract_terms/order_id
- * (as the exchange gives us per coin, and we return
- * per order).
- */
-struct Entry
-{
-
- /**
- * Order of the entry.
- */
- char *order_id;
-
- /**
- * Sum accumulator for deposited value.
- */
- struct TALER_Amount deposit_value;
-
- /**
- * Sum accumulator for deposit fee.
- */
- struct TALER_Amount deposit_fee;
-
-};
-
-
-/**
- * Function called with information about a wire transfer identifier.
- * Generate a response array based on the given information.
- *
- * @param cls closure, a hashmap to update
- * @param order_id the order to which the deposits belong
- * @param deposit_value the amount deposited under @a order_id
- * @param deposit_fee the fee charged for @a deposit_value
- */
-static void
-transfer_summary_cb (void *cls,
- const char *order_id,
- const struct TALER_Amount *deposit_value,
- const struct TALER_Amount *deposit_fee)
-{
- struct GNUNET_CONTAINER_MultiHashMap *map = cls;
- struct Entry *current_entry;
- struct GNUNET_HashCode h_key;
-
- GNUNET_CRYPTO_hash (order_id,
- strlen (order_id),
- &h_key);
- current_entry = GNUNET_CONTAINER_multihashmap_get (map,
- &h_key);
- if (NULL != current_entry)
- {
- /* The map already knows this order, do aggregation */
- GNUNET_assert ( (0 <=
- TALER_amount_add (&current_entry->deposit_value,
- &current_entry->deposit_value,
- deposit_value)) &&
- (0 <=
- TALER_amount_add (&current_entry->deposit_fee,
- &current_entry->deposit_fee,
- deposit_fee)) );
- }
- else
- {
- /* First time in the map for this h_contract_terms*/
- current_entry = GNUNET_new (struct Entry);
- current_entry->deposit_value = *deposit_value;
- current_entry->deposit_fee = *deposit_fee;
- current_entry->order_id = GNUNET_strdup (order_id);
- GNUNET_assert (GNUNET_SYSERR !=
- GNUNET_CONTAINER_multihashmap_put (map,
- &h_key,
- current_entry,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
- }
-}
-
-
-/**
- * Callback that frees all the elements in the hashmap, and @a cls
- * is non-NULL, appends them as JSON to the array
- *
- * @param cls closure, NULL or a `json_t *` array
- * @param key current key
- * @param value a `struct Entry`
- * @return #GNUNET_YES if the iteration should continue,
- * #GNUNET_NO otherwise.
- */
-static int
-hashmap_update_and_free (void *cls,
- const struct GNUNET_HashCode *key,
- void *value)
-{
- json_t *ja = cls;
- struct Entry *entry = value;
-
- (void) key;
- if (NULL != ja)
- {
- GNUNET_assert (
- 0 ==
- json_array_append_new (
- ja,
- GNUNET_JSON_PACK (
- GNUNET_JSON_pack_string ("order_id",
- entry->order_id),
- TALER_JSON_pack_amount ("deposit_value",
- &entry->deposit_value),
- TALER_JSON_pack_amount ("deposit_fee",
- &entry->deposit_fee))));
- }
- GNUNET_free (entry->order_id);
- GNUNET_free (entry);
- return GNUNET_YES;
-}
-
-
-/**
- * Handle a timeout for the processing of the track transfer request.
- *
- * @param cls closure
- */
-static void
-handle_transfer_timeout (void *cls)
-{
- struct PostTransfersContext *ptc = cls;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Resuming POST /private/transfers with error after timeout\n");
- ptc->timeout_task = NULL;
- if (NULL != ptc->fo)
- {
- TMH_EXCHANGES_find_exchange_cancel (ptc->fo);
- ptc->fo = NULL;
- }
- if (NULL != ptc->wdh)
- {
- TALER_EXCHANGE_transfers_get_cancel (ptc->wdh);
- ptc->wdh = NULL;
- }
- resume_transfer_with_error (ptc,
- MHD_HTTP_GATEWAY_TIMEOUT,
- TALER_EC_MERCHANT_GENERIC_EXCHANGE_TIMEOUT,
- NULL);
-}
-
-
-/**
- * We are *done* processing the request, just queue the response (!)
- *
- * @param ptc request context
- */
-static MHD_RESULT
-queue (struct PostTransfersContext *ptc)
-{
- MHD_RESULT ret;
-
- GNUNET_assert (0 != ptc->response_code);
- if (UINT_MAX == ptc->response_code)
- {
- GNUNET_break (0);
- return MHD_NO; /* hard error */
- }
- ret = MHD_queue_response (ptc->connection,
- ptc->response_code,
- ptc->response);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Queueing response (%u) for POST /private/transfers (%s).\n",
- (unsigned int) ptc->response_code,
- ret ? "OK" : "FAILED");
- return ret;
-}
-
-
-/**
- * Download transfer data from the exchange.
- *
- * @param ptc request context
- */
-static void
-download (struct PostTransfersContext *ptc)
-{
- ptc->downloaded = true;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Suspending POST /private/transfers handling while working with exchange\n");
- MHD_suspend_connection (ptc->connection);
- ptc->suspended = GNUNET_YES;
- GNUNET_CONTAINER_DLL_insert (ptc_head,
- ptc_tail,
- ptc);
- ptc->fo = TMH_EXCHANGES_find_exchange (ptc->exchange_url,
- false,
- &process_transfer_with_exchange,
- ptc);
- ptc->timeout_task
- = GNUNET_SCHEDULER_add_delayed (TRANSFER_GENERIC_TIMEOUT,
- &handle_transfer_timeout,
- ptc);
-}
-
MHD_RESULT
TMH_private_post_transfers (const struct TMH_RequestHandler *rh,
struct MHD_Connection *connection,
struct TMH_HandlerContext *hc)
{
- struct PostTransfersContext *ptc = hc->ctx;
+ const char *payto_uri;
+ const char *exchange_url;
+ struct TALER_WireTransferIdentifierRawP wtid;
+ struct TALER_Amount amount;
+ struct GNUNET_JSON_Specification spec[] = {
+ TALER_JSON_spec_amount ("credit_amount",
+ TMH_currency,
+ &amount),
+ GNUNET_JSON_spec_fixed_auto ("wtid",
+ &wtid),
+ GNUNET_JSON_spec_string ("payto_uri",
+ &payto_uri),
+ GNUNET_JSON_spec_string ("exchange_url",
+ &exchange_url),
+ GNUNET_JSON_spec_end ()
+ };
+ enum GNUNET_GenericReturnValue res;
enum GNUNET_DB_QueryStatus qs;
- if (NULL == ptc)
- {
- ptc = GNUNET_new (struct PostTransfersContext);
- ptc->connection = connection;
- ptc->hc = hc;
- hc->ctx = ptc;
- hc->cc = &transfer_cleanup;
- }
- if (GNUNET_SYSERR == ptc->suspended)
- return MHD_NO; /* we are in shutdown */
- /* resume logic: did we get resumed after a reply was built? */
- if (0 != ptc->response_code)
- return queue (ptc);
- if ( (NULL != ptc->fo) ||
- (NULL != ptc->wdh) )
- {
- /* likely old MHD version causing spurious wake-up */
- GNUNET_break (GNUNET_NO == ptc->suspended);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Not sure why we are here, should be suspended\n");
- return MHD_YES; /* still work in progress */
- }
- if (NULL == ptc->exchange_url)
- {
- /* First request, parse it! */
- struct GNUNET_JSON_Specification spec[] = {
- TALER_JSON_spec_amount ("credit_amount",
- TMH_currency,
- &ptc->amount),
- GNUNET_JSON_spec_fixed_auto ("wtid",
- &ptc->wtid),
- GNUNET_JSON_spec_string ("payto_uri",
- &ptc->payto_uri),
- GNUNET_JSON_spec_string ("exchange_url",
- &ptc->exchange_url),
- GNUNET_JSON_spec_end ()
- };
- enum GNUNET_GenericReturnValue res;
-
- res = TALER_MHD_parse_json_data (connection,
- hc->request_body,
- spec);
- if (GNUNET_OK != res)
- return (GNUNET_NO == res)
- ? MHD_YES
- : MHD_NO;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "New inbound wire transfer over %s to %s from %s\n",
- TALER_amount2s (&ptc->amount),
- ptc->payto_uri,
- ptc->exchange_url);
- }
+ res = TALER_MHD_parse_json_data (connection,
+ hc->request_body,
+ spec);
+ if (GNUNET_OK != res)
+ return (GNUNET_NO == res)
+ ? MHD_YES
+ : MHD_NO;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "New inbound wire transfer over %s to %s from %s\n",
+ TALER_amount2s (&amount),
+ payto_uri,
+ exchange_url);
/* Check if transfer data is in database, if not, add it. */
for (unsigned int retry = 0; retry<MAX_RETRIES; retry++)
{
- struct GNUNET_TIME_Timestamp execution_time;
- struct TALER_Amount total_amount;
- struct TALER_Amount exchange_amount;
- struct TALER_Amount wire_fee;
- bool verified;
- bool have_exchange_sig;
-
TMH_db->preflight (TMH_db->cls);
if (GNUNET_OK !=
TMH_db->start (TMH_db->cls,
@@ -984,16 +86,19 @@ TMH_private_post_transfers (const struct TMH_RequestHandler *rh,
TALER_EC_GENERIC_DB_START_FAILED,
"transfer");
}
- qs = TMH_db->lookup_transfer (TMH_db->cls,
- ptc->hc->instance->settings.id,
- ptc->exchange_url,
- &ptc->wtid,
- &total_amount,
- &wire_fee,
- &exchange_amount,
- &execution_time,
- &have_exchange_sig,
- &verified);
+ qs = TMH_db->insert_transfer (TMH_db->cls,
+ hc->instance->settings.id,
+ exchange_url,
+ &wtid,
+ &amount,
+ payto_uri,
+ true /* confirmed! */);
+ if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == 0)
+ qs = TMH_db->set_transfer_status_to_confirmed (TMH_db->cls,
+ hc->instance->settings.id,
+ exchange_url,
+ &wtid,
+ &amount);
switch (qs)
{
case GNUNET_DB_STATUS_HARD_ERROR:
@@ -1001,357 +106,58 @@ TMH_private_post_transfers (const struct TMH_RequestHandler *rh,
TMH_db->rollback (TMH_db->cls);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- "transfer");
+ TALER_EC_GENERIC_DB_STORE_FAILED,
+ "insert_transfer");
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ TMH_db->rollback (TMH_db->cls);
+ continue;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ /* Could not set to confirmed, must differ by amount! */
+ TMH_db->rollback (TMH_db->cls);
+ return TALER_MHD_reply_with_error (
+ connection,
+ MHD_HTTP_CONFLICT,
+ TALER_EC_MERCHANT_PRIVATE_POST_TRANSFERS_CONFLICTING_SUBMISSION,
+ NULL);
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
break;
+ }
+ {
+ struct GNUNET_DB_EventHeaderP es = {
+ .size = htons (sizeof (es)),
+ .type = htons (TALER_DBEVENT_MERCHANT_WIRE_TRANSFER_CONFIRMED)
+ };
+
+ TMH_db->event_notify (TMH_db->cls,
+ &es,
+ NULL,
+ 0);
+ }
+ qs = TMH_db->commit (TMH_db->cls);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ TMH_db->rollback (TMH_db->cls);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_COMMIT_FAILED,
+ NULL);
case GNUNET_DB_STATUS_SOFT_ERROR:
TMH_db->rollback (TMH_db->cls);
continue;
case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- /* Transfer so far unknown; try to persist the wire transfer information
- we have received in the database (it is not yet present). Upon
- success, try to download the transfer details from the exchange. */
- {
- uint64_t account_serial;
-
- /* Make sure the bank account is configured. */
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Transfer is not yet known\n");
- qs = TMH_db->lookup_account (TMH_db->cls,
- ptc->hc->instance->settings.id,
- ptc->payto_uri,
- &account_serial);
- switch (qs)
- {
- case GNUNET_DB_STATUS_SOFT_ERROR:
- TMH_db->rollback (TMH_db->cls);
- continue;
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- TMH_db->rollback (TMH_db->cls);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- "lookup_account");
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Bank account `%s' not configured for instance `%s'\n",
- ptc->payto_uri,
- ptc->hc->instance->settings.id);
- TMH_db->rollback (TMH_db->cls);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_NOT_FOUND,
- TALER_EC_MERCHANT_PRIVATE_POST_TRANSFERS_ACCOUNT_NOT_FOUND,
- ptc->payto_uri);
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Bank account `%s' is configured at row %llu\n",
- ptc->payto_uri,
- (unsigned long long) account_serial);
- break;
- }
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Inserting new transfer\n");
- qs = TMH_db->insert_transfer (TMH_db->cls,
- ptc->hc->instance->settings.id,
- ptc->exchange_url,
- &ptc->wtid,
- &ptc->amount,
- ptc->payto_uri,
- true /* confirmed! */);
- switch (qs)
- {
- case GNUNET_DB_STATUS_SOFT_ERROR:
- TMH_db->rollback (TMH_db->cls);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Soft error, retrying...\n");
- continue;
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- TMH_db->rollback (TMH_db->cls);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_STORE_FAILED,
- "transfer");
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- TMH_db->rollback (TMH_db->cls);
- /* Should not happen: we checked earlier! */
- GNUNET_break (0);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_CONFLICT,
- TALER_EC_GENERIC_DB_STORE_FAILED,
- "not unique");
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- {
- struct GNUNET_DB_EventHeaderP es = {
- .size = htons (sizeof (es)),
- .type = htons (TALER_DBEVENT_MERCHANT_WIRE_TRANSFER_CONFIRMED)
- };
-
- TMH_db->event_notify (TMH_db->cls,
- &es,
- NULL,
- 0);
- }
- break;
- }
-
- qs = TMH_db->commit (TMH_db->cls);
- switch (qs)
- {
- case GNUNET_DB_STATUS_SOFT_ERROR:
- TMH_db->rollback (TMH_db->cls);
- continue;
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- TMH_db->rollback (TMH_db->cls);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_COMMIT_FAILED,
- NULL);
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "post-transfer committed successfully\n");
- break;
- }
- download (ptc);
- return MHD_YES; /* download() always suspends */
- }
case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- /* Transfer exists */
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Transfer exists in DB (verified: %s, exchange signature: %s)\n",
- verified ? "true" : "false",
- have_exchange_sig ? "true" : "false");
- if (! verified)
- {
- if ( (! ptc->downloaded) &&
- (! have_exchange_sig) )
- {
- /* We may have previously attempted and failed to
- download the exchange data, do it again! */
- TMH_db->rollback (TMH_db->cls);
- download (ptc);
- return MHD_YES; /* download always suspends */
- }
- if (! have_exchange_sig)
- {
- /* We tried to download and still failed to get
- an exchange signture. Still, that should have
- been handled there. */
- TMH_db->rollback (TMH_db->cls);
- GNUNET_break (0);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
- "download but no exchange signature and no error");
- }
- /* verify */
- if (GNUNET_SYSERR ==
- check_wire_fee (ptc,
- execution_time,
- &wire_fee))
- {
- TMH_db->rollback (TMH_db->cls);
- return queue (ptc); /* generate error */
- }
- if (ptc->soft_retry)
- {
- /* DB serialization failure */
- ptc->soft_retry = false;
- TMH_db->rollback (TMH_db->cls);
- continue;
- }
- qs = TMH_db->lookup_transfer_details (TMH_db->cls,
- ptc->exchange_url,
- &ptc->wtid,
- &verify_exchange_claim_cb,
- ptc);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- TMH_db->rollback (TMH_db->cls);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- "lookup_transfer_details");
- case GNUNET_DB_STATUS_SOFT_ERROR:
- TMH_db->rollback (TMH_db->cls);
- continue;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- default:
- break;
- }
- if (0 != ptc->response_code)
- {
- TMH_db->rollback (TMH_db->cls);
- return queue (ptc); /* generate error */
- }
- if (ptc->soft_retry)
- {
- /* DB serialization failure */
- ptc->soft_retry = false;
- TMH_db->rollback (TMH_db->cls);
- continue;
- }
-
- {
- struct TALER_Amount delta;
-
- if (0 >
- TALER_amount_subtract (&delta,
- &total_amount,
- &wire_fee))
- {
- GNUNET_break (0);
- TMH_db->rollback (TMH_db->cls);
- return TALER_MHD_reply_with_error (
- connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
- NULL);
- }
- if (0 !=
- TALER_amount_cmp (&exchange_amount,
- &delta))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Amount of expected was %s\n",
- TALER_amount2s (&delta));
- TMH_db->rollback (TMH_db->cls);
- return TALER_MHD_reply_with_error (
- connection,
- MHD_HTTP_CONFLICT,
- TALER_EC_MERCHANT_PRIVATE_POST_TRANSFERS_CONFLICTING_TRANSFERS,
- TALER_amount2s (&exchange_amount));
- }
- if ( (GNUNET_OK !=
- TALER_amount_cmp_currency (&ptc->amount,
- &delta)) ||
- (0 !=
- TALER_amount_cmp (&ptc->amount,
- &delta)) )
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Amount submitted was %s\n",
- TALER_amount2s (&ptc->amount));
- TMH_db->rollback (TMH_db->cls);
- return TALER_MHD_reply_with_error (
- connection,
- MHD_HTTP_CONFLICT,
- TALER_EC_MERCHANT_PRIVATE_POST_TRANSFERS_CONFLICTING_SUBMISSION,
- TALER_amount2s (&exchange_amount));
- }
- }
- verified = true;
- qs = TMH_db->set_transfer_status_to_verified (TMH_db->cls,
- ptc->exchange_url,
- &ptc->wtid);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- TMH_db->rollback (TMH_db->cls);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- "set_transfer_status_to_verified");
- case GNUNET_DB_STATUS_SOFT_ERROR:
- TMH_db->rollback (TMH_db->cls);
- continue;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- GNUNET_assert (0);
- break;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- break;
- }
- } /* end of 'if (! verified)' */
-
- /* Short version: we verified that the exchange reply and
- our own accounting match; generate the summary response */
- GNUNET_assert (verified);
- {
- struct GNUNET_CONTAINER_MultiHashMap *map;
- json_t *deposit_sums;
-
- map = GNUNET_CONTAINER_multihashmap_create (16,
- GNUNET_NO);
- qs = TMH_db->lookup_transfer_summary (TMH_db->cls,
- ptc->exchange_url,
- &ptc->wtid,
- &transfer_summary_cb,
- map);
- switch (qs)
- {
- case GNUNET_DB_STATUS_SOFT_ERROR:
- TMH_db->rollback (TMH_db->cls);
- continue;
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- TMH_db->rollback (TMH_db->cls);
- GNUNET_CONTAINER_multihashmap_iterate (map,
- &hashmap_update_and_free,
- NULL);
- GNUNET_CONTAINER_multihashmap_destroy (map);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- "transfer summary");
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- default:
- break;
- }
-
- qs = TMH_db->commit (TMH_db->cls);
- switch (qs)
- {
- case GNUNET_DB_STATUS_SOFT_ERROR:
- TMH_db->rollback (TMH_db->cls);
- continue;
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- TMH_db->rollback (TMH_db->cls);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_COMMIT_FAILED,
- NULL);
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "post-transfer committed uselessly\n");
- break;
- }
-
- deposit_sums = json_array ();
- GNUNET_assert (NULL != deposit_sums);
- GNUNET_CONTAINER_multihashmap_iterate (map,
- &hashmap_update_and_free,
- deposit_sums);
- GNUNET_CONTAINER_multihashmap_destroy (map);
- return TALER_MHD_REPLY_JSON_PACK (
- connection,
- MHD_HTTP_OK,
- TALER_JSON_pack_amount ("total",
- &total_amount),
- TALER_JSON_pack_amount ("wire_fee",
- &wire_fee),
- GNUNET_JSON_pack_timestamp ("execution_time",
- execution_time),
- GNUNET_JSON_pack_array_steal ("deposit_sums",
- deposit_sums));
- } /* end of 'verified == true' (not an 'if'!) */
- } /* end of 'switch (qs)' */
- GNUNET_assert (0);
- } /* end of 'for(retries...) */
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_SOFT_FAILURE,
- "post-transfers");
+ "post-transfer committed successfully\n");
+ break;
+ }
+ }
+ return TALER_MHD_reply_static (connection,
+ MHD_HTTP_NO_CONTENT,
+ NULL,
+ NULL,
+ 0);
}
diff --git a/src/backend/taler-merchant-httpd_private-post-transfers.h b/src/backend/taler-merchant-httpd_private-post-transfers.h
index a83a3449..8a411d2c 100644
--- a/src/backend/taler-merchant-httpd_private-post-transfers.h
+++ b/src/backend/taler-merchant-httpd_private-post-transfers.h
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- (C) 2014-2020 Taler Systems SA
+ (C) 2014-2023 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
@@ -26,13 +26,6 @@
/**
- * We are shutting down, force resume of all POST /transfers requests.
- */
-void
-TMH_force_post_transfers_resume (void);
-
-
-/**
* 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.
diff --git a/src/backend/taler-merchant-httpd_private-post-webhooks.c b/src/backend/taler-merchant-httpd_private-post-webhooks.c
index a7b90b0d..1115811e 100644
--- a/src/backend/taler-merchant-httpd_private-post-webhooks.c
+++ b/src/backend/taler-merchant-httpd_private-post-webhooks.c
@@ -87,11 +87,11 @@ TMH_private_post_webhooks (const struct TMH_RequestHandler *rh,
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_string ("header_template",
(const char **) &wb.header_template),
- NULL),
+ NULL),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_string ("body_template",
(const char **) &wb.body_template),
- NULL),
+ NULL),
GNUNET_JSON_spec_end ()
};
@@ -112,7 +112,6 @@ TMH_private_post_webhooks (const struct TMH_RequestHandler *rh,
}
-
/* finally, interact with DB until no serialization error */
for (unsigned int i = 0; i<MAX_RETRIES; i++)
{
diff --git a/src/backenddb/Makefile.am b/src/backenddb/Makefile.am
index 2ed54ef7..ab46a59e 100644
--- a/src/backenddb/Makefile.am
+++ b/src/backenddb/Makefile.am
@@ -62,6 +62,7 @@ libtaler_plugin_merchantdb_postgres_la_SOURCES = \
pg_update_transfer_status.h pg_update_transfer_status.c \
pg_delete_exchange_accounts.h pg_delete_exchange_accounts.c \
pg_select_accounts_by_exchange.h pg_select_accounts_by_exchange.c \
+ pg_set_transfer_status_to_confirmed.h pg_set_transfer_status_to_confirmed.c \
pg_insert_exchange_account.h pg_insert_exchange_account.c \
pg_lookup_reserves.h pg_lookup_reserves.c \
plugin_merchantdb_postgres.c pg_helper.h
diff --git a/src/backenddb/merchant-0001.sql b/src/backenddb/merchant-0001.sql
index cd4ae9f3..77792735 100644
--- a/src/backenddb/merchant-0001.sql
+++ b/src/backenddb/merchant-0001.sql
@@ -380,13 +380,13 @@ COMMENT ON TABLE merchant_refund_proofs
-------------------- Wire transfers ---------------------------
CREATE TABLE IF NOT EXISTS merchant_transfers
- (credit_serial BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
+ (credit_serial INT8 GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
,exchange_url VARCHAR NOT NULL
,wtid BYTEA CHECK (LENGTH(wtid)=32)
,credit_amount_val INT8 NOT NULL
,credit_amount_frac INT4 NOT NULL
- ,account_serial BIGINT NOT NULL
- REFERENCES merchant_accounts (account_serial) ON DELETE CASCADE
+ ,account_serial INT8 NOT NULL
+ REFERENCES merchant_accounts (account_serial) ON DELETE CASCADE
,verified BOOLEAN NOT NULL DEFAULT FALSE
,confirmed BOOLEAN NOT NULL DEFAULT FALSE
,UNIQUE (wtid, exchange_url, account_serial)
diff --git a/src/backenddb/pg_set_transfer_status_to_confirmed.c b/src/backenddb/pg_set_transfer_status_to_confirmed.c
new file mode 100644
index 00000000..700965a1
--- /dev/null
+++ b/src/backenddb/pg_set_transfer_status_to_confirmed.c
@@ -0,0 +1,66 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2023 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file backenddb/pg_set_transfer_status_to_confirmed.c
+ * @brief Implementation of the set_transfer_status_to_confirmed function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <taler/taler_error_codes.h>
+#include <taler/taler_dbevents.h>
+#include <taler/taler_pq_lib.h>
+#include "pg_set_transfer_status_to_confirmed.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TMH_PG_set_transfer_status_to_confirmed (
+ void *cls,
+ const char *instance_id,
+ const char *exchange_url,
+ const struct TALER_WireTransferIdentifierRawP *wtid,
+ const struct TALER_Amount *amount)
+{
+ struct PostgresClosure *pg = cls;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
+ GNUNET_PQ_query_param_auto_from_type (wtid),
+ GNUNET_PQ_query_param_string (exchange_url),
+ TALER_PQ_query_param_amount (amount),
+ GNUNET_PQ_query_param_end
+ };
+
+ check_connection (pg);
+ PREPARE (pg,
+ "set_transfer_status_to_confirmed",
+ "UPDATE merchant_transfers SET"
+ " confirmed=TRUE"
+ " WHERE wtid=$2"
+ " AND credit_amount_val=$4"
+ " AND credit_amount_frac=$5"
+ " AND exchange_url=$3"
+ " AND account_serial IN"
+ " (SELECT account_serial"
+ " FROM merchant_accounts"
+ " WHERE merchant_serial ="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1));");
+ return GNUNET_PQ_eval_prepared_non_select (
+ pg->conn,
+ "set_transfer_status_to_confirmed",
+ params);
+}
diff --git a/src/backenddb/pg_set_transfer_status_to_confirmed.h b/src/backenddb/pg_set_transfer_status_to_confirmed.h
new file mode 100644
index 00000000..859ebb26
--- /dev/null
+++ b/src/backenddb/pg_set_transfer_status_to_confirmed.h
@@ -0,0 +1,48 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file backenddb/pg_set_transfer_status_to_confirmed.h
+ * @brief implementation of the set_transfer_status_to_confirmed function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_SET_TRANSFER_STATUS_TO_CONFIRMED_H
+#define PG_SET_TRANSFER_STATUS_TO_CONFIRMED_H
+
+#include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
+#include "taler_merchantdb_plugin.h"
+
+
+/**
+ * Set transfer status to confirmed.
+ *
+ * @param cls closure
+ * @param instance_id merchant instance with the update
+ * @param exchange_url the exchange that made the transfer
+ * @param wtid wire transfer subject
+ * @param amount confirmed amount of the wire transfer
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+TMH_PG_set_transfer_status_to_confirmed (
+ void *cls,
+ const char *instance_id,
+ const char *exchange_url,
+ const struct TALER_WireTransferIdentifierRawP *wtid,
+ const struct TALER_Amount *amount);
+
+
+#endif
diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c
index ca26c01d..710fbdb3 100644
--- a/src/backenddb/plugin_merchantdb_postgres.c
+++ b/src/backenddb/plugin_merchantdb_postgres.c
@@ -42,6 +42,7 @@
#include "pg_insert_exchange_account.h"
#include "pg_lookup_reserves.h"
#include "pg_update_transfer_status.h"
+#include "pg_set_transfer_status_to_confirmed.h"
/**
@@ -3609,13 +3610,12 @@ postgres_insert_transfer (
bool confirmed)
{
struct PostgresClosure *pg = cls;
- uint8_t confirmed8 = confirmed;
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_string (exchange_url),
GNUNET_PQ_query_param_auto_from_type (wtid),
TALER_PQ_query_param_amount (credit_amount),
GNUNET_PQ_query_param_string (payto_uri),
- GNUNET_PQ_query_param_auto_from_type (&confirmed8),
+ GNUNET_PQ_query_param_bool (confirmed),
GNUNET_PQ_query_param_string (instance_id),
GNUNET_PQ_query_param_end
};
@@ -4227,35 +4227,6 @@ postgres_lookup_transfer (
/**
- * Set transfer status to verified.
- *
- * @param cls closure
- * @param exchange_url the exchange that made the transfer
- * @param wtid wire transfer subject
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-postgres_set_transfer_status_to_verified (
- void *cls,
- const char *exchange_url,
- const struct TALER_WireTransferIdentifierRawP *wtid)
-{
- struct PostgresClosure *pg = cls;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (wtid),
- GNUNET_PQ_query_param_string (exchange_url),
- GNUNET_PQ_query_param_end
- };
-
- check_connection (pg);
- return GNUNET_PQ_eval_prepared_non_select (
- pg->conn,
- "set_transfer_status_to_verified",
- params);
-}
-
-
-/**
* Closure for #lookup_transfer_summary_cb().
*/
struct LookupTransferSummaryContext
@@ -8637,7 +8608,8 @@ postgres_connect (void *cls)
" AND merchant_serial="
" (SELECT merchant_serial"
" FROM merchant_instances"
- " WHERE merchant_id=$7)"),
+ " WHERE merchant_id=$7)"
+ " ON CONFLICT DO NOTHING;"),
/* for postgres_delete_transfer() */
GNUNET_PQ_make_prepare ("delete_transfer",
"DELETE FROM merchant_transfers"
@@ -8805,12 +8777,6 @@ postgres_connect (void *cls)
" WHERE wtid=$2"
" AND exchange_url=$1"
" AND merchant_id=$3;"),
- /* for postgres_set_transfer_status_to_verified() */
- GNUNET_PQ_make_prepare ("set_transfer_status_to_verified",
- "UPDATE merchant_transfers SET"
- " verified=TRUE"
- " WHERE wtid=$1"
- " AND exchange_url=$2"),
/* for postgres_lookup_transfer_summary() */
GNUNET_PQ_make_prepare ("lookup_transfer_summary",
"SELECT"
@@ -9555,8 +9521,8 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
plugin->lookup_deposits_by_contract_and_coin =
&postgres_lookup_deposits_by_contract_and_coin;
plugin->lookup_transfer = &postgres_lookup_transfer;
- plugin->set_transfer_status_to_verified =
- &postgres_set_transfer_status_to_verified;
+ plugin->set_transfer_status_to_confirmed =
+ &TMH_PG_set_transfer_status_to_confirmed;
plugin->lookup_transfer_summary = &postgres_lookup_transfer_summary;
plugin->lookup_transfer_details = &postgres_lookup_transfer_details;
plugin->lookup_instances
diff --git a/src/backenddb/test_merchantdb.c b/src/backenddb/test_merchantdb.c
index c678f484..c3a2d3ad 100644
--- a/src/backenddb/test_merchantdb.c
+++ b/src/backenddb/test_merchantdb.c
@@ -3809,11 +3809,12 @@ test_lookup_transfer_details_by_order (
memset (results_matching,
0,
sizeof (unsigned int) * transfers_length);
- if (transfers_length != plugin->lookup_transfer_details_by_order (plugin->cls,
- order_serial,
- &
- lookup_transfer_details_order_cb,
- &cmp))
+ if (transfers_length !=
+ plugin->lookup_transfer_details_by_order (
+ plugin->cls,
+ order_serial,
+ &lookup_transfer_details_order_cb,
+ &cmp))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Lookup transfer details by order failed\n");
@@ -4352,15 +4353,16 @@ run_test_transfers (struct TestTransfers_Closure *cls)
true));
TEST_RET_ON_FAIL (test_lookup_transfer (&cls->instance,
&cls->transfers[0]));
- TEST_COND_RET_ON_FAIL (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT ==
- plugin->set_transfer_status_to_verified (plugin->cls,
- cls->deposit.
- exchange_url,
- &cls->
- transfers[0].
- wtid),
- "Set transfer status to verified failed\n");
- cls->transfers[0].verified = true;
+ TEST_COND_RET_ON_FAIL (
+ GNUNET_DB_STATUS_SUCCESS_ONE_RESULT ==
+ plugin->set_transfer_status_to_confirmed (
+ plugin->cls,
+ cls->instance.instance.id,
+ cls->deposit.exchange_url,
+ &cls->transfers[0].wtid,
+ &cls->deposit.amount_with_fee),
+ "Set transfer status to confirmed failed\n");
+ cls->transfers[0].confirmed = true;
TEST_RET_ON_FAIL (test_lookup_transfer (&cls->instance,
&cls->transfers[0]));
TEST_RET_ON_FAIL (test_lookup_transfer_summary (cls->deposit.exchange_url,
diff --git a/src/include/taler_merchant_service.h b/src/include/taler_merchant_service.h
index 1135cb38..15d83fce 100644
--- a/src/include/taler_merchant_service.h
+++ b/src/include/taler_merchant_service.h
@@ -2930,31 +2930,6 @@ TALER_MERCHANT_wallet_post_order_refund_cancel (
*/
struct TALER_MERCHANT_PostTransfersHandle;
-/**
- * Information about the _total_ amount that was paid back
- * by the exchange for a given h_contract_terms, by _one_ wire
- * transfer.
- */
-struct TALER_MERCHANT_TrackTransferDetail
-{
-
- /**
- * Total amount paid back by the exchange.
- */
- struct TALER_Amount deposit_value;
-
- /**
- * Total amount of deposit fees.
- */
- struct TALER_Amount deposit_fee;
-
- /**
- * Order ID associated whit this payment.
- */
- const char *order_id;
-
-};
-
/**
* @brief Response to a POST /transfers operation from a merchant's backend.
@@ -2973,38 +2948,6 @@ struct TALER_MERCHANT_PostTransfersResponse
{
/**
- * Details in case of success (#MHD_HTTP_OK).
- */
- struct
- {
-
- /**
- * when did the transfer happen (according to the exchange)
- */
- struct GNUNET_TIME_Timestamp execution_time;
-
- /**
- * total amount of the wire transfer
- */
- struct TALER_Amount total_amount;
-
- /**
- * how much did the exchange charge in terms of wire fees
- */
- struct TALER_Amount wire_fee;
-
- /**
- * Length of the @e details array
- */
- unsigned int details_length;
-
- /**
- * array with details about the combined transactions
- */
- const struct TALER_MERCHANT_TrackTransferDetail *details;
- } success;
-
- /**
* Details if we got an #MHD_HTTP_BAD_GATEWAY.
*/
struct
diff --git a/src/include/taler_merchantdb_plugin.h b/src/include/taler_merchantdb_plugin.h
index 7a15ddee..d07b92f1 100644
--- a/src/include/taler_merchantdb_plugin.h
+++ b/src/include/taler_merchantdb_plugin.h
@@ -2341,20 +2341,22 @@ struct TALER_MERCHANTDB_Plugin
/**
- * Set transfer status to verified.
+ * Set transfer status to confirmed.
*
* @param cls closure
* @param instance_id instance to lookup payments for
* @param exchange_url the exchange that made the transfer
- * @param payto_uri account that received the transfer
* @param wtid wire transfer subject
+ * @param amount confirmed amount of the wire transfer
* @return transaction status
*/
enum GNUNET_DB_QueryStatus
- (*set_transfer_status_to_verified)(
+ (*set_transfer_status_to_confirmed)(
void *cls,
+ const char *instance_id,
const char *exchange_url,
- const struct TALER_WireTransferIdentifierRawP *wtid);
+ const struct TALER_WireTransferIdentifierRawP *wtid,
+ const struct TALER_Amount *amount);
/**
diff --git a/src/lib/merchant_api_post_transfers.c b/src/lib/merchant_api_post_transfers.c
index 2a1a3f68..4a4ad2ac 100644
--- a/src/lib/merchant_api_post_transfers.c
+++ b/src/lib/merchant_api_post_transfers.c
@@ -96,96 +96,7 @@ handle_post_transfers_finished (void *cls,
case 0:
ptr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
break;
- case MHD_HTTP_OK:
- {
- json_t *deposit_sums;
- struct GNUNET_JSON_Specification spec[] = {
- TALER_JSON_spec_amount_any (
- "total",
- &ptr.details.success.total_amount),
- TALER_JSON_spec_amount_any (
- "wire_fee",
- &ptr.details.success.wire_fee),
- GNUNET_JSON_spec_timestamp (
- "execution_time",
- &ptr.details.success.execution_time),
- GNUNET_JSON_spec_json ("deposit_sums",
- &deposit_sums),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (ptr.hr.reply,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- ptr.hr.http_status = 0;
- ptr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
- break;
- }
- if (! json_is_array (deposit_sums))
- {
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (spec);
- ptr.hr.http_status = 0;
- ptr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
- break;
- }
- {
- struct TALER_MERCHANT_TrackTransferDetail *details;
- unsigned int i;
- bool ok;
- json_t *deposit_sum;
-
- ptr.details.success.details_length
- = json_array_size (deposit_sums);
- details = GNUNET_new_array (ptr.details.success.details_length,
- struct TALER_MERCHANT_TrackTransferDetail);
- ptr.details.success.details = details;
- ok = true;
- json_array_foreach (deposit_sums, i, deposit_sum) {
- struct TALER_MERCHANT_TrackTransferDetail *d
- = &details[i];
- struct GNUNET_JSON_Specification ispec[] = {
- GNUNET_JSON_spec_string ("order_id",
- &d->order_id),
- TALER_JSON_spec_amount_any ("deposit_value",
- &d->deposit_value),
- TALER_JSON_spec_amount_any ("deposit_fee",
- &d->deposit_fee),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (deposit_sum,
- ispec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- ok = false;
- break;
- }
- }
-
- if (! ok)
- {
- GNUNET_break_op (0);
- GNUNET_free (details);
- GNUNET_JSON_parse_free (spec);
- ptr.hr.http_status = 0;
- ptr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
- break;
- }
- pth->cb (pth->cb_cls,
- &ptr);
- GNUNET_free (details);
- GNUNET_JSON_parse_free (spec);
- TALER_MERCHANT_transfers_post_cancel (pth);
- return;
- }
- }
- case MHD_HTTP_ACCEPTED:
+ case MHD_HTTP_NO_CONTENT:
break;
case MHD_HTTP_UNAUTHORIZED:
ptr.hr.ec = TALER_JSON_get_error_code (ptr.hr.reply);
diff --git a/src/testing/test_kyc_api.c b/src/testing/test_kyc_api.c
index e000778f..90b0def3 100644
--- a/src/testing/test_kyc_api.c
+++ b/src/testing/test_kyc_api.c
@@ -255,7 +255,7 @@ run (void *cls,
merchant_payto,
merchant_url,
"EUR:4.98",
- MHD_HTTP_OK,
+ MHD_HTTP_NO_CONTENT,
"deposit-simple",
NULL),
TALER_TESTING_cmd_run_tme ("run taler-merchant-exchange-1",
@@ -368,7 +368,7 @@ run (void *cls,
merchant_payto,
merchant_url,
"EUR:4.98",
- MHD_HTTP_OK,
+ MHD_HTTP_NO_CONTENT,
"deposit-simple",
NULL),
TALER_TESTING_cmd_run_tme ("run taler-merchant-exchange-2-aml",
diff --git a/src/testing/test_merchant_api.c b/src/testing/test_merchant_api.c
index 551f824c..89bce513 100644
--- a/src/testing/test_merchant_api.c
+++ b/src/testing/test_merchant_api.c
@@ -492,13 +492,11 @@ run (void *cls,
PAYTO_I1,
merchant_url,
"EUR:4.98",
- MHD_HTTP_OK,
+ MHD_HTTP_NO_CONTENT,
"deposit-simple",
NULL),
TALER_TESTING_cmd_run_tme ("run taler-merchant-exchange-1",
config_file),
- /* FIXME: with the new API, the following will no longer
- make sense (probably should just be removed): */
TALER_TESTING_cmd_merchant_post_transfer2 ("post-transfer-bad",
merchant_url,
PAYTO_I1,
@@ -508,7 +506,7 @@ run (void *cls,
so we are sure to not get
any reply*/
"http://192.0.2.1/404/",
- MHD_HTTP_GATEWAY_TIMEOUT),
+ MHD_HTTP_NO_CONTENT),
TALER_TESTING_cmd_merchant_get_transfers ("get-transfers-1",
merchant_url,
PAYTO_I1,
diff --git a/src/testing/testing_api_cmd_get_transfers.c b/src/testing/testing_api_cmd_get_transfers.c
index fe50c349..33c2d462 100644
--- a/src/testing/testing_api_cmd_get_transfers.c
+++ b/src/testing/testing_api_cmd_get_transfers.c
@@ -224,29 +224,6 @@ get_transfers_cb (
return;
}
}
- {
- const struct GNUNET_TIME_Timestamp *execution_time;
-
- if (GNUNET_OK !=
- TALER_TESTING_get_trait_timestamp (transfer_cmd,
- 0,
- &execution_time))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Could not fetch wire transfer execution time\n");
- TALER_TESTING_interpreter_fail (gts->is);
- return;
- }
- if (GNUNET_TIME_timestamp_cmp (*execution_time,
- !=,
- transfers[i].execution_time))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Wire transfer execution time does not match\n");
- TALER_TESTING_interpreter_fail (gts->is);
- return;
- }
- }
}
break;
default:
diff --git a/src/testing/testing_api_cmd_post_transfers.c b/src/testing/testing_api_cmd_post_transfers.c
index b73c6b15..4971d952 100644
--- a/src/testing/testing_api_cmd_post_transfers.c
+++ b/src/testing/testing_api_cmd_post_transfers.c
@@ -115,10 +115,6 @@ struct PostTransfersState
*/
unsigned int deposits_length;
- /**
- * When the exchange executed the transfer.
- */
- struct GNUNET_TIME_Timestamp execution_time;
};
@@ -147,150 +143,7 @@ transfers_cb (void *cls,
}
switch (ptr->hr.http_status)
{
- case MHD_HTTP_OK:
- {
- pts->execution_time = ptr->details.success.execution_time;
- pts->wire_fee = ptr->details.success.wire_fee;
- fprintf (stderr,
- "FIXME");
- json_dumpf (ptr->hr.reply,
- stderr,
- 0);
-#if FIXME_WRITE_PROPPER_CHECK_OF_RETURNED_DATA_HERE
- /* this code is some legacy logic that is close to what we
- need but needs to be updated to the current API */
- struct TALER_Amount total;
-
- if (0 >
- TALER_amount_subtract (&total,
- total_amount,
- wire_fee))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (pts->is);
- return;
- }
- if (0 !=
- TALER_amount_cmp (&total,
- &pts->credit_amount))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (pts->is);
- return;
- }
- TALER_amount_set_zero (total.currency,
- &total);
- for (unsigned int i = 0; i<details_length; i++)
- {
- const struct TALER_MERCHANT_TrackTransferDetail *tdd = &details[i];
- struct TALER_Amount sum;
- struct TALER_Amount fees;
-
- TALER_amount_set_zero (tdd->deposit_value.currency,
- &sum);
- TALER_amount_set_zero (tdd->deposit_fee.currency,
- &fees);
- for (unsigned int j = 0; j<pts->deposits_length; j++)
- {
- const char *label = pts->deposits[j];
- const struct TALER_TESTING_Command *cmd;
- const json_t *contract_terms;
- const struct TALER_Amount *deposit_value;
- const struct TALER_Amount *deposit_fee;
- const char *order_id;
-
- cmd = TALER_TESTING_interpreter_lookup_command (pts->is,
- label);
- if (NULL == cmd)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (pts->is);
- return;
- }
- if ( (GNUNET_OK !=
- TALER_TESTING_get_trait_contract_terms (cmd,
- 0,
- &contract_terms)) ||
- (GNUNET_OK !=
- TALER_TESTING_get_trait_amount_obj (cmd,
- TALER_TESTING_CMD_DEPOSIT_TRAIT_IDX_DEPOSIT_VALUE,
- &deposit_value)) ||
- (GNUNET_OK !=
- TALER_TESTING_get_trait_amount_obj (cmd,
- TALER_TESTING_CMD_DEPOSIT_TRAIT_IDX_DEPOSIT_FEE,
- &deposit_fee)) )
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (pts->is);
- return;
- }
- order_id = json_string_value (json_object_get (contract_terms,
- "order_id"));
- if (NULL == order_id)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (pts->is);
- return;
- }
- if (0 != strcmp (tdd->order_id,
- order_id))
- continue;
- if (0 >
- TALER_amount_add (&sum,
- &sum,
- deposit_value))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (pts->is);
- return;
- }
- if (0 >
- TALER_amount_add (&fees,
- &fees,
- deposit_fee))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (pts->is);
- return;
- }
- }
- if (0 !=
- TALER_amount_cmp (&sum,
- &tdd->deposit_value))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (pts->is);
- return;
- }
- if (0 !=
- TALER_amount_cmp (&fees,
- &tdd->deposit_fee))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (pts->is);
- return;
- }
- GNUNET_assert (0 <=
- TALER_amount_add (&total,
- &total,
- &tdd->deposit_value));
- GNUNET_assert (0 <=
- TALER_amount_subtract (&total,
- &total,
- &tdd->deposit_fee));
- }
- if (0 !=
- TALER_amount_cmp (&total,
- &pts->credit_amount))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (pts->is);
- return;
- }
-#endif
- break;
- }
- case MHD_HTTP_ACCEPTED:
+ case MHD_HTTP_NO_CONTENT:
break;
case MHD_HTTP_UNAUTHORIZED:
break;
@@ -334,8 +187,6 @@ post_transfers_traits (void *cls,
TALER_TESTING_make_trait_fee (&pts->wire_fee),
TALER_TESTING_make_trait_exchange_url (
(const char **) &pts->exchange_url),
- TALER_TESTING_make_trait_timestamp (0,
- &pts->execution_time),
TALER_TESTING_make_trait_bank_row (&pts->serial),
TALER_TESTING_trait_end (),
};