View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0010959 | Taler | merchant backoffice SPA | public | 2026-01-31 20:55 | 2026-03-30 19:25 |
| Reporter | Christian Grothoff | Assigned To | Christian Grothoff | ||
| Priority | high | Severity | block | Reproducibility | always |
| Status | feedback | Resolution | open | ||
| Platform | i7 | OS | Debian GNU/Linux | OS Version | squeeze |
| Product Version | git (master) | ||||
| Target Version | 1.8 | ||||
| Summary | 0010959: Cannot "cancel" dialog "Confirm the wire transfer" | ||||
| Description | When clicking on an unconfirmed wire transfer (after selecting the wire transfer in the "Incoming wire transfers" list), the "cancel" and both "X" buttons do not work at all. | ||||
| Steps To Reproduce | Pay an order, wait for the wire transfer deadline, give the merchant backend a chance to fetch the WTID, click on the transfer. (note: I did SIGSTOP taler-exchange-transfer when producing the issue, but that should be orthogonal). | ||||
| Tags | design-required | ||||
|
|
Ah, one key detail: taler-merchant-reconciliation was NOT running, so there was no *amount* available. Once I started taler-merchant-reconciliation, the 'cancel' button started to work. So to reproduce, run the merchant backend without taler-merchant-reconciliation! (also, if the amount is not available, it should probably be *impossible* to confirm the wire transfer, basically, disable the "confirm" case with a hint/message like "Awaiting amount, make sure taler-merchant-reconciliation is running" somewhere.). |
|
|
Vlada: how to best explain to the user that they cannot confirm while the total amount remains unknown and that this is likely because some merchant service is not running properly -- I leave that to you. I'd probably just put some yellow bar into the dialog explaining this with way too much English text. After all, the case _should_ be uncommon. |
|
|
I can't reproduce this and there is no link between canceling/removing the dialog with the running services server side. Those actions doesn't trigger any http request. What if "verified": false ? This is like an error state because merchant calculation doesn't match with the exchange wire transfer amount, should the merchant still be able to confirm? |
|
|
I tried many ways. 1) Stopping reconciliation, confirm a wire transfer (worked) and try to reproduce. Nothing 2) Stopping httpd, confirm (failed) and try to reproduce. Nothing (dialog closes ok), http request fail but spa keeps working ok. 3) Starting again httpd, confirm (ok) and try to reproduce. Nothing Without reloading SPA. It could happen that an error was thrown and the SPA internal state was screw up, in this cases the console in the browser's developer tools should be good to check (if there isn't ANY error on the screen, which is weird). |
|
|
Yes, I also cannot reproduce it anymore. What I'm sure of is that I was testing against an older version (it looked different), so the bug is fixed. However, there is still a problem in the UX. If you run the attached shell script and open localhost:9966 when it shells-out to bash, you can see it: (1) The confirmed wire transfers into bank account has initially a button "Details". When you click on it, you get interesting details (good!). (2) On the details page, you can then "confirm" the wire transfer. However, after you do (2), the "Details" button is replaced with a "checkmark" and you cannot go see the details again. What I had wanted to see is a bit different: (1) The confirmed wire transfer details list is clickable on the "ID" field (which should be underlined in blue to indicate it is a link!), as the ID is what is linked to the details. That should ALWAYS be clickable, even for confirmed transfers. (2) The "confirm" button should be where we have the "details" button right now, to make it super-fast and easy to confirm wire transfers (basically turning the "confirm" button into a "checkmark"). I don't need the details to confirm, the date, amount and subject are all that is needed! @Vlada: please confirm this would be better, then re-assign to sebastian to implement! test_b10959.sh (8,774 bytes)
#!/bin/bash
# This file is in the public domain.
set -eu
function clean_wallet() {
rm -f "${WALLET_DB}"
exit_cleanup
}
# Replace with 0 for nexus...
USE_FAKEBANK=1
if [ 1 = "$USE_FAKEBANK" ]
then
ACCOUNT="exchange-account-2"
BANK_FLAGS="-f -d x-taler-bank -u $ACCOUNT"
BANK_URL="http://localhost:8082/"
else
ACCOUNT="exchange-account-1"
BANK_FLAGS="-ns -d iban -u $ACCOUNT"
BANK_URL="http://localhost:8082/"
echo -n "Testing for libeufin-bank"
libeufin-bank --help >/dev/null </dev/null || exit_skip " MISSING"
echo " FOUND"
fi
. setup.sh
echo -n "Testing for taler-harness"
taler-harness --help >/dev/null </dev/null || exit_skip " MISSING"
echo " FOUND"
# Launch exchange, merchant and bank.
setup -c "test_template.conf" \
-r "merchant-exchange-default" \
-em \
$BANK_FLAGS
LAST_RESPONSE=$(mktemp -p "${TMPDIR:-/tmp}" test_response.conf-XXXXXX)
CONF="test_template.conf.edited"
WALLET_DB=$(mktemp -p "${TMPDIR:-/tmp}" test_wallet.json-XXXXXX)
EXCHANGE_URL="http://localhost:8081/"
# Install cleanup handler (except for kill -9)
trap clean_wallet EXIT
echo -n "First prepare wallet with coins ..."
rm -f "$WALLET_DB"
taler-wallet-cli \
--no-throttle \
--wallet-db="$WALLET_DB" \
api \
--expect-success 'withdrawTestBalance' \
"$(jq -n '
{
amount: "TESTKUDOS:99",
corebankApiBaseUrl: $BANK_URL,
exchangeBaseUrl: $EXCHANGE_URL
}' \
--arg BANK_URL "${BANK_URL}" \
--arg EXCHANGE_URL "$EXCHANGE_URL"
)" 2>wallet-withdraw-1.err >wallet-withdraw-1.out
echo -n "."
# FIXME-MS: add logic to have nexus check immediately here.
# sleep 10
echo -n "."
# NOTE: once libeufin can do long-polling, we should
# be able to reduce the delay here and run wirewatch
# always in the background via setup
taler-exchange-wirewatch \
-a "$ACCOUNT" \
-L "INFO" \
-c "$CONF" \
-t &> taler-exchange-wirewatch.out
echo -n "."
timeout 60 taler-wallet-cli \
--wallet-db="$WALLET_DB" \
run-until-done \
2>wallet-withdraw-finish-1.err \
>wallet-withdraw-finish-1.out
echo " OK"
CURRENCY_COUNT=$(taler-wallet-cli --wallet-db="$WALLET_DB" balance | jq '.balances|length')
if [ "$CURRENCY_COUNT" = "0" ]
then
exit_fail "Expected least one currency, withdrawal failed. check log."
fi
#
# CREATE INSTANCE FOR TESTING
#
echo -n "Configuring merchant 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":"admin","name":"default","user_type":"business","address":{},"jurisdiction":{},"use_stefan":true,"default_wire_transfer_delay":{"d_us" : 50000000000},"default_pay_delay":{"d_us": 60000000000}}' \
-w "%{http_code}" -s -o /dev/null)
if [ "$STATUS" != "204" ]
then
exit_fail "Expected '204 No content' response. Got instead $STATUS"
fi
echo "Ok"
echo -n "Configuring merchant account ..."
if [ 1 = "$USE_FAKEBANK" ]
then
FORTYTHREE="payto://x-taler-bank/localhost/fortythree?receiver-name=fortythree"
else
FORTYTHREE=$(get_payto_uri fortythree x)
fi
# create with 2 bank account addresses
STATUS=$(curl -H "Content-Type: application/json" -X POST \
-H 'Authorization: Bearer secret-token:super_secret' \
http://localhost:9966/private/accounts \
-d '{"payto_uri":"'"$FORTYTHREE"'"}' \
-w "%{http_code}" -s -o /dev/null)
if [ "$STATUS" != "200" ]
then
exit_fail "Expected '200 OK' response. Got instead $STATUS"
fi
STATUS=$(curl -H "Content-Type: application/json" -X POST \
-H 'Authorization: Bearer secret-token:super_secret' \
http://localhost:9966/private/accounts \
-d '{"payto_uri":"payto://iban/SANDBOXX/DE270744?receiver-name=Forty+Four"}' \
-w "%{http_code}" -s -o /dev/null)
if [ "$STATUS" != "200" ]
then
exit_fail "Expected '200 OK' response. Got instead $STATUS"
fi
echo "Ok"
echo -n "Get accounts..."
STATUS=$(curl http://localhost:9966/private/accounts \
-w "%{http_code}" -s -o "$LAST_RESPONSE")
PAY_URI=$(jq -r .accounts[1].payto_uri < "$LAST_RESPONSE")
H_WIRE=$(jq -r .accounts[1].h_wire < "$LAST_RESPONSE")
if [ "$PAY_URI" != "payto://iban/SANDBOXX/DE270744?receiver-name=Forty+Four" ]
then
cat "$LAST_RESPONSE" >&2
exit_fail "Expected second payto URI. Got $PAY_URI"
fi
echo "OK"
# remove one account address
echo -n "Deleting one account ..."
STATUS=$(curl -H "Content-Type: application/json" -X PATCH \
-H 'Authorization: Bearer secret-token:super_secret' \
"http://localhost:9966/private/accounts/${H_WIRE}" \
-X DELETE \
-w "%{http_code}" -s -o /dev/null)
if [ "$STATUS" != "204" ]
then
exit_fail "Expected '204 No content' for deletion of ${H_WIRE}. Got instead: $STATUS"
fi
echo "OK"
# CREATE ORDER AND SELL IT
echo -n "Creating order to be paid..."
STATUS=$(curl 'http://localhost:9966/private/orders' \
-d '{"refund_delay":{"d_us":0},"order":{"amount":"TESTKUDOS:1","summary":"payme"}}' \
-w "%{http_code}" -s -o "$LAST_RESPONSE")
if [ "$STATUS" != "200" ]
then
jq . < "$LAST_RESPONSE"
exit_fail "Expected 200, 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/private/orders/${ORDER_ID}" \
-w "%{http_code}" -s -o "$LAST_RESPONSE")
if [ "$STATUS" != "200" ]
then
jq . < "$LAST_RESPONSE"
exit_fail "Expected 200, getting order info. got: $STATUS"
fi
PAY_URL=$(jq -e -r .taler_pay_uri < "$LAST_RESPONSE")
echo "OK"
NOW=$(date +%s)
echo -n "Pay first order ${PAY_URL} ..."
taler-wallet-cli \
--no-throttle \
--wallet-db="$WALLET_DB" \
handle-uri "${PAY_URL}" \
-y 2> wallet-pay1.err > wallet-pay1.log
timeout 60 taler-wallet-cli \
--no-throttle \
--wallet-db="$WALLET_DB" \
run-until-done 2> wallet-finish-pay1.err > wallet-finish-pay1.log
NOW2=$(date +%s)
echo " OK (took $(( NOW2 - NOW )) secs )"
STATUS=$(curl "http://localhost:9966/private/orders/${ORDER_ID}" \
-w "%{http_code}" -s -o "$LAST_RESPONSE")
if [ "$STATUS" != "200" ]
then
jq . < "$LAST_RESPONSE"
exit_fail "Expected 200, after pay. got: $STATUS"
fi
ORDER_STATUS=$(jq -r .order_status < "$LAST_RESPONSE")
if [ "$ORDER_STATUS" != "paid" ]
then
jq . < "$LAST_RESPONSE"
exit_fail "Order status should be '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=$((1200 + WIRE_DEADLINE - NOW ))
echo "Waiting $TO_SLEEP secs for wire transfer"
echo -n "Call taler-exchange-aggregator ..."
taler-exchange-aggregator \
-y \
-c "$CONF" \
-T "${TO_SLEEP}"000000 \
-t \
-L INFO &> aggregator.log
echo " DONE"
echo -n "Call taler-exchange-transfer ..."
taler-exchange-transfer \
-c "$CONF" \
-t \
-L INFO &> transfer.log
echo " DONE"
echo -n "Give time to Nexus to route the payment to Sandbox..."
# FIXME: trigger immediate update at nexus
# NOTE: once libeufin can do long-polling, we should
# be able to reduce the delay here and run aggregator/transfer
# always in the background via setup
sleep 3
echo " DONE"
echo -n "Running taler-merchant-depositcheck ..."
set -e
taler-merchant-depositcheck \
-L INFO \
-c "$CONF" \
-T "${TO_SLEEP}"000000 \
-t &> taler-merchant-depositcheck.log
echo " OK"
echo -n "Running taler-merchant-reconciliation ..."
set -e
taler-merchant-reconciliation \
-L INFO \
-c "$CONF" \
-T "${TO_SLEEP}"000000 \
-t &> taler-merchant-reconciliation.log
echo " OK"
bash
echo -n "Fetching wire transfers ..."
STATUS=$(curl 'http://localhost:9966/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" != "1" ]
then
jq . < "$LAST_RESPONSE"
exit_fail "Expected 1 entry in transfer list. Got: $TRANSFERS_LIST_SIZE"
fi
echo "OK"
echo -n "Checking order status ..."
STATUS=$(curl "http://localhost:9966/private/orders/${ORDER_ID}?transfer=YES" \
-w "%{http_code}" -s -o "$LAST_RESPONSE")
if [ "$STATUS" != "200" ]
then
jq . < "$LAST_RESPONSE"
exit_fail "Expected 200, after order inquiry. got: $STATUS"
fi
DEPOSIT_TOTAL=$(jq -r .deposit_total < "$LAST_RESPONSE")
if [ "$DEPOSIT_TOTAL" == "TESTKUDOS:0" ]
then
jq . < "$LAST_RESPONSE"
exit_fail "Expected non-zero deposit total. got: $DEPOSIT_TOTAL"
fi
echo " OK"
exit 0
|
|
|
@Christian, behavior like you proposed in (1) we don't have in SPA at all. Other lists also use buttons or click on the row to show details. So I think it's good to add a click on a row to show the details page as well. I don't see a problem with showing 2 buttons when it is needed: Confirm and Details. For a confirmed wire transfer, only Details button is needed. |
| Date Modified | Username | Field | Change |
|---|---|---|---|
| 2026-01-31 20:55 | Christian Grothoff | New Issue | |
| 2026-01-31 20:55 | Christian Grothoff | Status | new => assigned |
| 2026-01-31 20:55 | Christian Grothoff | Assigned To | => sebasjm |
| 2026-01-31 20:58 | Christian Grothoff | Note Added: 0027508 | |
| 2026-01-31 20:58 | Christian Grothoff | Tag Attached: design-required | |
| 2026-01-31 20:59 | Christian Grothoff | Note Added: 0027509 | |
| 2026-01-31 21:00 | Christian Grothoff | Priority | high => low |
| 2026-01-31 21:00 | Christian Grothoff | Target Version | 1.5 => 1.8 |
| 2026-02-05 13:32 | sebasjm | Note Added: 0027587 | |
| 2026-02-05 13:33 | sebasjm | Assigned To | sebasjm => Christian Grothoff |
| 2026-02-05 13:33 | sebasjm | Status | assigned => feedback |
| 2026-02-05 13:39 | sebasjm | Note Added: 0027588 | |
| 2026-02-05 13:44 | sebasjm | Note Edited: 0027588 | |
| 2026-02-22 23:22 | Christian Grothoff | Priority | low => high |
| 2026-03-30 16:07 | Christian Grothoff | Note Added: 0028305 | |
| 2026-03-30 16:07 | Christian Grothoff | File Added: test_b10959.sh | |
| 2026-03-30 16:07 | Christian Grothoff | Assigned To | Christian Grothoff => vlada.svirsh |
| 2026-03-30 16:07 | Christian Grothoff | Status | feedback => assigned |
| 2026-03-30 19:25 | vlada.svirsh | Note Added: 0028310 | |
| 2026-03-30 19:25 | vlada.svirsh | Assigned To | vlada.svirsh => Christian Grothoff |
| 2026-03-30 19:25 | vlada.svirsh | Status | assigned => feedback |