From 8c1dc58656d3d27184f51d2e7e6dcf2bf66d6081 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 11 Jun 2016 00:47:48 +0200 Subject: implement /track/transaction API and testcase --- src/backend/taler-merchant-httpd_responses.c | 6 +- src/backend/taler-merchant-httpd_responses.h | 53 +--------- .../taler-merchant-httpd_track-transaction.c | 8 +- src/include/taler_merchant_service.h | 66 ++++++++++-- src/lib/merchant_api_track_transaction.c | 112 +++++++++++++++++++-- src/lib/test_merchant_api.c | 39 ++++--- 6 files changed, 193 insertions(+), 91 deletions(-) diff --git a/src/backend/taler-merchant-httpd_responses.c b/src/backend/taler-merchant-httpd_responses.c index 5fed0dbf..60ba558c 100644 --- a/src/backend/taler-merchant-httpd_responses.c +++ b/src/backend/taler-merchant-httpd_responses.c @@ -373,7 +373,7 @@ TMH_RESPONSE_reply_arg_invalid (struct MHD_Connection *connection, */ struct MHD_Response * TMH_RESPONSE_make_track_transaction_ok (unsigned int num_transfers, - const struct TMH_TransactionWireTransfer *transfers) + const struct TALER_MERCHANT_TransactionWireTransfer *transfers) { struct MHD_Response *ret; unsigned int i; @@ -382,14 +382,14 @@ TMH_RESPONSE_make_track_transaction_ok (unsigned int num_transfers, j_transfers = json_array (); for (i=0;inum_coins;j++) { - const struct TMH_CoinWireTransfer *coin = &transfer->coins[j]; + const struct TALER_MERCHANT_CoinWireTransfer *coin = &transfer->coins[j]; json_array_append_new (j_coins, json_pack ("{s:o, s:o, s:o}", diff --git a/src/backend/taler-merchant-httpd_responses.h b/src/backend/taler-merchant-httpd_responses.h index c1bd5c8f..b79a0f4e 100644 --- a/src/backend/taler-merchant-httpd_responses.h +++ b/src/backend/taler-merchant-httpd_responses.h @@ -29,6 +29,8 @@ #include #include #include +/* just need some structs, not the actual API */ +#include "taler_merchant_service.h" /** * Make JSON response object. @@ -65,55 +67,6 @@ struct MHD_Response * TMH_RESPONSE_make_json_pack (const char *fmt, ...); -/** - * Information about a coin aggregated in a wire transfer for a - * /track/transaction response. - */ -struct TMH_CoinWireTransfer -{ - - /** - * Public key of the coin. - */ - struct TALER_CoinSpendPublicKeyP coin_pub; - - /** - * Value of the coin including deposit fee. - */ - struct TALER_Amount amount_with_fee; - - /** - * Deposit fee for the coin. - */ - struct TALER_Amount deposit_fee; - -}; - -/** - * Information about a wire transfer for a /track/transaction response. - */ -struct TMH_TransactionWireTransfer -{ - - /** - * Wire transfer identifier this struct is about. - */ - struct TALER_WireTransferIdentifierRawP wtid; - - /** - * Number of coins of the selected transaction that - * is covered by this wire transfer. - */ - unsigned int num_coins; - - /** - * Information about the coins of the selected transaction - * that are part of the wire transfer. - */ - struct TMH_CoinWireTransfer *coins; - -}; - /** * Generate /track/transaction response. @@ -124,7 +77,7 @@ struct TMH_TransactionWireTransfer */ struct MHD_Response * TMH_RESPONSE_make_track_transaction_ok (unsigned int num_transfers, - const struct TMH_TransactionWireTransfer *transfers); + const struct TALER_MERCHANT_TransactionWireTransfer *transfers); /** diff --git a/src/backend/taler-merchant-httpd_track-transaction.c b/src/backend/taler-merchant-httpd_track-transaction.c index 2df08a2d..8759c002 100644 --- a/src/backend/taler-merchant-httpd_track-transaction.c +++ b/src/backend/taler-merchant-httpd_track-transaction.c @@ -493,7 +493,7 @@ trace_coins (struct TrackTransactionContext *tctx) /* on-stack allocation is fine, as the number of coins and the number of wire-transfers per-transaction is expected to be tiny. */ struct MHD_Response *resp; - struct TMH_TransactionWireTransfer wts[num_wtid]; + struct TALER_MERCHANT_TransactionWireTransfer wts[num_wtid]; unsigned int wtid_off; wtid_off = 0; @@ -515,7 +515,7 @@ trace_coins (struct TrackTransactionContext *tctx) if (GNUNET_NO == found) { unsigned int num_coins; - struct TMH_TransactionWireTransfer *wt; + struct TALER_MERCHANT_TransactionWireTransfer *wt; wt = &wts[wtid_off++]; wt->wtid = tcc->wtid; @@ -531,7 +531,7 @@ trace_coins (struct TrackTransactionContext *tctx) /* initialize coins array */ wt->num_coins = num_coins; wt->coins = GNUNET_new_array (num_coins, - struct TMH_CoinWireTransfer); + struct TALER_MERCHANT_CoinWireTransfer); num_coins = 0; for (tcc2 = tctx->tcc_head; NULL != tcc2; tcc2 = tcc2->next) { @@ -539,7 +539,7 @@ trace_coins (struct TrackTransactionContext *tctx) &tcc2->wtid, sizeof (struct TALER_WireTransferIdentifierRawP))) { - struct TMH_CoinWireTransfer *coin = &wt->coins[num_coins++]; + struct TALER_MERCHANT_CoinWireTransfer *coin = &wt->coins[num_coins++]; coin->coin_pub = tcc2->coin_pub; coin->amount_with_fee = tcc2->amount_with_fee; diff --git a/src/include/taler_merchant_service.h b/src/include/taler_merchant_service.h index 51293744..d97d065e 100644 --- a/src/include/taler_merchant_service.h +++ b/src/include/taler_merchant_service.h @@ -365,27 +365,71 @@ TALER_MERCHANT_track_transfer_cancel (struct TALER_MERCHANT_TrackTransferHandle */ struct TALER_MERCHANT_TrackTransactionHandle; +/** + * Information about a coin aggregated in a wire transfer for a + * /track/transaction response. + */ +struct TALER_MERCHANT_CoinWireTransfer +{ + + /** + * Public key of the coin. + */ + struct TALER_CoinSpendPublicKeyP coin_pub; + + /** + * Value of the coin including deposit fee. + */ + struct TALER_Amount amount_with_fee; + + /** + * Deposit fee for the coin. + */ + struct TALER_Amount deposit_fee; + +}; + +/** + * Information about a wire transfer for a /track/transaction response. + */ +struct TALER_MERCHANT_TransactionWireTransfer +{ + + /** + * Wire transfer identifier this struct is about. + */ + struct TALER_WireTransferIdentifierRawP wtid; + + /** + * Number of coins of the selected transaction that + * is covered by this wire transfer. + */ + unsigned int num_coins; + + /** + * Information about the coins of the selected transaction + * that are part of the wire transfer. + */ + struct TALER_MERCHANT_CoinWireTransfer *coins; + +}; + + /** * Callbacks of this type are used to work the result of submitting a /track/transaction request to a merchant * * @param cls closure * @param http_status HTTP status code we got, 0 on exchange protocol violation - * @param sign_key exchange key used to sign @a json, or NULL - * @param json original json reply (may include signatures, those have then been - * validated already) - * @param wtid wire transfer identifier used by the exchange, NULL if exchange did not - * yet execute the transaction - * @param execution_time actual or planned execution time for the wire transfer - * @param coin_contribution contribution to the @a total_amount of the deposited coin (may be NULL) + * @param json original json reply from the backend + * @param num_transfers number of wire transfers the exchange used for the transaction + * @param transfers details about each transfer and which coins are aggregated in it */ typedef void (*TALER_MERCHANT_TrackTransactionCallback) (void *cls, unsigned int http_status, - const struct TALER_ExchangePublicKeyP *sign_key, const json_t *json, - const struct TALER_WireTransferIdentifierRawP *wtid, - struct GNUNET_TIME_Absolute execution_time, - const struct TALER_Amount *coin_contribution); + unsigned int num_transfers, + const struct TALER_MERCHANT_TransactionWireTransfer *transfers); /** diff --git a/src/lib/merchant_api_track_transaction.c b/src/lib/merchant_api_track_transaction.c index b05e3494..4c684d16 100644 --- a/src/lib/merchant_api_track_transaction.c +++ b/src/lib/merchant_api_track_transaction.c @@ -65,6 +65,102 @@ struct TALER_MERCHANT_TrackTransactionHandle }; +/** + * Free data in @a transfers. + * + * @param num_transfers length of the @a transfers array + * @param transfers information about wire transfers to free + */ +static void +free_transfers (unsigned int num_transfers, + struct TALER_MERCHANT_TransactionWireTransfer *transfers) +{ + unsigned int i; + + for (i=0;iwtid), + GNUNET_JSON_spec_json ("coins", &coins), + GNUNET_JSON_spec_end() + }; + + if (GNUNET_OK != + GNUNET_JSON_parse (json_array_get (json, i), + spec, + NULL, NULL)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + transfer->num_coins = json_array_size (coins); + transfer->coins = GNUNET_new_array (transfer->num_coins, + struct TALER_MERCHANT_CoinWireTransfer); + for (j=0;jnum_coins;j++) + { + struct TALER_MERCHANT_CoinWireTransfer *coin = &transfer->coins[j]; + struct GNUNET_JSON_Specification coin_spec[] = { + GNUNET_JSON_spec_fixed_auto ("coin_pub", &coin->coin_pub), + TALER_JSON_spec_amount ("amount_with_fee", &coin->amount_with_fee), + TALER_JSON_spec_amount ("deposit_fee", &coin->deposit_fee), + GNUNET_JSON_spec_end() + }; + if (GNUNET_OK != + GNUNET_JSON_parse (json_array_get (coins, j), + coin_spec, + NULL, NULL)) + { + GNUNET_break_op (0); + GNUNET_JSON_parse_free (spec); + free_transfers (i, + transfers); + return GNUNET_SYSERR; + } + } + GNUNET_JSON_parse_free (spec); + } + tdo->cb (tdo->cb_cls, + MHD_HTTP_OK, + json, + num_transfers, + transfers); + free_transfers (num_transfers, + transfers); + TALER_MERCHANT_track_transaction_cancel (tdo); + return GNUNET_OK; +} + + /** * Function called when we're done processing the * HTTP /track/transaction request. @@ -86,12 +182,11 @@ handle_track_transaction_finished (void *cls, case 0: break; case MHD_HTTP_OK: - { - /* Work out argument for external callback from the body .. */ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "200 returned from /track/transaction\n"); - /* FIXME: actually verify signature */ - } + if (GNUNET_OK == + parse_track_transaction_ok (tdo, + json)) + return; + response_code = 0; break; case MHD_HTTP_ACCEPTED: { @@ -117,13 +212,10 @@ handle_track_transaction_finished (void *cls, response_code = 0; break; } - /* FIXME: pass proper results back! */ tdo->cb (tdo->cb_cls, response_code, - NULL, json, - NULL, - GNUNET_TIME_UNIT_ZERO_ABS, + 0, NULL); TALER_MERCHANT_track_transaction_cancel (tdo); } diff --git a/src/lib/test_merchant_api.c b/src/lib/test_merchant_api.c index 2e608fd7..4b74c065 100644 --- a/src/lib/test_merchant_api.c +++ b/src/lib/test_merchant_api.c @@ -1089,22 +1089,16 @@ track_transfer_cb (void *cls, * * @param cls closure * @param http_status HTTP status code we got, 0 on exchange protocol violation - * @param sign_key exchange key used to sign @a json, or NULL - * @param json original json reply (may include signatures, those have then been - * validated already) - * @param wtid wire transfer identifier used by the exchange, NULL if exchange did not - * yet execute the transaction - * @param execution_time actual or planned execution time for the wire transfer - * @param coin_contribution contribution to the @a total_amount of the deposited coin (may be NULL) + * @param json original json reply + * @param num_transfers number of wire transfers involved in setting the transaction + * @param transfers detailed list of transfers involved and their coins */ static void track_transaction_cb (void *cls, unsigned int http_status, - const struct TALER_ExchangePublicKeyP *sign_key, const json_t *json, - const struct TALER_WireTransferIdentifierRawP *wtid, - struct GNUNET_TIME_Absolute execution_time, - const struct TALER_Amount *coin_contribution) + unsigned int num_transfers, + const struct TALER_MERCHANT_TransactionWireTransfer *transfers) { struct InterpreterState *is = cls; struct Command *cmd = &is->commands[is->ip]; @@ -1127,12 +1121,20 @@ track_transaction_cb (void *cls, { const struct Command *ref; struct TALER_Amount ea; + struct TALER_Amount coin_contribution; + if (1 != num_transfers) + { + GNUNET_break (0); + json_dumpf (json, stderr, 0); + fail (is); + return; + } ref = find_command (is, cmd->details.track_transaction.expected_transfer_ref); GNUNET_assert (NULL != ref); if (0 != memcmp (&ref->details.check_bank_transfer.wtid, - wtid, + &transfers[0].wtid, sizeof (struct TALER_WireTransferIdentifierRawP))) { GNUNET_break (0); @@ -1144,12 +1146,23 @@ track_transaction_cb (void *cls, single coin involved in a pay/deposit. Thus, this invariant may not always hold in the future depending no how the testcases evolve. */ + if (1 != transfers[0].num_coins) + { + GNUNET_break (0); + json_dumpf (json, stderr, 0); + fail (is); + return; + } GNUNET_assert (GNUNET_OK == TALER_string_to_amount (ref->details.check_bank_transfer.amount, &ea)); + GNUNET_assert (GNUNET_OK == + TALER_amount_subtract (&coin_contribution, + &transfers[0].coins[0].amount_with_fee, + &transfers[0].coins[0].deposit_fee)); if (0 != TALER_amount_cmp (&ea, - coin_contribution)) + &coin_contribution)) { GNUNET_break (0); json_dumpf (json, stderr, 0); -- cgit v1.2.3