diff options
author | Christian Grothoff <christian@grothoff.org> | 2024-01-28 14:13:31 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2024-01-28 14:17:44 +0100 |
commit | d5398b862f7c80bc02c8b10ab61500dd48ae1925 (patch) | |
tree | f655f9ba43b32aa8500a9f29ca445e69447d59b6 | |
parent | 159591d0be133ac8d5537ef4a8ae9e55aa813443 (diff) |
add -T option for deposit check, fix memory leaks, be more strict about validating credit facade URL upon POST, expand test case
-rw-r--r-- | src/backend/taler-merchant-depositcheck.c | 2 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_config.c | 8 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_private-post-account.c | 26 | ||||
-rw-r--r-- | src/bank/mb_parse.c | 6 | ||||
-rwxr-xr-x | src/testing/test_merchant_transfer_tracking.sh | 323 |
5 files changed, 332 insertions, 33 deletions
diff --git a/src/backend/taler-merchant-depositcheck.c b/src/backend/taler-merchant-depositcheck.c index 9576f04b..90fbeb6e 100644 --- a/src/backend/taler-merchant-depositcheck.c +++ b/src/backend/taler-merchant-depositcheck.c @@ -999,6 +999,8 @@ main (int argc, "BASE_URL", "limit us to checking deposits of this exchange", &exchange_url), + GNUNET_GETOPT_option_timetravel ('T', + "timetravel"), GNUNET_GETOPT_option_flag ('t', "test", "run in test mode and exit when idle", diff --git a/src/backend/taler-merchant-httpd_config.c b/src/backend/taler-merchant-httpd_config.c index d53554f6..87278116 100644 --- a/src/backend/taler-merchant-httpd_config.c +++ b/src/backend/taler-merchant-httpd_config.c @@ -42,8 +42,7 @@ * #MERCHANT_PROTOCOL_CURRENT and #MERCHANT_PROTOCOL_AGE in * merchant_api_config.c! */ -#define MERCHANT_PROTOCOL_VERSION "6:0:2" - +#define MERCHANT_PROTOCOL_VERSION "6:1:2" /** @@ -95,7 +94,7 @@ MH_handler_config (struct TMH_RequestHandler *rh, GNUNET_assert (NULL != exchanges); TMH_exchange_get_trusted (&add_exchange, exchanges); - for (unsigned int i=0;i<TMH_num_cspecs;i++) + for (unsigned int i = 0; i<TMH_num_cspecs; i++) { const struct TALER_CurrencySpecification *cspec = &TMH_cspecs[i]; @@ -103,7 +102,8 @@ MH_handler_config (struct TMH_RequestHandler *rh, GNUNET_assert (0 == json_object_set_new (specs, cspec->currency, - TALER_CONFIG_currency_specs_to_json (cspec))); + TALER_CONFIG_currency_specs_to_json ( + cspec))); } response = TALER_MHD_MAKE_JSON_PACK ( GNUNET_JSON_pack_string ("currency", diff --git a/src/backend/taler-merchant-httpd_private-post-account.c b/src/backend/taler-merchant-httpd_private-post-account.c index 7c9ffa0f..b5b1d527 100644 --- a/src/backend/taler-merchant-httpd_private-post-account.c +++ b/src/backend/taler-merchant-httpd_private-post-account.c @@ -41,7 +41,7 @@ TMH_private_post_account (const struct TMH_RequestHandler *rh, const char *uri; struct GNUNET_JSON_Specification ispec[] = { TALER_JSON_spec_payto_uri ("payto_uri", - &uri), + &uri), GNUNET_JSON_spec_mark_optional ( TALER_JSON_spec_web_url ("credit_facade_url", &credit_facade_url), @@ -165,17 +165,21 @@ TMH_private_post_account (const struct TMH_RequestHandler *rh, { TMH_wire_method_free (wm); GNUNET_free (adx.payto_uri); - return TALER_MHD_REPLY_JSON_PACK (connection, - MHD_HTTP_OK, - GNUNET_JSON_pack_data_auto ( - "salt", - &adx. - salt), - GNUNET_JSON_pack_data_auto ( - "h_wire", - &adx. - h_wire)); + GNUNET_free (adx.credit_facade_url); + json_decref (adx.credit_facade_credentials); + return TALER_MHD_REPLY_JSON_PACK ( + connection, + MHD_HTTP_OK, + GNUNET_JSON_pack_data_auto ( + "salt", + &adx.salt), + GNUNET_JSON_pack_data_auto ( + "h_wire", + &adx.h_wire)); } + GNUNET_free (adx.payto_uri); + GNUNET_free (adx.credit_facade_url); + json_decref (adx.credit_facade_credentials); break; case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: case GNUNET_DB_STATUS_SOFT_ERROR: diff --git a/src/bank/mb_parse.c b/src/bank/mb_parse.c index 275fdc92..c05ea133 100644 --- a/src/bank/mb_parse.c +++ b/src/bank/mb_parse.c @@ -134,6 +134,12 @@ TALER_MERCHANT_BANK_auth_parse_json ( GNUNET_break_op (0); return GNUNET_SYSERR; } + if ( (0 == strlen (backend_url)) || + ('/' != backend_url[strlen (backend_url) - 1]) ) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } auth->wire_gateway_url = GNUNET_strdup (backend_url); method = json_string_value (json_object_get (cred, "type")); diff --git a/src/testing/test_merchant_transfer_tracking.sh b/src/testing/test_merchant_transfer_tracking.sh index 6be6b7a5..6efaa09c 100755 --- a/src/testing/test_merchant_transfer_tracking.sh +++ b/src/testing/test_merchant_transfer_tracking.sh @@ -1,6 +1,6 @@ #!/bin/bash # This file is part of TALER -# Copyright (C) 2014-2023 Taler Systems SA +# Copyright (C) 2014-2024 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 @@ -16,7 +16,7 @@ # License along with TALER; see the file COPYING. If not, see # <http://www.gnu.org/licenses/> # -# Testcase for #6912 (failed to reproduce so far) +# Testcase for #6912 and #8061 set -eu @@ -153,7 +153,7 @@ echo -n "Configuring merchant test instance ..." STATUS=$(curl -H "Content-Type: application/json" -X POST \ -H 'Authorization: Bearer secret-token:super_secret' \ http://localhost:9966/management/instances \ - -d '{"auth":{"method":"external"},"id":"test","name":"default","user_type":"business","address":{},"jurisdiction":{},"use_stefan":true,"default_wire_transfer_delay":{"d_us" : 50000000},"default_pay_delay":{"d_us": 60000000}}' \ + -d '{"auth":{"method":"external"},"id":"test","name":"test","user_type":"business","address":{},"jurisdiction":{},"use_stefan":true,"default_wire_transfer_delay":{"d_us" : 50000000},"default_pay_delay":{"d_us": 60000000}}' \ -w "%{http_code}" -s -o /dev/null) if [ "$STATUS" != "204" ] @@ -163,24 +163,14 @@ fi STATUS=$(curl -H "Content-Type: application/json" -X POST \ -H 'Authorization: Bearer secret-token:super_secret' \ http://localhost:9966/instances/test/private/accounts \ - -d '{"payto_uri":"'"$SURVEY_PAYTO"'"}' \ + -d '{"payto_uri":"'"$SURVEY_PAYTO"'","credit_facade_url":"http://localhost:8082/accounts/survey/taler-revenue/","credit_facade_credentials":{"type":"basic","username":"survey","password":"x"}}' \ -w "%{http_code}" -s -o /dev/null) if [ "$STATUS" != "200" ] then exit_fail "Expected 200 OK. Got: $STATUS" fi -STATUS=$(curl -H "Content-Type: application/json" -X POST \ - -H 'Authorization: Bearer secret-token:super_secret' \ - http://localhost:9966/instances/test/private/accounts \ - -d '{"payto_uri":"'"$TUTORIAL_PAYTO"'"}' \ - -w "%{http_code}" -s -o /dev/null) -if [ "$STATUS" != "200" ] -then - exit_fail "Expected 200 OK. Got: $STATUS" -fi -echo "OK" # CREATE ORDER AND SELL IT echo -n "Creating order to be paid..." @@ -268,8 +258,8 @@ TARGET=$(echo "$TARGET_PAYTO" | awk -F = '{print $2}') if echo "$SURVEY_PAYTO" | grep -q "$TARGET" > /dev/null; then TARGET_PAYTO="$SURVEY_PAYTO"; fi -if echo "$TUTORIAL_PAYTO" | grep -q "$TARGET" > /dev/null; then - TARGET_PAYTO="$TUTORIAL_PAYTO"; +if echo "$SURVEY_PAYTO" | grep -q "$TARGET" > /dev/null; then + TARGET_PAYTO="$SURVEY_PAYTO"; fi if [ "$EXCHANGE_URL" != "$WURL" ] then @@ -318,7 +308,7 @@ fi echo "OK" echo -n "Fetching running taler-merchant-exchange on bogus transfer ..." -taler-merchant-exchange -c $CONF -L INFO -t &> taler-merchant-exchange-bad.log +taler-merchant-exchange -c "$CONF" -L INFO -t &> taler-merchant-exchange-bad.log echo "OK" echo -n "Fetching wire transfers of 'test' instance ..." @@ -403,7 +393,177 @@ fi echo "OK" echo -n "Checking order status ..." -STATUS=$(curl "http://localhost:9966/instances/test/private/orders/${ORDER_ID}?transfer=YES" \ +STATUS=$(curl "http://localhost:9966/instances/test/private/orders/${ORDER_ID}" \ + -w "%{http_code}" -s -o "$LAST_RESPONSE") + +if [ "$STATUS" != "200" ] +then + jq . < "$LAST_RESPONSE" + exit_fail "Expected 200 ok, after order inquiry. got: $STATUS" +fi + +WAS_WIRED=$(jq -r .wired < "$LAST_RESPONSE") + +if [ "$WAS_WIRED" != "true" ] +then + jq . < "$LAST_RESPONSE" + exit_fail ".wired false, expected true" +fi + +echo " OK" + + +echo "================== 2nd order ====================== " + + + +# CREATE ORDER AND SELL IT +echo -n "Creating 2nd order to be paid..." +STATUS=$(curl 'http://localhost:9966/instances/test/private/orders' \ + -d '{"order":{"amount":"TESTKUDOS:2","summary":"payme"}}' \ + -w "%{http_code}" -s -o "$LAST_RESPONSE") + +if [ "$STATUS" != "200" ] +then + cat "$LAST_RESPONSE" + exit_fail "Expected 200 ok, order created. got: $STATUS" +fi + +ORDER_ID=$(jq -e -r .order_id < "$LAST_RESPONSE") +#TOKEN=$(jq -e -r .token < "$LAST_RESPONSE") + +STATUS=$(curl "http://localhost:9966/instances/test/private/orders/${ORDER_ID}" \ + -w "%{http_code}" -s -o "$LAST_RESPONSE") + +if [ "$STATUS" != "200" ] +then + cat "$LAST_RESPONSE" + exit_fail "Expected 200 ok, getting order info before claming it. got: $STATUS" +fi +PAY_URL=$(jq -e -r .taler_pay_uri < "$LAST_RESPONSE") +echo "OK" + +NOW=$(date +%s) +echo -n "Pay second order ..." +taler-wallet-cli \ + --no-throttle \ + --wallet-db="$WALLET_DB" \ + handle-uri "${PAY_URL}" \ + -y \ + 2> wallet-pay2.err > wallet-pay2.log +NOW2=$(date +%s) +echo " OK (took $(( NOW2 - NOW )) secs)" + +STATUS=$(curl "http://localhost:9966/instances/test/private/orders/${ORDER_ID}" \ + -w "%{http_code}" -s -o "$LAST_RESPONSE") + +if [ "$STATUS" != "200" ] +then + cat "$LAST_RESPONSE" + exit_fail "Expected 200 ok, after pay. got: $STATUS" +fi + +ORDER_STATUS=$(jq -r .order_status < "$LAST_RESPONSE") + +if [ "$ORDER_STATUS" != "paid" ] +then + cat "$LAST_RESPONSE" + exit_fail "Expected 'paid'. got: $ORDER_STATUS" +fi + +# +# WIRE TRANSFER TO MERCHANT AND NOTIFY BACKEND +# + +#PAY_DEADLINE=$(jq -r .contract_terms.pay_deadline.t_s < "$LAST_RESPONSE") +WIRE_DEADLINE=$(jq -r .contract_terms.wire_transfer_deadline.t_s < "$LAST_RESPONSE") + +NOW=$(date +%s) + +TO_SLEEP=$(( WIRE_DEADLINE - NOW )) +echo "waiting $TO_SLEEP secs for wire transfer" + +echo -n "Pre-check for exchange deposit ..." +taler-merchant-depositcheck -c $CONF -t -L INFO &> depositcheck2a.log +echo " DONE" + +echo -n "Perform wire transfers ..." +taler-exchange-aggregator -y -c $CONF -T ${TO_SLEEP}000000 -t -L INFO &> aggregator2.log +taler-exchange-transfer -c $CONF -t -L INFO &> transfer2.log +echo " DONE" + +echo -n "Post-check for exchange deposit ..." +taler-merchant-depositcheck -c $CONF -t -T ${TO_SLEEP}000000 -L INFO &> depositcheck2b.log +echo " DONE" + + +echo -n "Obtaining wire transfer details from bank..." + +BANKDATA="$(curl 'http://localhost:8082/accounts/exchange/taler-wire-gateway/history/outgoing?delta=2' -s)" + +WTID=$(echo "$BANKDATA" | jq -r .outgoing_transactions[1].wtid) +WURL=$(echo "$BANKDATA" | jq -r .outgoing_transactions[1].exchange_base_url) +CREDIT_AMOUNT=$(echo "$BANKDATA" | jq -r .outgoing_transactions[1].amount) +TARGET_PAYTO=$(echo "$BANKDATA" | jq -r .outgoing_transactions[1].credit_account) +TARGET=$(echo "$TARGET_PAYTO" | awk -F = '{print $2}') + +# Figure out which account got paid, in order to +# resort the right (and complete: including the receiver-name) +# TARGET_PAYTO +if echo "$SURVEY_PAYTO" | grep -q "$TARGET" > /dev/null; then + TARGET_PAYTO="$SURVEY_PAYTO"; +fi +if echo "$SURVEY_PAYTO" | grep -q "$TARGET" > /dev/null; then + TARGET_PAYTO="$SURVEY_PAYTO"; +fi +if [ "$EXCHANGE_URL" != "$WURL" ] +then + exit_fail "Wrong exchange URL in subject '$SUBJECT', expected $EXCHANGE_URL" +fi +echo " OK" + +echo -n "Notifying merchant of correct wire transfer in the correct instance..." +#this time in the correct instance so the order will be marked as wired... + +STATUS=$(curl 'http://localhost:9966/instances/test/private/transfers' \ + -d '{"credit_amount":"'"$CREDIT_AMOUNT"'","wtid":"'"$WTID"'","payto_uri":"'"$TARGET_PAYTO"'","exchange_url":"'"$WURL"'"}' \ + -m 3 \ + -w "%{http_code}" -s -o "$LAST_RESPONSE") + +if [ "$STATUS" != "204" ] +then + jq . < "$LAST_RESPONSE" + exit_fail "Expected response 204 no content, after providing transfer data. got: $STATUS" +fi +echo " OK" + +echo -n "Fetching running taler-merchant-exchange on good transfer ..." +taler-merchant-exchange -c $CONF -L INFO -t &> taler-merchant-exchange2.log +echo "OK" + +echo -n "Fetching wire transfers of TEST instance ..." + +STATUS=$(curl 'http://localhost:9966/instances/test/private/transfers' \ + -w "%{http_code}" -s -o "$LAST_RESPONSE") + +if [ "$STATUS" != "200" ] +then + jq . < "$LAST_RESPONSE" + exit_fail "Expected response 200 Ok. got: $STATUS" +fi + +TRANSFERS_LIST_SIZE=$(jq -r '.transfers | length' < "$LAST_RESPONSE") + +if [ "$TRANSFERS_LIST_SIZE" != "2" ] +then + jq . < "$LAST_RESPONSE" + exit_fail "Expected two transfers. got: $TRANSFERS_LIST_SIZE" +fi + +echo "OK" + +echo -n "Checking order status ..." +STATUS=$(curl "http://localhost:9966/instances/test/private/orders/${ORDER_ID}" \ -w "%{http_code}" -s -o "$LAST_RESPONSE") if [ "$STATUS" != "200" ] @@ -422,4 +582,131 @@ fi echo " OK" +echo "================== 3rd order ====================== " + +# CREATE ORDER AND SELL IT +echo -n "Creating 3nd order to be paid..." +STATUS=$(curl 'http://localhost:9966/instances/test/private/orders' \ + -d '{"order":{"amount":"TESTKUDOS:3","summary":"payme"}}' \ + -w "%{http_code}" -s -o "$LAST_RESPONSE") + +if [ "$STATUS" != "200" ] +then + cat "$LAST_RESPONSE" + exit_fail "Expected 200 ok, order created. got: $STATUS" +fi + +ORDER_ID=$(jq -e -r .order_id < "$LAST_RESPONSE") +#TOKEN=$(jq -e -r .token < "$LAST_RESPONSE") + +STATUS=$(curl "http://localhost:9966/instances/test/private/orders/${ORDER_ID}" \ + -w "%{http_code}" -s -o "$LAST_RESPONSE") + +if [ "$STATUS" != "200" ] +then + cat "$LAST_RESPONSE" + exit_fail "Expected 200 ok, getting order info before claming it. got: $STATUS" +fi +PAY_URL=$(jq -e -r .taler_pay_uri < "$LAST_RESPONSE") +echo "OK" + +NOW=$(date +%s) +echo -n "Pay third order ..." +taler-wallet-cli \ + --no-throttle \ + --wallet-db="$WALLET_DB" \ + handle-uri "${PAY_URL}" \ + -y \ + 2> wallet-pay2.err > wallet-pay2.log +NOW2=$(date +%s) +echo " OK (took $(( NOW2 - NOW )) secs)" + +STATUS=$(curl "http://localhost:9966/instances/test/private/orders/${ORDER_ID}" \ + -w "%{http_code}" -s -o "$LAST_RESPONSE") + +if [ "$STATUS" != "200" ] +then + cat "$LAST_RESPONSE" + exit_fail "Expected 200 ok, after pay. got: $STATUS" +fi + +ORDER_STATUS=$(jq -r .order_status < "$LAST_RESPONSE") + +if [ "$ORDER_STATUS" != "paid" ] +then + cat "$LAST_RESPONSE" + exit_fail "Expected 'paid'. got: $ORDER_STATUS" +fi + +# +# WIRE TRANSFER TO MERCHANT AND NOTIFY BACKEND +# + +#PAY_DEADLINE=$(jq -r .contract_terms.pay_deadline.t_s < "$LAST_RESPONSE") +WIRE_DEADLINE=$(jq -r .contract_terms.wire_transfer_deadline.t_s < "$LAST_RESPONSE") + +NOW=$(date +%s) + +TO_SLEEP=$(( WIRE_DEADLINE - NOW )) +echo "waiting $TO_SLEEP secs for wire transfer" + +echo -n "Perform wire transfers ..." +taler-exchange-aggregator -y -c $CONF -T ${TO_SLEEP}000000 -t -L INFO &> aggregator3.log +taler-exchange-transfer -c $CONF -t -L INFO &> transfer3.log +echo " DONE" + +echo -n "Running taler-merchant-wirewatch to check transfer ..." +taler-merchant-wirewatch -c $CONF -t -L INFO &> taler-merchant-wirewatch.log +echo " DONE" + +echo -n "Post-wirewatch check for exchange deposit ..." +taler-merchant-depositcheck -c $CONF -t -T ${TO_SLEEP}000000 -L INFO &> depositcheck2b.log +echo " DONE" + +echo -n "Fetching wire transfers of TEST instance ..." + +STATUS=$(curl 'http://localhost:9966/instances/test/private/transfers' \ + -w "%{http_code}" -s -o "$LAST_RESPONSE") + +if [ "$STATUS" != "200" ] +then + jq . < "$LAST_RESPONSE" + exit_fail "Expected response 200 Ok. got: $STATUS" +fi + +TRANSFERS_LIST_SIZE=$(jq -r '.transfers | length' < "$LAST_RESPONSE") + +if [ "$TRANSFERS_LIST_SIZE" != "3" ] +then + jq . < "$LAST_RESPONSE" + exit_fail "Expected three transfers. got: $TRANSFERS_LIST_SIZE" +fi + +echo "OK" + +echo -n "Fetching running taler-merchant-exchange on good transfer ..." +taler-merchant-exchange -c $CONF -L INFO -t &> taler-merchant-exchange2.log +echo "OK" + +echo -n "Checking order status ..." +STATUS=$(curl "http://localhost:9966/instances/test/private/orders/${ORDER_ID}" \ + -w "%{http_code}" -s -o "$LAST_RESPONSE") + +if [ "$STATUS" != "200" ] +then + jq . < "$LAST_RESPONSE" + exit_fail "Expected 200 ok, after order inquiry. got: $STATUS" +fi + +WAS_WIRED=$(jq -r .wired < "$LAST_RESPONSE") + +if [ "$WAS_WIRED" != "true" ] +then + jq . < "$LAST_RESPONSE" + exit_fail ".wired false, expected true" +fi + +echo " OK" + + exit 0 |