merchant

Merchant backend to process payments, run by merchants
Log | Files | Refs | Submodules | README | LICENSE

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 &lt;unsafe&gt; &amp; 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