test_merchant_order_creation.sh (26597B)
1 #!/usr/bin/env bash 2 # This file is in the public domain. 3 4 set -eu 5 6 function clean_wallet() { 7 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:8082/" 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 -r "merchant-exchange-default" \ 55 -em \ 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 113 echo -n "Configuring merchant instance ..." 114 115 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 116 http://localhost:9966/management/instances \ 117 -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}}' \ 118 -w "%{http_code}" -s -o /dev/null) 119 120 if [ "$STATUS" != "204" ] 121 then 122 exit_fail "Expected '204 No content' response. Got instead $STATUS" 123 fi 124 ADMIN_TOKEN=$(merchant_login admin super_secret) 125 echo "Ok" 126 127 echo -n "Configuring merchant account ..." 128 129 if [ 1 = "$USE_FAKEBANK" ] 130 then 131 FORTYTHREE="payto://x-taler-bank/localhost/fortythree?receiver-name=fortythree" 132 else 133 FORTYTHREE=$(get_payto_uri fortythree x) 134 fi 135 # create with 2 bank account addresses 136 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 137 -H "Authorization: Bearer $ADMIN_TOKEN" \ 138 http://localhost:9966/private/accounts \ 139 -d '{"payto_uri":"'"$FORTYTHREE"'"}' \ 140 -w "%{http_code}" -s -o /dev/null) 141 142 if [ "$STATUS" != "200" ] 143 then 144 exit_fail "Expected '200 OK' response. Got instead $STATUS" 145 fi 146 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 147 -H "Authorization: Bearer $ADMIN_TOKEN" \ 148 http://localhost:9966/private/accounts \ 149 -d '{"payto_uri":"payto://iban/SANDBOXX/DE270744?receiver-name=Forty+Four"}' \ 150 -w "%{http_code}" -s -o /dev/null) 151 152 if [ "$STATUS" != "200" ] 153 then 154 exit_fail "Expected '200 OK' response. Got instead $STATUS" 155 fi 156 157 echo "Ok" 158 159 160 echo -n "Get accounts..." 161 STATUS=$(curl http://localhost:9966/private/accounts \ 162 -H "Authorization: Bearer $ADMIN_TOKEN" \ 163 -w "%{http_code}" -s -o "$LAST_RESPONSE") 164 PAY_URI=$(jq -r .accounts[1].payto_uri < "$LAST_RESPONSE") 165 H_WIRE=$(jq -r .accounts[1].h_wire < "$LAST_RESPONSE") 166 if [ "$PAY_URI" != "payto://iban/SANDBOXX/DE270744?receiver-name=Forty+Four" ] 167 then 168 cat "$LAST_RESPONSE" >&2 169 exit_fail "Expected second payto URI. Got $PAY_URI" 170 fi 171 echo "OK" 172 173 # remove one account address 174 echo -n "Deleting one account ..." 175 STATUS=$(curl -H "Content-Type: application/json" -X PATCH \ 176 -H "Authorization: Bearer $ADMIN_TOKEN" \ 177 "http://localhost:9966/private/accounts/${H_WIRE}" \ 178 -X DELETE \ 179 -w "%{http_code}" -s -o /dev/null) 180 181 if [ "$STATUS" != "204" ] 182 then 183 exit_fail "Expected '204 No content' for deletion of ${H_WIRE}. Got instead: $STATUS" 184 fi 185 echo "OK" 186 187 RANDOM_IMG='data:image/png;base64,abcdefg' 188 189 # 190 # CREATE AN ORDER WITHOUT TOKEN 191 # 192 193 echo -n "Creating order without TOKEN..." 194 STATUS=$(curl 'http://localhost:9966/private/orders' \ 195 -H "Authorization: Bearer $ADMIN_TOKEN" \ 196 -d '{"create_token":false,"refund_delay":{"d_us":0},"order":{"amount":"TESTKUDOS:7","summary":"3 <unsafe> & tea","products":[{"description":"desct","image":"'"$RANDOM_IMG"'","price":"TESTKUDOS:1","taxes":[],"unit":"u","quantity":1}]}}' \ 197 -w "%{http_code}" -s -o "$LAST_RESPONSE") 198 199 if [ "$STATUS" != "200" ] 200 then 201 cat "$LAST_RESPONSE" >&2 202 exit_fail "Expected 200, order created. got: $STATUS" 203 fi 204 205 ORDER_ID=$(jq -r .order_id < "$LAST_RESPONSE") 206 TOKEN=$(jq -r .token < "$LAST_RESPONSE") 207 208 if [ "$TOKEN" != "null" ] 209 then 210 exit_fail "token should be null, got: $TOKEN" 211 fi 212 213 echo "OK" 214 215 echo -n "Checking created order without TOKEN..." 216 STATUS=$(curl http://localhost:9966/orders/"$ORDER_ID" \ 217 -w "%{http_code}" -s -o "$LAST_RESPONSE") 218 PAY_URI=$(jq -r .taler_pay_uri < "$LAST_RESPONSE") 219 if [ "$PAY_URI" == "null" ] 220 then 221 cat "$LAST_RESPONSE" >&2 222 exit_fail "Expected non-NULL payuri. got $PAY_URI" 223 fi 224 echo "OK" 225 226 echo -n "Checking unclaimed order HTML..." 227 STATUS=$(curl -H 'Accept: text/html' \ 228 "http://localhost:9966/orders/${ORDER_ID}" \ 229 -w "%{http_code}" -s -o "$HTML_RESPONSE") 230 if [ "$STATUS" != "402" ] 231 then 232 cat "$HTML_RESPONSE" >&2 233 exit_fail "Expected 402 payment HTML. Got: $STATUS" 234 fi 235 assert_html_contains "$HTML_RESPONSE" 'Pay with GNU Taler' 236 assert_html_contains "$HTML_RESPONSE" 'TESTKUDOS:7' 237 assert_html_contains "$HTML_RESPONSE" '3 <unsafe> & tea' 238 assert_html_contains "$HTML_RESPONSE" "$ORDER_ID" 239 assert_html_contains "$HTML_RESPONSE" 'class="qr-frame"' 240 assert_html_rendered "$HTML_RESPONSE" 241 echo "OK" 242 243 # 244 # CREATE AN ORDER WITHOUT TOKEN WITH FULLFILMENT URL 245 # 246 247 echo -n "Creating order without TOKEN and fullfilment URL..." 248 STATUS=$(curl 'http://localhost:9966/private/orders' \ 249 -H "Authorization: Bearer $ADMIN_TOKEN" \ 250 -d '{"create_token":false,"refund_delay":{"d_us":0},"order":{"fulfillment_url":"go_here_please", "amount":"TESTKUDOS:7","summary":"3","products":[{"description":"desct","image":"'"$RANDOM_IMG"'","price":"TESTKUDOS:1","taxes":[],"unit":"u","quantity":1}]}}' \ 251 -w "%{http_code}" -s -o "$LAST_RESPONSE") 252 253 if [ "$STATUS" != "200" ] 254 then 255 cat "$LAST_RESPONSE" >&2 256 exit_fail "Expected 200, order created. got: $STATUS" 257 fi 258 259 ORDER_ID=$(jq -r .order_id < "$LAST_RESPONSE") 260 TOKEN=$(jq -r .token < "$LAST_RESPONSE") 261 262 if [ "$TOKEN" != "null" ] 263 then 264 exit_fail "Token should be null, got: $TOKEN" 265 fi 266 267 STATUS=$(curl http://localhost:9966/orders/"$ORDER_ID" \ 268 -w "%{http_code}" -s -o "$LAST_RESPONSE") 269 270 PAY_URI=$(jq -r .taler_pay_uri < "$LAST_RESPONSE") 271 FULLFILMENT_URL=$(jq -r .fulfillment_url < "$LAST_RESPONSE") 272 273 if [ "$FULLFILMENT_URL" != "go_here_please" ] 274 then 275 cat "$LAST_RESPONSE" >&2 276 exit_fail "Expected a pay URI. got: $PAY_URI" 277 fi 278 279 if [ "$PAY_URI" == "null" ] 280 then 281 cat "$LAST_RESPONSE" >&2 282 exit_fail "Expected non-NULL pay URI. Got: $PAY_URI" 283 fi 284 echo "OK" 285 286 # 287 # CREATE A DISCOUNT TOKEN FAMILY 288 # 289 echo -n "Creating discount token family..." 290 VALID_AFTER="{\"t_s\": $(date +%s)}" # now 291 VALID_BEFORE="{\"t_s\": $(date +%s -d "+30 days")}" # 30 days from now 292 DURATION="{\"d_us\": $(expr 30 \* 24 \* 60 \* 60 \* 1000000)}" # 30 days 293 STATUS=$(curl 'http://localhost:9966/private/tokenfamilies' \ 294 -H "Authorization: Bearer $ADMIN_TOKEN" \ 295 -d "{\"kind\": \"discount\", \"slug\":\"test-discount\", \"name\": \"Test discount\", \"description\": \"Less money $$\", \"description_i18n\": {\"en\": \"Less money $$\", \"es\": \"Menos dinero $$\"}, \"valid_after\": $VALID_AFTER, \"valid_before\": $VALID_BEFORE, \"duration\": $DURATION, \"validity_granularity\": $DURATION}" \ 296 -w "%{http_code}" -s -o "$LAST_RESPONSE") 297 if [ "$STATUS" != "204" ] 298 then 299 cat "$LAST_RESPONSE" >&2 300 exit_fail "Expected '204 OK' response. Got instead $STATUS" 301 fi 302 echo "Ok" 303 304 # 305 # CREATE A SUBSCRIPTION TOKEN FAMILY 306 # 307 echo -n "Creating subscription token family..." 308 VALID_AFTER="{\"t_s\": $(date +%s)}" # now 309 VALID_BEFORE="{\"t_s\": $(date +%s -d "+30 days")}" # 30 days from now 310 DURATION="{\"d_us\": $(expr 30 \* 24 \* 60 \* 60 \* 1000000)}" # 30 days 311 STATUS=$(curl 'http://localhost:9966/private/tokenfamilies' \ 312 -H "Authorization: Bearer $ADMIN_TOKEN" \ 313 -d "{\"kind\": \"subscription\", \"slug\":\"test-subscription\", \"name\": \"Test subscription\", \"description\": \"Money per month\", \"description_i18n\": {\"en\": \"Money $$$ per month\", \"es\": \"Dinero $$$ al mes\"}, \"valid_after\": $VALID_AFTER, \"valid_before\": $VALID_BEFORE, \"duration\": $DURATION, \"validity_granularity\": $DURATION}" \ 314 -w "%{http_code}" -s -o "$LAST_RESPONSE") 315 if [ "$STATUS" != "204" ] 316 then 317 cat "$LAST_RESPONSE" >&2 318 exit_fail "Expected '204 OK' response. Got instead $STATUS" 319 fi 320 echo "Ok" 321 322 # 323 # CREATE AN DISCOUNTABLE ORDER WITHOUT TOKEN 324 # 325 RANDOM_IMG='data:image/png;base64,abcdefg' 326 327 echo -n "Creating discountable order..." 328 STATUS=$(curl 'http://localhost:9966/private/orders' \ 329 -H "Authorization: Bearer $ADMIN_TOKEN" \ 330 -d '{"create_token":true,"refund_delay":{"d_us":0},"order":{"version":1,"summary":"Expensive purchase","products":[{"description":"Expensive steak","quantity":2,"unit":"pieces","price":"TESTKUDOS:100"}],"choices":[{"amount":"TESTKUDOS:100"},{"amount":"TESTKUDOS:10","inputs":[{"type":"token","token_family_slug":"test-discount","count":1}],"outputs":[]}]}}' \ 331 -w "%{http_code}" -s -o "$LAST_RESPONSE") 332 333 if [ "$STATUS" != "200" ] 334 then 335 cat "$LAST_RESPONSE" >&2 336 exit_fail "Expected 200, order created. got: $STATUS" 337 fi 338 echo "OK" 339 340 ORDER_ID=$(jq -r .order_id < "$LAST_RESPONSE") 341 TOKEN=$(jq -r .token < "$LAST_RESPONSE") 342 343 echo -n "Checking created order..." 344 STATUS=$(curl http://localhost:9966/orders/"$ORDER_ID?token=$TOKEN" \ 345 -w "%{http_code}" -s -o "$LAST_RESPONSE") 346 PAY_URI=$(jq -r .taler_pay_uri < "$LAST_RESPONSE") 347 if [ "$PAY_URI" == "null" ] 348 then 349 cat "$LAST_RESPONSE" >&2 350 exit_fail "Expected non-NULL payuri. got $PAY_URI" 351 fi 352 echo "OK" 353 354 echo -n "Checking multi-option order HTML..." 355 STATUS=$(curl -H 'Accept: text/html' \ 356 "http://localhost:9966/orders/${ORDER_ID}?token=${TOKEN}" \ 357 -w "%{http_code}" -s -o "$HTML_RESPONSE") 358 if [ "$STATUS" != "402" ] 359 then 360 cat "$HTML_RESPONSE" >&2 361 exit_fail "Expected 402 payment HTML. Got: $STATUS" 362 fi 363 assert_html_contains "$HTML_RESPONSE" 'Expensive purchase' 364 assert_html_contains "$HTML_RESPONSE" 'select the amount and payment option in your wallet' 365 assert_html_rendered "$HTML_RESPONSE" 366 echo "OK" 367 368 echo -n "Claming order with token family ..." 369 STATUS=$(curl http://localhost:9966/orders/"$ORDER_ID"/claim \ 370 -d '{"nonce":"0FTTZ475NBECCZN97VFTN6DEKWVKJ8AQY9PWR6VS36JZQFS66YG0","token":"'"$TOKEN"'"}' \ 371 -w "%{http_code}" -s -o "$LAST_RESPONSE") 372 373 if [ "$STATUS" != "200" ] 374 then 375 cat "$LAST_RESPONSE" >&2 376 exit_fail "Expected 200, order claimed. got: $STATUS" 377 fi 378 379 echo " OK" 380 381 echo -n "Checking claimed order HTML..." 382 STATUS=$(curl -H 'Accept: text/html' \ 383 "http://localhost:9966/orders/${ORDER_ID}?token=${TOKEN}" \ 384 -w "%{http_code}" -s -o "$HTML_RESPONSE") 385 if [ "$STATUS" != "402" ] 386 then 387 cat "$HTML_RESPONSE" >&2 388 exit_fail "Expected 402 claimed payment HTML. Got: $STATUS" 389 fi 390 assert_html_contains "$HTML_RESPONSE" 'Order claimed by wallet' 391 assert_html_contains "$HTML_RESPONSE" 'data-claimed="true"' 392 assert_html_rendered "$HTML_RESPONSE" 393 echo "OK" 394 395 # echo -n "Fetching pay URL for order ..." 396 # STATUS=$(curl "http://localhost:9966/private/orders/${ORDER_ID}" \ 397 # -w "%{http_code}" -s -o "$LAST_RESPONSE") 398 399 # if [ "$STATUS" != "200" ] 400 # then 401 # jq . < "$LAST_RESPONSE" 402 # exit_fail "Expected 200, getting order info before claming it. got: $STATUS" 403 # fi 404 405 # PAY_URL=$(jq -e -r .taler_pay_uri < "$LAST_RESPONSE") 406 407 # echo " OK" 408 409 # NOW=$(date +%s) 410 411 # echo -n "Pay for order ${PAY_URL} ..." 412 # taler-wallet-cli --no-throttle --wallet-db="$WALLET_DB" handle-uri "${PAY_URL}" -y 2> wallet-pay1.err > wallet-pay1.log 413 # taler-wallet-cli --no-throttle --wallet-db="$WALLET_DB" run-until-done 2> wallet-finish-pay1.err > wallet-finish-pay1.log 414 # NOW2=$(date +%s) 415 # echo " OK (took $(( NOW2 - NOW )) secs )" 416 417 # 418 # CREATE ORDER WITH NON-INVENTORY AND CHECK 419 # 420 421 echo -n "Creating order with non-inventory products..." 422 STATUS=$(curl 'http://localhost:9966/private/orders' \ 423 -H "Authorization: Bearer $ADMIN_TOKEN" \ 424 -d '{"refund_delay":{"d_us":0},"order":{"amount":"TESTKUDOS:7","summary":"3","products":[{"description":"desct","image":"'"$RANDOM_IMG"'","price":"TESTKUDOS:1","taxes":[],"unit":"u","quantity":1}]}}' \ 425 -w "%{http_code}" -s -o "$LAST_RESPONSE") 426 427 if [ "$STATUS" != "200" ] 428 then 429 cat "$LAST_RESPONSE" >&2 430 exit_fail "Expected 200, order created. got: $STATUS" 431 fi 432 433 ORDER_ID=$(jq -r .order_id < "$LAST_RESPONSE") 434 TOKEN=$(jq -r .token < "$LAST_RESPONSE") 435 436 STATUS=$(curl http://localhost:9966/orders/"$ORDER_ID"/claim \ 437 -d '{"nonce":"0FTTZ475NBECCZN97VFTN6DEKWVKJ8AQY9PWR6VS36JZQFS66YG0","token":"'"$TOKEN"'"}' \ 438 -w "%{http_code}" -s -o "$LAST_RESPONSE") 439 440 if [ "$STATUS" != "200" ] 441 then 442 cat "$LAST_RESPONSE" >&2 443 exit_fail "Expected 200, order claimed. got: $STATUS" 444 fi 445 446 QUANTITY=$(jq -r .contract_terms.products[0].quantity < "$LAST_RESPONSE") 447 if [ "$QUANTITY" != "1" ] 448 then 449 cat < "$LAST_RESPONSE" >&2 450 exit_fail "Expected quantity 1. got: $QUANTITY" 451 fi 452 453 IMAGE=$(jq -r .contract_terms.products[0].image < "$LAST_RESPONSE") 454 if [ "$IMAGE" != "$RANDOM_IMG" ] 455 then 456 cat "$LAST_RESPONSE" >&2 457 exit_fail "Expected $RANDOM_IMG but got something else: $IMAGE" 458 fi 459 echo "OK" 460 461 462 # The products created below are measured in "u", which is not a builtin 463 # unit; POST/PATCH /private/products reject a unit that does not exist, so 464 # create it first. 465 echo -n "Creating unit for the products below ..." 466 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 467 -H "Authorization: Bearer $ADMIN_TOKEN" \ 468 http://localhost:9966/private/units \ 469 -d '{"unit":"u","unit_name_long":"unit","unit_name_short":"u"}' \ 470 -w "%{http_code}" -s -o /dev/null) 471 472 if [ "$STATUS" != "204" ] 473 then 474 exit_fail "Expected 204 No content, unit created. Got: $STATUS" 475 fi 476 477 echo "OK" 478 479 # 480 # CREATE INVENTORY PRODUCT AND CLAIM IT 481 # 482 483 echo -n "Creating product..." 484 STATUS=$(curl 'http://localhost:9966/private/products' \ 485 -H "Authorization: Bearer $ADMIN_TOKEN" \ 486 -d '{"product_id":"2","description":"product with id 2 and price :15","unit_price":["TESTKUDOS:15"],"unit_total_stock":"2","description_i18n":{},"unit":"u","image":"'$RANDOM_IMG'","taxes":[],"address":{},"next_restock":{"t_s":"never"}}' \ 487 -w "%{http_code}" -s -o /dev/null) 488 489 if [ "$STATUS" != "204" ] 490 then 491 exit_fail "Expected 204, product created. got: $STATUS" 492 fi 493 echo "OK" 494 495 echo -n "Creating order with inventory products..." 496 STATUS=$(curl 'http://localhost:9966/private/orders' \ 497 -H "Authorization: Bearer $ADMIN_TOKEN" \ 498 -d '{"refund_delay":{"d_us":0},"order":{"amount":"TESTKUDOS:7","summary":"3"},"inventory_products":[{"product_id":"2","unit_quantity":"1"}]}' \ 499 -w "%{http_code}" -s -o "$LAST_RESPONSE") 500 501 502 if [ "$STATUS" != "200" ] 503 then 504 jq . < "$LAST_RESPONSE" 505 exit_fail "Expected 200 OK, order created response. Got: $STATUS" 506 fi 507 508 ORDER_ID=$(jq -e -r .order_id < "$LAST_RESPONSE") 509 TOKEN=$(jq -e -r .token < "$LAST_RESPONSE") 510 511 STATUS=$(curl http://localhost:9966/orders/"$ORDER_ID"/claim \ 512 -d '{"nonce":"1ZRJCEAGM5N98P6ATH0NSR9SP3RKQJQQ05MQJAJA57T8YNPCPWEG","token":"'"$TOKEN"'"}' \ 513 -w "%{http_code}" -s -o "$LAST_RESPONSE") 514 515 if [ "$STATUS" != "200" ] 516 then 517 jq . < "$LAST_RESPONSE" 518 exit_fail "Expected 200, order claimed. got: $STATUS" 519 fi 520 521 QUANTITY=$(jq -r .contract_terms.products[0].quantity < "$LAST_RESPONSE") 522 523 if [ "$QUANTITY" != "1" ] 524 then 525 exit_fail "Expected quantity 1. got: $QUANTITY" 526 fi 527 528 echo "OK" 529 530 # 531 # Create product in another currency 532 # 533 534 535 STATUS=$(curl 'http://localhost:9966/private/products' \ 536 -H "Authorization: Bearer $ADMIN_TOKEN" \ 537 -d '{"product_id":"1","description":"product with id 1 and price :15","unit_price":["USD:15"],"unit_total_stock":"1","description_i18n":{},"unit":"u","image":"","taxes":[],"address":{},"next_restock":{"t_s":"never"}}' \ 538 -w "%{http_code}" -s -o /dev/null) 539 540 if [ "$STATUS" != "204" ] 541 then 542 exit_fail "Expected 204 no content. got: $STATUS" 543 fi 544 545 # 546 # CREATE ORDER AND SELL IT 547 # 548 549 echo -n "Creating order to be paid..." 550 STATUS=$(curl 'http://localhost:9966/private/orders' \ 551 -H "Authorization: Bearer $ADMIN_TOKEN" \ 552 -d '{"refund_delay":{"d_us":0},"order":{"amount":"TESTKUDOS:1","summary":"payme"},"inventory_products":[{"product_id":"2","unit_quantity":"1"}]}' \ 553 -w "%{http_code}" -s -o "$LAST_RESPONSE") 554 555 if [ "$STATUS" != "200" ] 556 then 557 jq . < "$LAST_RESPONSE" 558 exit_fail "Expected 200, order created. got: $STATUS" 559 fi 560 561 ORDER_ID=$(jq -e -r .order_id < "$LAST_RESPONSE") 562 TOKEN=$(jq -e -r .token < "$LAST_RESPONSE") 563 564 STATUS=$(curl "http://localhost:9966/private/orders/${ORDER_ID}" \ 565 -H "Authorization: Bearer $ADMIN_TOKEN" \ 566 -w "%{http_code}" -s -o "$LAST_RESPONSE") 567 568 if [ "$STATUS" != "200" ] 569 then 570 jq . < "$LAST_RESPONSE" 571 exit_fail "Expected 200, getting order info. got: $STATUS" 572 fi 573 574 PAY_URL=$(jq -e -r .taler_pay_uri < "$LAST_RESPONSE") 575 576 echo "OK" 577 578 NOW=$(date +%s) 579 580 echo -n "Pay first order ${PAY_URL} ..." 581 timeout 60 taler-wallet-cli \ 582 --no-throttle \ 583 --wallet-db="$WALLET_DB" \ 584 handle-uri "${PAY_URL}" \ 585 -y 2> wallet-pay1.err > wallet-pay1.log 586 timeout 60 taler-wallet-cli \ 587 --no-throttle \ 588 --wallet-db="$WALLET_DB" \ 589 run-until-done 2> wallet-finish-pay1.err > wallet-finish-pay1.log 590 NOW2=$(date +%s) 591 echo " OK (took $(( NOW2 - NOW )) secs )" 592 593 STATUS=$(curl "http://localhost:9966/private/orders/${ORDER_ID}" \ 594 -H "Authorization: Bearer $ADMIN_TOKEN" \ 595 -w "%{http_code}" -s -o "$LAST_RESPONSE") 596 597 if [ "$STATUS" != "200" ] 598 then 599 jq . < "$LAST_RESPONSE" 600 exit_fail "Expected 200, after pay. got: $STATUS" 601 fi 602 603 ORDER_STATUS=$(jq -r .order_status < "$LAST_RESPONSE") 604 605 if [ "$ORDER_STATUS" != "paid" ] 606 then 607 jq . < "$LAST_RESPONSE" 608 exit_fail "Order status should be 'paid'. got: $ORDER_STATUS" 609 fi 610 611 echo -n "Checking paid order HTML..." 612 STATUS=$(curl -H 'Accept: text/html' \ 613 "http://localhost:9966/orders/${ORDER_ID}?token=${TOKEN}" \ 614 -w "%{http_code}" -s -o "$HTML_RESPONSE") 615 if [ "$STATUS" != "200" ] 616 then 617 cat "$HTML_RESPONSE" >&2 618 exit_fail "Expected 200 paid order HTML. Got: $STATUS" 619 fi 620 assert_html_contains "$HTML_RESPONSE" 'Payment complete' 621 assert_html_contains "$HTML_RESPONSE" 'TESTKUDOS:1' 622 assert_html_contains "$HTML_RESPONSE" "$ORDER_ID" 623 assert_html_rendered "$HTML_RESPONSE" 624 echo "OK" 625 626 # 627 # WIRE TRANSFER TO MERCHANT AND NOTIFY BACKEND 628 # 629 630 # PAY_DEADLINE=$(jq -r .contract_terms.pay_deadline.t_s < "$LAST_RESPONSE") 631 WIRE_DEADLINE=$(jq -r .contract_terms.wire_transfer_deadline.t_s < "$LAST_RESPONSE") 632 633 NOW=$(date +%s) 634 635 TO_SLEEP=$((1200 + WIRE_DEADLINE - NOW )) 636 echo "Waiting $TO_SLEEP secs for wire transfer" 637 638 echo -n "Call taler-exchange-aggregator ..." 639 taler-exchange-aggregator \ 640 -y \ 641 -c "$CONF" \ 642 -T "${TO_SLEEP}"000000 \ 643 -t \ 644 -L INFO &> aggregator.log 645 echo " DONE" 646 echo -n "Call taler-exchange-transfer ..." 647 taler-exchange-transfer \ 648 -c "$CONF" \ 649 -t \ 650 -L INFO &> transfer.log 651 echo " DONE" 652 echo -n "Give time to Nexus to route the payment to Sandbox..." 653 # FIXME: trigger immediate update at nexus 654 # NOTE: once libeufin can do long-polling, we should 655 # be able to reduce the delay here and run aggregator/transfer 656 # always in the background via setup 657 sleep 3 658 echo " DONE" 659 660 echo -n "Obtaining wire transfer details from bank ($USE_FAKEBANK)..." 661 662 BANKDATA="$(curl 'http://localhost:8082/accounts/exchange/taler-wire-gateway/history/outgoing?delta=1' -s)" 663 WTID=$(echo "$BANKDATA" | jq -r .outgoing_transactions[0].wtid) 664 WURL=$(echo "$BANKDATA" | jq -r .outgoing_transactions[0].exchange_base_url) 665 CREDIT_AMOUNT=$(echo "$BANKDATA" | jq -r .outgoing_transactions[0].amount) 666 TARGET_PAYTO=$(echo "$BANKDATA" | jq -r .outgoing_transactions[0].credit_account) 667 668 if [ "$EXCHANGE_URL" != "$WURL" ] 669 then 670 exit_fail "Wrong exchange URL in '$BANKDATA' response, expected '$EXCHANGE_URL'" 671 fi 672 673 echo " OK" 674 675 set +e 676 677 echo -n "Notifying merchant of bogus wire transfer ..." 678 679 STATUS=$(curl 'http://localhost:9966/private/transfers' \ 680 -H "Authorization: Bearer $ADMIN_TOKEN" \ 681 -d '{"credit_amount":"'"$CREDIT_AMOUNT"'1","wtid":"'"$WTID"'","payto_uri":"'"$TARGET_PAYTO"'","exchange_url":"'"$WURL"'"}' \ 682 -m 3 \ 683 -w "%{http_code}" -s -o "$LAST_RESPONSE") 684 685 if [ "$STATUS" != "204" ] 686 then 687 jq . < "$LAST_RESPONSE" 688 exit_fail "Expected to fail since the amount is not valid. got: $STATUS" 689 fi 690 691 echo "OK" 692 693 echo -n "Deleting bogus wire transfer ..." 694 695 TID=$(curl -H "Authorization: Bearer $ADMIN_TOKEN" -s http://localhost:9966/private/transfers | jq -r .transfers[0].transfer_serial_id) 696 STATUS=$(curl -H "Content-Type: application/json" -X DELETE \ 697 -H "Authorization: Bearer $ADMIN_TOKEN" \ 698 "http://localhost:9966/private/transfers/$TID" \ 699 -w "%{http_code}" -s -o "$LAST_RESPONSE") 700 701 if [ "$STATUS" != "204" ] 702 then 703 jq . < "$LAST_RESPONSE" 704 exit_fail "Expected response 204 No Content, after deleting valid TID. got: $STATUS" 705 fi 706 707 STATUS=$(curl -H "Content-Type: application/json" -X DELETE \ 708 -H "Authorization: Bearer $ADMIN_TOKEN" \ 709 "http://localhost:9966/private/transfers/$TID" \ 710 -w "%{http_code}" -s -o "$LAST_RESPONSE") 711 if [ "$STATUS" != "404" ] 712 then 713 jq . < "$LAST_RESPONSE" 714 exit_fail "Expected response 404 Not found, after deleting TID again. got: $STATUS" 715 fi 716 717 echo " OK" 718 719 echo -n "Notifying merchant of correct wire transfer..." 720 721 STATUS=$(curl 'http://localhost:9966/private/transfers' \ 722 -H "Authorization: Bearer $ADMIN_TOKEN" \ 723 -d '{"credit_amount":"'"$CREDIT_AMOUNT"'","wtid":"'"$WTID"'","payto_uri":"'"$TARGET_PAYTO"'","exchange_url":"'"$WURL"'"}' \ 724 -m 3 \ 725 -w "%{http_code}" -s -o "$LAST_RESPONSE") 726 727 if [ "$STATUS" != "204" ] 728 then 729 jq . < "$LAST_RESPONSE" 730 exit_fail "Expected response 204 No content, after providing transfer data. got: $STATUS" 731 fi 732 733 echo " OK" 734 735 echo -n "Running taler-merchant-depositcheck ..." 736 set -e 737 taler-merchant-depositcheck \ 738 -L INFO \ 739 -c "$CONF" \ 740 -T "${TO_SLEEP}"000000 \ 741 -t &> taler-merchant-depositcheck.log 742 echo " OK" 743 744 echo -n "Running taler-merchant-reconciliation ..." 745 set -e 746 taler-merchant-reconciliation \ 747 -L INFO \ 748 -c "$CONF" \ 749 -T "${TO_SLEEP}"000000 \ 750 -t &> taler-merchant-reconciliation.log 751 echo " OK" 752 753 754 echo -n "Fetching wire transfers ..." 755 756 STATUS=$(curl 'http://localhost:9966/private/transfers' \ 757 -H "Authorization: Bearer $ADMIN_TOKEN" \ 758 -w "%{http_code}" -s -o "$LAST_RESPONSE") 759 760 if [ "$STATUS" != "200" ] 761 then 762 jq . < "$LAST_RESPONSE" 763 exit_fail "Expected response 200 Ok. got: $STATUS" 764 fi 765 766 TRANSFERS_LIST_SIZE=$(jq -r '.transfers | length' < "$LAST_RESPONSE") 767 768 if [ "$TRANSFERS_LIST_SIZE" != "1" ] 769 then 770 jq . < "$LAST_RESPONSE" 771 exit_fail "Expected 1 entry in transfer list. Got: $TRANSFERS_LIST_SIZE" 772 fi 773 774 echo "OK" 775 776 echo -n "Checking order status ..." 777 STATUS=$(curl "http://localhost:9966/private/orders/${ORDER_ID}?transfer=YES" \ 778 -H "Authorization: Bearer $ADMIN_TOKEN" \ 779 -w "%{http_code}" -s -o "$LAST_RESPONSE") 780 if [ "$STATUS" != "200" ] 781 then 782 jq . < "$LAST_RESPONSE" 783 exit_fail "Expected 200, after order inquiry. got: $STATUS" 784 fi 785 DEPOSIT_TOTAL=$(jq -r .deposit_total < "$LAST_RESPONSE") 786 if [ "$DEPOSIT_TOTAL" == "TESTKUDOS:0" ] 787 then 788 jq . < "$LAST_RESPONSE" 789 exit_fail "Expected non-zero deposit total. got: $DEPOSIT_TOTAL" 790 fi 791 echo " OK" 792 793 echo -n "Checking bank account status ..." 794 if [ 1 = "$USE_FAKEBANK" ] 795 then 796 STATUS=$(curl "http://localhost:8082/accounts/fortythree" \ 797 -w "%{http_code}" \ 798 -s \ 799 -o "$LAST_RESPONSE") 800 if [ "$STATUS" != "200" ] 801 then 802 jq . < "$LAST_RESPONSE" 803 exit_fail "Expected response 200 Ok, getting account status. Got: $STATUS" 804 fi 805 BALANCE=$(jq -r .balance.amount < "$LAST_RESPONSE") 806 if [ "$BALANCE" == "TESTKUDOS:0" ] 807 then 808 jq . < "$LAST_RESPONSE" 809 exit_fail "Wire transfer did not happen. Got: $BALANCE" 810 fi 811 else 812 ACCOUNT_PASSWORD="fortythree:x" 813 BANK_HOST="localhost:18082" 814 STATUS=$(curl "http://$ACCOUNT_PASSWORD@$BANK_HOST/accounts/fortythree" \ 815 -w "%{http_code}" -s -o "$LAST_RESPONSE") 816 if [ "$STATUS" != "200" ] 817 then 818 jq . < "$LAST_RESPONSE" 819 exit_fail "Expected response 200 Ok, getting account status. Got: $STATUS" 820 fi 821 BALANCE=$(jq -r .balance.amount < "$LAST_RESPONSE") 822 if [ "$BALANCE" == "TESTKUDOS:0" ] 823 then 824 jq . < "$LAST_RESPONSE" 825 exit_fail "Wire transfer did not happen. Got: $BALANCE" 826 fi 827 fi 828 echo " OK" 829 830 echo -n "Getting information about kyc ..." 831 STATUS=$(curl -H "Content-Type: application/json" -X GET \ 832 -H "Authorization: Bearer $ADMIN_TOKEN" \ 833 http://localhost:9966/private/kyc \ 834 -w "%{http_code}" -s -o /dev/null) 835 if [ "$STATUS" != "200" ] 836 then 837 exit_fail "Expected 200. Got: $STATUS" 838 fi 839 echo " OK" 840 841 echo "Test PASSED" 842 exit 0