summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2016-06-11 00:47:48 +0200
committerChristian Grothoff <christian@grothoff.org>2016-06-11 00:47:48 +0200
commit8c1dc58656d3d27184f51d2e7e6dcf2bf66d6081 (patch)
tree97cdf7f9d43231cd456ee21846469f19079b3344
parent0b502ddd4869022dcfe2816e30f7db2529ce1bed (diff)
downloadmerchant-8c1dc58656d3d27184f51d2e7e6dcf2bf66d6081.tar.gz
merchant-8c1dc58656d3d27184f51d2e7e6dcf2bf66d6081.tar.bz2
merchant-8c1dc58656d3d27184f51d2e7e6dcf2bf66d6081.zip
implement /track/transaction API and testcase
-rw-r--r--src/backend/taler-merchant-httpd_responses.c6
-rw-r--r--src/backend/taler-merchant-httpd_responses.h53
-rw-r--r--src/backend/taler-merchant-httpd_track-transaction.c8
-rw-r--r--src/include/taler_merchant_service.h66
-rw-r--r--src/lib/merchant_api_track_transaction.c112
-rw-r--r--src/lib/test_merchant_api.c39
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;i<num_transfers;i++)
{
- const struct TMH_TransactionWireTransfer *transfer = &transfers[i];
+ const struct TALER_MERCHANT_TransactionWireTransfer *transfer = &transfers[i];
json_t *j_coins;
unsigned int j;
j_coins = json_array ();
for (j=0;j<transfer->num_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 <jansson.h>
#include <microhttpd.h>
#include <pthread.h>
+/* 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
@@ -366,26 +366,70 @@ 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
@@ -66,6 +66,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;i<num_transfers;i++)
+ GNUNET_free (transfers[i].coins);
+}
+
+
+/**
+ * Handle #MHD_HTTP_OK response to /track/transaction.
+ * Parse @a json and if successful call the callback in @a tdo.
+ *
+ * @param tdo handle of the operation
+ * @param json json to parse
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+static int
+parse_track_transaction_ok (struct TALER_MERCHANT_TrackTransactionHandle *tdo,
+ const json_t *json)
+{
+ unsigned int num_transfers = json_array_size (json);
+ struct TALER_MERCHANT_TransactionWireTransfer transfers[num_transfers];
+ unsigned int i;
+
+ if (0 == num_transfers)
+ {
+ /* zero transfers is not a valid reply */
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ for (i=0;i<num_transfers;i++)
+ {
+ struct TALER_MERCHANT_TransactionWireTransfer *transfer = &transfers[i];
+ json_t *coins;
+ unsigned int j;
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_fixed_auto ("wtid", &transfer->wtid),
+ 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;j<transfer->num_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);