test_merchant_order_refund.sh (8762B)
1 #!/usr/bin/env bash 2 # This file is in the public domain. 3 4 set -eu 5 6 function clean_wallet() { 7 echo rm -f "${WALLET_DB}" 8 rm -f "${HTML_RESPONSE}" 9 exit_cleanup 10 } 11 12 function assert_html_contains() { 13 if ! grep -Fq -- "$2" "$1" 14 then 15 cat "$1" >&2 16 exit_fail "Expected rendered HTML to contain: $2" 17 fi 18 } 19 20 function assert_html_rendered() { 21 if grep -Fq -- '{{' "$1" 22 then 23 cat "$1" >&2 24 exit_fail "Rendered HTML contains unresolved Mustache markup" 25 fi 26 } 27 28 29 # Replace with 0 for nexus... 30 USE_FAKEBANK=1 31 if [ 1 = "$USE_FAKEBANK" ] 32 then 33 ACCOUNT="exchange-account-2" 34 BANK_FLAGS="-f -d x-taler-bank -u $ACCOUNT" 35 BANK_URL="http://localhost:8082/" 36 else 37 ACCOUNT="exchange-account-1" 38 BANK_FLAGS="-ns -d iban -u $ACCOUNT" 39 BANK_URL="http://localhost:18082/" 40 echo -n "Testing for libeufin-bank" 41 libeufin-bank --help >/dev/null </dev/null || exit_skip " MISSING" 42 echo " FOUND" 43 44 fi 45 46 . setup.sh 47 48 echo -n "Testing for taler-harness" 49 taler-harness --help >/dev/null </dev/null || exit_skip " MISSING" 50 echo " FOUND" 51 52 # Launch exchange, merchant and bank. 53 setup -c "test_template.conf" \ 54 -em \ 55 -r "merchant-exchange-default" \ 56 $BANK_FLAGS 57 LAST_RESPONSE=$(mktemp -p "${TMPDIR:-/tmp}" test_response.conf-XXXXXX) 58 HTML_RESPONSE="${LAST_RESPONSE}.html" 59 CONF="test_template.conf.edited" 60 WALLET_DB=$(mktemp -p "${TMPDIR:-/tmp}" test_wallet.json-XXXXXX) 61 EXCHANGE_URL="http://localhost:8081/" 62 63 # Install cleanup handler (except for kill -9) 64 trap clean_wallet EXIT 65 66 echo -n "First prepare wallet with coins ..." 67 rm -f "$WALLET_DB" 68 taler-wallet-cli \ 69 --no-throttle \ 70 --wallet-db="$WALLET_DB" \ 71 api \ 72 --expect-success 'withdrawTestBalance' \ 73 "$(jq -n ' 74 { 75 amount: "TESTKUDOS:99", 76 corebankApiBaseUrl: $BANK_URL, 77 exchangeBaseUrl: $EXCHANGE_URL 78 }' \ 79 --arg BANK_URL "${BANK_URL}" \ 80 --arg EXCHANGE_URL "$EXCHANGE_URL" 81 )" 2>wallet-withdraw-1.err >wallet-withdraw-1.out 82 echo -n "." 83 # FIXME-MS: add logic to have nexus check immediately here. 84 # sleep 10 85 echo -n "." 86 # NOTE: once libeufin can do long-polling, we should 87 # be able to reduce the delay here and run wirewatch 88 # always in the background via setup 89 taler-exchange-wirewatch \ 90 -a "$ACCOUNT" \ 91 -L "INFO" \ 92 -c "$CONF" \ 93 -t &> taler-exchange-wirewatch.out 94 echo -n "." 95 timeout 60 taler-wallet-cli \ 96 --wallet-db="$WALLET_DB" \ 97 run-until-done \ 98 2>wallet-withdraw-finish-1.err \ 99 >wallet-withdraw-finish-1.out 100 echo " OK" 101 102 CURRENCY_COUNT=$(taler-wallet-cli --wallet-db="$WALLET_DB" balance | jq '.balances|length') 103 if [ "$CURRENCY_COUNT" = "0" ] 104 then 105 exit_fail "Expected least one currency, withdrawal failed. check log." 106 fi 107 108 # 109 # CREATE INSTANCE FOR TESTING 110 # 111 112 echo -n "Configuring merchant instance ..." 113 114 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 115 http://localhost:9966/management/instances \ 116 -d '{"auth":{"method":"token","password":"super_secret"},"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}}' \ 117 -w "%{http_code}" -s -o /dev/null) 118 119 if [ "$STATUS" != "204" ] 120 then 121 exit_fail "Expected '204 No content' response. Got instead $STATUS" 122 fi 123 ADMIN_TOKEN=$(merchant_login admin super_secret) 124 echo "Ok" 125 126 echo -n "Configuring merchant account ..." 127 128 if [ 1 = "$USE_FAKEBANK" ] 129 then 130 FORTYTHREE="payto://x-taler-bank/localhost/fortythree?receiver-name=fortythree" 131 else 132 FORTYTHREE=$(get_payto_uri fortythree x) 133 fi 134 # create with 2 bank account addresses 135 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 136 -H "Authorization: Bearer $ADMIN_TOKEN" \ 137 http://localhost:9966/private/accounts \ 138 -d '{"payto_uri":"'"$FORTYTHREE"'"}' \ 139 -w "%{http_code}" -s -o /dev/null) 140 141 if [ "$STATUS" != "200" ] 142 then 143 exit_fail "Expected '200 OK' response. Got instead $STATUS" 144 fi 145 146 echo "Ok" 147 148 149 # 150 # CREATE ORDER AND SELL IT 151 # 152 153 echo -n "Creating order to be paid..." 154 STATUS=$(curl 'http://localhost:9966/private/orders' \ 155 -H "Authorization: Bearer $ADMIN_TOKEN" \ 156 -d '{"order":{"amount":"TESTKUDOS:5","summary":"payme","auto_refund":{"d_us":180000000}}}' \ 157 -w "%{http_code}" -s -o "$LAST_RESPONSE") 158 159 if [ "$STATUS" != "200" ] 160 then 161 jq . < "$LAST_RESPONSE" 162 exit_fail "Expected 200, order created. got: $STATUS" 163 fi 164 165 ORDER_ID=$(jq -e -r .order_id < "$LAST_RESPONSE") 166 TOKEN=$(jq -e -r .token < "$LAST_RESPONSE") 167 168 RESPONSE_HEADERS=$(curl "http://localhost:9966/private/orders/${ORDER_ID}" \ 169 -H "Authorization: Bearer $ADMIN_TOKEN" \ 170 -w "%{header_json}" \ 171 -s \ 172 -o "$LAST_RESPONSE") 173 174 ETAG=$(echo "$RESPONSE_HEADERS" | jq -r .etag[0]) 175 ETAG_NQ=$(echo "$ETAG" | tr -d '"') 176 PAY_URL=$(jq -e -r .taler_pay_uri < "$LAST_RESPONSE") 177 178 echo "OK" 179 180 LP_START=$(date +%s) 181 182 echo -n "Long-polling for order status change paid..." 183 184 curl "http://localhost:9966/private/orders/${ORDER_ID}?timeout_ms=30000&lp_not_etag=${ETAG_NQ}" \ 185 -H "Authorization: Bearer $ADMIN_TOKEN" \ 186 -H "If-none-match: $ETAG" \ 187 -w "%{header_json}" \ 188 -s \ 189 -o "${LAST_RESPONSE}-long-poll" & 190 LP_PID="$!" 191 192 # 193 # PAY THE ORDER 194 # 195 196 # FIXME: use claim-only first: 197 # $ taler-wallet-cli api 'preparePayForUri' '{"talerPayUri":"taler://pay/backend.demo.taler.net/instances/blog/2026.035-0184YVPMMWKKE/b4f09f9c-f863-4805-9caf-4f849e5eb34b?c=0P603WJ9T6TYTC7Z6QRDFXEJQ0"}' 198 199 200 # set -x 201 PAYMENT_START=$(date +%s) 202 echo "Pay first order ${PAY_URL} ..." 203 taler-wallet-cli \ 204 --no-throttle \ 205 -V \ 206 --wallet-db="$WALLET_DB" \ 207 handle-uri "${PAY_URL}" \ 208 -y \ 209 2> wallet-pay1.err \ 210 > wallet-pay1.log 211 PAYMENT_END=$(date +%s) 212 echo " OK (payment took $(( PAYMENT_END - PAYMENT_START )) secs )" 213 214 STATUS=$(curl "http://localhost:9966/private/orders/${ORDER_ID}" \ 215 -H "Authorization: Bearer $ADMIN_TOKEN" \ 216 -w "%{http_code}" -s -o "$LAST_RESPONSE") 217 218 if [ "$STATUS" != "200" ] 219 then 220 jq . < "$LAST_RESPONSE" 221 exit_fail "Expected 200, after pay. got: $STATUS" 222 fi 223 224 ORDER_STATUS=$(jq -r .order_status < "$LAST_RESPONSE") 225 226 if [ "$ORDER_STATUS" != "paid" ] 227 then 228 jq . < "$LAST_RESPONSE" 229 exit_fail "Order status should be 'paid'. got: $ORDER_STATUS" 230 fi 231 232 # Wait for long-poller 233 echo -e "Wait for long-poller ..." 234 wait $LP_PID &> /dev/null 235 LP_END=$(date +%s) 236 237 if (( "$LP_END" - "$LP_START" > 10 )) 238 then 239 exit_fail "Expected long-poller to return quickly. Instead took from $LP_START to $LP_END" 240 fi 241 echo " OK" 242 243 echo -n "Sending refund for TESTKUDOS:1 ..." 244 245 STATUS=$(curl "http://localhost:9966/private/orders/${ORDER_ID}/refund" \ 246 -H "Authorization: Bearer $ADMIN_TOKEN" \ 247 -d '{"refund":"TESTKUDOS:1","reason":"duplicated"}' \ 248 -w "%{http_code}" \ 249 -s \ 250 -o "$LAST_RESPONSE") 251 252 if [ "$STATUS" != "200" ] 253 then 254 jq . < "$LAST_RESPONSE" 255 exit_fail "Expected 200, after refund. got: $STATUS" 256 fi 257 REFUND_URI=$(jq -e -r .taler_refund_uri < "$LAST_RESPONSE") 258 echo " OK" 259 260 echo -n "Checking refund HTML..." 261 STATUS=$(curl -H 'Accept: text/html' \ 262 "http://localhost:9966/orders/${ORDER_ID}?token=${TOKEN}" \ 263 -w "%{http_code}" -s -o "$HTML_RESPONSE") 264 if [ "$STATUS" != "200" ] 265 then 266 cat "$HTML_RESPONSE" >&2 267 exit_fail "Expected 200 refund HTML. Got: $STATUS" 268 fi 269 assert_html_contains "$HTML_RESPONSE" 'Collect your refund' 270 assert_html_contains "$HTML_RESPONSE" 'TESTKUDOS:1' 271 assert_html_contains "$HTML_RESPONSE" 'class="qr-frame"' 272 assert_html_rendered "$HTML_RESPONSE" 273 echo "OK" 274 275 REFUND_START=$(date +%s) 276 echo "First refund order ${REFUND_URI} ..." 277 set -x 278 timeout 60 taler-wallet-cli \ 279 --no-throttle \ 280 --wallet-db="$WALLET_DB" \ 281 handle-uri "${REFUND_URI}" \ 282 -y \ 283 2> wallet-refund1.err \ 284 > wallet-refund1.log 285 REFUND_END=$(date +%s) 286 echo " OK (refund1 took $(( REFUND_END - REFUND_START )) secs)" 287 288 echo -n "Increasing refund for TESTKUDOS:3 ..." 289 290 STATUS=$(curl "http://localhost:9966/private/orders/${ORDER_ID}/refund" \ 291 -H "Authorization: Bearer $ADMIN_TOKEN" \ 292 -d '{"refund":"TESTKUDOS:5","reason":"duplicated"}' \ 293 -w "%{http_code}" -s -o "$LAST_RESPONSE") 294 295 if [ "$STATUS" != "200" ] 296 then 297 jq . < "$LAST_RESPONSE" 298 exit_fail "Expected 200, after refund. got: $STATUS" 299 fi 300 REFUND_URI=$(jq -e -r .taler_refund_uri < "$LAST_RESPONSE") 301 echo " OK" 302 303 REFUND2_START=$(date +%s) 304 echo -n "Second refund order ${REFUND_URI} ..." 305 timeout 60 taler-wallet-cli \ 306 --no-throttle \ 307 --wallet-db="$WALLET_DB" \ 308 handle-uri "${REFUND_URI}" \ 309 -y \ 310 2> wallet-refund2.err \ 311 > wallet-refund2.log 312 REFUND2_END=$(date +%s) 313 echo " OK (refund2 took $(( REFUND2_END - REFUND_START )) secs)" 314 315 echo "TEST PASSED" 316 exit 0