test_merchant_product_creation.sh (10768B)
1 #!/usr/bin/env bash 2 # This file is part of TALER 3 # Copyright (C) 2014-2023 Taler Systems SA 4 # 5 # TALER is free software; you can redistribute it and/or modify 6 # it under the terms of the GNU General Public License as 7 # published by the Free Software Foundation; either version 3, or 8 # (at your option) any later version. 9 # 10 # TALER is distributed in the hope that it will be useful, but 11 # WITHOUT ANY WARRANTY; without even the implied warranty of 12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 # GNU General Public License for more details. 14 # 15 # You should have received a copy of the GNU General Public 16 # License along with TALER; see the file COPYING. If not, see 17 # <http://www.gnu.org/licenses/> 18 # 19 20 set -eu 21 22 # Replace with 0 for nexus... 23 USE_FAKEBANK=1 24 if [ 1 = "$USE_FAKEBANK" ] 25 then 26 ACCOUNT="exchange-account-2" 27 WIRE_METHOD="x-taler-bank" 28 BANK_FLAGS="-f -d $WIRE_METHOD -u $ACCOUNT" 29 BANK_URL="http://localhost:8082/" 30 else 31 echo -n "Testing for libeufin-bank" 32 libeufin-bank --help >/dev/null </dev/null || exit_skip " MISSING" 33 echo " FOUND" 34 35 ACCOUNT="exchange-account-1" 36 WIRE_METHOD="iban" 37 BANK_FLAGS="-ns -d $WIRE_METHOD -u $ACCOUNT" 38 BANK_URL="http://localhost:18082/" 39 fi 40 41 . setup.sh 42 43 44 echo -n "Testing for taler-harness" 45 taler-harness --help >/dev/null </dev/null || exit_skip " MISSING" 46 echo " FOUND" 47 48 49 # Launch system. 50 setup -c "test_template.conf" \ 51 -r "merchant-exchange-default" \ 52 -em \ 53 $BANK_FLAGS 54 55 LAST_RESPONSE=$(mktemp -p "${TMPDIR:-/tmp}" test_response.conf-XXXXXX) 56 WALLET_DB=$(mktemp -p "${TMPDIR:-/tmp}" test_wallet.json-XXXXXX) 57 CONF="test_template.conf.edited" 58 if [ 1 = "$USE_FAKEBANK" ] 59 then 60 FORTYTHREE="payto://x-taler-bank/localhost/fortythree?receiver-name=fortythree" 61 else 62 FORTYTHREE=$(get_payto_uri fortythree x) 63 fi 64 EXCHANGE_URL="http://localhost:8081/" 65 66 echo -n "Configuring merchant instance ..." 67 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 68 "http://localhost:9966/management/instances" \ 69 -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" : 50000000},"default_pay_delay":{"d_us": 60000000}}' \ 70 -w "%{http_code}" -s -o /dev/null) 71 72 if [ "$STATUS" != "204" ] 73 then 74 exit_fail "Expected 204 No content, instance created. Got $STATUS instead" 75 fi 76 ADMIN_TOKEN=$(merchant_login admin super_secret) 77 78 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 79 -H "Authorization: Bearer $ADMIN_TOKEN" \ 80 http://localhost:9966/private/accounts \ 81 -d '{"payto_uri":"'"$FORTYTHREE"'"}' \ 82 -w "%{http_code}" -s -o /dev/null) 83 84 if [ "$STATUS" != "200" ] 85 then 86 exit_fail "Expected 200 OK. Got: $STATUS" 87 fi 88 89 echo "OK" 90 91 # The products created below are measured in "u", which is not a builtin 92 # unit; POST/PATCH /private/products reject a unit that does not exist, so 93 # create it first. 94 echo -n "Creating unit for the products below ..." 95 STATUS=$(curl -H "Content-Type: application/json" -X POST \ 96 -H "Authorization: Bearer $ADMIN_TOKEN" \ 97 http://localhost:9966/private/units \ 98 -d '{"unit":"u","unit_name_long":"unit","unit_name_short":"u"}' \ 99 -w "%{http_code}" -s -o /dev/null) 100 101 if [ "$STATUS" != "204" ] 102 then 103 exit_fail "Expected 204 No content, unit created. Got: $STATUS" 104 fi 105 106 echo "OK" 107 108 RANDOM_IMG='data:image/png;base64,abcdefg' 109 INFINITE_PRODUCT_TEMPLATE='{"product_id":"2","product_name":"stuff","description":"product with id 2 and price :15","unit_price":["TESTKUDOS:15"],"unit_total_stock":"-1","unit":"u","image":"'"$RANDOM_IMG"'","taxes":[]}' 110 MANAGED_PRODUCT_TEMPLATE='{"product_id":"3","product_name":"more stuff","description":"product with id 3 and price :10","unit_price":["TESTKUDOS:150"],"unit_total_stock":"2","unit":"u","image":"'"$RANDOM_IMG"'","taxes":[]}' 111 112 echo -n "Creating products..." 113 STATUS=$(curl 'http://localhost:9966/private/products' \ 114 -H "Authorization: Bearer $ADMIN_TOKEN" \ 115 -d "$INFINITE_PRODUCT_TEMPLATE" \ 116 -w "%{http_code}" -s -o /dev/null) 117 118 if [ "$STATUS" != "204" ] 119 then 120 exit_fail "Expected 204, product created. got: $STATUS" 121 fi 122 123 STATUS=$(curl 'http://localhost:9966/private/products' \ 124 -H "Authorization: Bearer $ADMIN_TOKEN" \ 125 -d "$MANAGED_PRODUCT_TEMPLATE" \ 126 -w "%{http_code}" -s -o /dev/null) 127 128 if [ "$STATUS" != "204" ] 129 then 130 exit_fail "Expected 204, product created. got: $STATUS" 131 fi 132 echo "OK" 133 134 135 PRODUCT_DATA=$(echo "$INFINITE_PRODUCT_TEMPLATE" | jq 'del(.product_id) | . + {description: "other description"}') 136 137 echo -n "Updating infinite stock product..." 138 STATUS=$(curl 'http://localhost:9966/private/products/2' -X PATCH \ 139 -H "Authorization: Bearer $ADMIN_TOKEN" \ 140 -d "$PRODUCT_DATA" \ 141 -w "%{http_code}" -s -o "$LAST_RESPONSE") 142 143 if [ "$STATUS" != "204" ] 144 then 145 cat "$LAST_RESPONSE" 146 exit_fail "Expected 204, updating product. got: $STATUS" 147 fi 148 149 STATUS=$(curl 'http://localhost:9966/private/products/2' \ 150 -H "Authorization: Bearer $ADMIN_TOKEN" \ 151 -w "%{http_code}" -s -o "$LAST_RESPONSE") 152 153 DESCRIPTION=$(jq -r .description < "$LAST_RESPONSE") 154 155 if [ "$DESCRIPTION" != "other description" ] 156 then 157 cat "$LAST_RESPONSE" 158 exit_fail "Expected 'other description'. Got: $DESCRIPTION" 159 fi 160 echo "OK" 161 162 MANAGED_PRODUCT_ID=$(echo "$MANAGED_PRODUCT_TEMPLATE" | jq -r '.product_id') 163 164 echo -n "Locking inventory ..." 165 166 STATUS=$(curl "http://localhost:9966/private/products/${MANAGED_PRODUCT_ID}/lock" \ 167 -H "Authorization: Bearer $ADMIN_TOKEN" \ 168 -d '{"lock_uuid":"luck","duration":{"d_us": 100000000},"unit_quantity":"10"}' \ 169 -w "%{http_code}" -s -o "$LAST_RESPONSE") 170 171 if [ "$STATUS" != "410" ] 172 then 173 cat "$LAST_RESPONSE" 174 exit_fail "Expected 410, lock failed. got: $STATUS" 175 fi 176 177 echo -n "." 178 179 STATUS=$(curl "http://localhost:9966/private/products/${MANAGED_PRODUCT_ID}/lock" \ 180 -H "Authorization: Bearer $ADMIN_TOKEN" \ 181 -d '{"lock_uuid":"luck","duration":{"d_us": 100000000},"unit_quantity":"1"}' \ 182 -w "%{http_code}" -s -o "$LAST_RESPONSE") 183 184 if [ "$STATUS" != "204" ] 185 then 186 cat "$LAST_RESPONSE" 187 exit_fail "Expected 204, lock created. got: $STATUS" 188 fi 189 echo " OK" 190 191 echo -n "Creating order to be paid..." 192 STATUS=$(curl 'http://localhost:9966/private/orders' \ 193 -H "Authorization: Bearer $ADMIN_TOKEN" \ 194 -d '{"order":{"amount":"TESTKUDOS:1","summary":"payme"},"inventory_products":[{"product_id":"'"${MANAGED_PRODUCT_ID}"'","unit_quantity":"1"}]}' \ 195 -w "%{http_code}" -s -o "$LAST_RESPONSE") 196 197 if [ "$STATUS" != "200" ] 198 then 199 cat "$LAST_RESPONSE" 200 exit_fail "Expected 200, order created. got: $STATUS" 201 fi 202 203 ORDER_ID=$(jq -e -r .order_id < "$LAST_RESPONSE") 204 #TOKEN=$(jq -e -r .token < "$LAST_RESPONSE") 205 206 STATUS=$(curl "http://localhost:9966/private/orders/${ORDER_ID}" \ 207 -H "Authorization: Bearer $ADMIN_TOKEN" \ 208 -w "%{http_code}" -s -o "$LAST_RESPONSE") 209 210 if [ "$STATUS" != "200" ] 211 then 212 cat "$LAST_RESPONSE" 213 exit_fail "Expected 200, getting order info before claming it. got: $STATUS" 214 fi 215 PAY_URL=$(jq -e -r .taler_pay_uri < "$LAST_RESPONSE") 216 217 echo -n "." 218 219 STATUS=$(curl 'http://localhost:9966/private/orders' \ 220 -H "Authorization: Bearer $ADMIN_TOKEN" \ 221 -d '{"order":{"amount":"TESTKUDOS:1","summary":"payme"},"inventory_products":[{"product_id":"'"${MANAGED_PRODUCT_ID}"'","unit_quantity":"1"}]}' \ 222 -w "%{http_code}" -s -o "$LAST_RESPONSE") 223 224 if [ "$STATUS" != "410" ] 225 then 226 cat "$LAST_RESPONSE" 227 exit_fail "Expected 410 out of stock (what remains is locked). got: $STATUS" 228 fi 229 230 echo -n "." 231 232 # Using the 'luck' inventory lock, order creation should work. 233 STATUS=$(curl 'http://localhost:9966/private/orders' \ 234 -H "Authorization: Bearer $ADMIN_TOKEN" \ 235 -d '{"order":{"amount":"TESTKUDOS:1","summary":"payme"},"lock_uuids":["luck"],"inventory_products":[{"product_id":"'"$MANAGED_PRODUCT_ID"'","unit_quantity":"1"}]}' \ 236 -w "%{http_code}" -s -o "$LAST_RESPONSE") 237 238 if [ "$STATUS" != "200" ] 239 then 240 cat "$LAST_RESPONSE" 241 exit_fail "Expected 200 OK, lock should apply. Got: $STATUS" 242 fi 243 echo " OK" 244 245 echo -n "First withdraw wallet ..." 246 rm -f "$WALLET_DB" 247 taler-wallet-cli \ 248 --no-throttle \ 249 --wallet-db="$WALLET_DB" \ 250 api \ 251 --expect-success 'withdrawTestBalance' \ 252 "$(jq -n ' 253 { 254 amount: "TESTKUDOS:5", 255 corebankApiBaseUrl: $BANK_URL, 256 exchangeBaseUrl: $EXCHANGE_URL 257 }' \ 258 --arg BANK_URL "$BANK_URL" \ 259 --arg EXCHANGE_URL "$EXCHANGE_URL" 260 )" 2>wallet-withdraw-1.err >wallet-withdraw-1.out 261 echo -n "." 262 if [ 1 = "$USE_FAKEBANK" ] 263 then 264 # Fakebank is instant... 265 sleep 0 266 else 267 sleep 10 268 # NOTE: once libeufin can do long-polling, we should 269 # be able to reduce the delay here and run wirewatch 270 # always in the background via setup 271 fi 272 echo -n "." 273 taler-exchange-wirewatch -L "INFO" -c "$CONF" -t &> taler-exchange-wirewatch.out 274 echo -n "." 275 276 timeout 60 taler-wallet-cli \ 277 --wallet-db="$WALLET_DB" \ 278 run-until-done \ 279 2>wallet-withdraw-finish-1.err \ 280 >wallet-withdraw-finish-1.out 281 echo " OK" 282 283 echo -n "Pay first order ..." 284 NOW=$(date +%s) 285 taler-wallet-cli \ 286 --no-throttle \ 287 --wallet-db="$WALLET_DB" \ 288 handle-uri "${PAY_URL}" \ 289 -y \ 290 2> wallet-pay1.err > wallet-pay1.log 291 NOW2=$(date +%s) 292 echo " OK (took $(( NOW2 - NOW)) secs )" 293 294 295 STATUS=$(curl "http://localhost:9966/private/orders/${ORDER_ID}" \ 296 -H "Authorization: Bearer $ADMIN_TOKEN" \ 297 -w "%{http_code}" -s -o "$LAST_RESPONSE") 298 299 if [ "$STATUS" != "200" ] 300 then 301 cat "$LAST_RESPONSE" 302 exit_fail "Expected 200 ok, after pay. got: $STATUS" 303 fi 304 305 ORDER_STATUS=$(jq -r .order_status < "$LAST_RESPONSE") 306 307 if [ "$ORDER_STATUS" != "paid" ] 308 then 309 cat "$LAST_RESPONSE" 310 exit_fail "Expected 'paid'. got: $ORDER_STATUS" 311 fi 312 313 314 echo -n "Updating product..." 315 316 PRODUCT_DATA=$(echo "$MANAGED_PRODUCT_TEMPLATE" | jq 'del(.product_id) | . + {"total_stock": (.total_stock + 2) }') 317 318 STATUS=$(curl 'http://localhost:9966/private/products/3' -X PATCH \ 319 -H "Authorization: Bearer $ADMIN_TOKEN" \ 320 -d "$PRODUCT_DATA" \ 321 -w "%{http_code}" -s -o "$LAST_RESPONSE") 322 323 if [ "$STATUS" != "204" ] 324 then 325 cat "$LAST_RESPONSE" 326 exit_fail "Expected 204, updating product. got: $STATUS" 327 fi 328 329 echo -n "Requesting inventory..." 330 STATUS=$(curl 'http://localhost:9966/private/products?name_filter=more' \ 331 -H "Authorization: Bearer $ADMIN_TOKEN" \ 332 -w "%{http_code}" -s -o "$LAST_RESPONSE") 333 334 if [ "$STATUS" != "200" ] 335 then 336 cat "$LAST_RESPONSE" 337 exit_fail "Expected 200. got: $STATUS" 338 fi 339 340 PRODUCT_COUNT=$(jq -r '.products|length' < "$LAST_RESPONSE") 341 342 if [ "$PRODUCT_COUNT" != "1" ] 343 then 344 cat "$LAST_RESPONSE" 345 exit_fail "Expected one product for the 'more'. filter, got: $PRODUCT_COUNT" 346 fi 347 echo " OK" 348 349 echo "Test PASSED" 350 351 exit 0