bunq / sdk_php

PHP SDK for bunq API
MIT License
83 stars 54 forks source link

vsprintf(): Argument #2 ($values) must be of type array, string given - ResponseHandlerSignature.php:171 #229

Closed WouterFlorijn closed 1 year ago

WouterFlorijn commented 1 year ago

Steps to reproduce:

  1. Call ApiContext::create

What should happen:

  1. It should work.

What happens:

  1. An exception occurs.

Traceback

production.ERROR: vsprintf(): Argument #2 ($values) must be of type array, string given {"exception":"[object] (TypeError(code: 0): vsprintf(): Argument #2 ($values) must be of type array, string given at /app/vendor/bunq/sdk_php/src/Http/Handler/ResponseHandlerSignature.php:171) [stacktrace]

0 /app/vendor/bunq/sdk_php/src/Http/Handler/ResponseHandlerSignature.php(171): vsprintf('/%s/', '-c')

1 /app/vendor/bunq/sdk_php/src/Http/Handler/ResponseHandlerSignature.php(146): bunq\Http\Handler\ResponseHandlerSignature->ensureHeaderIsCorrectlyCased('Access-control-...')

2 /app/vendor/bunq/sdk_php/src/Http/Handler/ResponseHandlerSignature.php(100): bunq\Http\Handler\ResponseHandlerSignature->determineHeaderStringForSignedResponse(Array)

3 /app/vendor/bunq/sdk_php/src/Http/Handler/ResponseHandlerSignature.php(74): bunq\Http\Handler\ResponseHandlerSignature->isResponseSignatureHeaderWithBodyValid(Object(GuzzleHttp\Psr7\Response))

4 /app/vendor/bunq/sdk_php/src/Http/Handler/HandlerUtil.php(42): bunq\Http\Handler\ResponseHandlerSignature->execute(Object(GuzzleHttp\Psr7\Response))

5 /app/vendor/guzzlehttp/promises/src/Promise.php(204): bunq\Http\Handler\HandlerUtil::bunq\Http\Handler\{closure}(Object(GuzzleHttp\Psr7\Response))

6 /app/vendor/guzzlehttp/promises/src/Promise.php(153): GuzzleHttp\Promise\Promise::callHandler(1, Object(GuzzleHttp\Psr7\Response), NULL)

7 /app/vendor/guzzlehttp/promises/src/TaskQueue.php(48): GuzzleHttp\Promise\Promise::GuzzleHttp\Promise\{closure}()

8 /app/vendor/guzzlehttp/promises/src/Promise.php(248): GuzzleHttp\Promise\TaskQueue->run(true)

9 /app/vendor/guzzlehttp/promises/src/Promise.php(224): GuzzleHttp\Promise\Promise->invokeWaitFn()

10 /app/vendor/guzzlehttp/promises/src/Promise.php(269): GuzzleHttp\Promise\Promise->waitIfPending()

11 /app/vendor/guzzlehttp/promises/src/Promise.php(226): GuzzleHttp\Promise\Promise->invokeWaitList()

12 /app/vendor/guzzlehttp/promises/src/Promise.php(62): GuzzleHttp\Promise\Promise->waitIfPending()

13 /app/vendor/guzzlehttp/guzzle/src/Client.php(187): GuzzleHttp\Promise\Promise->wait()

14 /app/vendor/bunq/sdk_php/src/Http/ApiClient.php(220): GuzzleHttp\Client->request('POST', Object(GuzzleHttp\Psr7\Uri), Array)

15 /app/vendor/bunq/sdk_php/src/Http/ApiClient.php(485): bunq\Http\ApiClient->request('POST', 'device-server', Array, Array, Array)

16 /app/vendor/bunq/sdk_php/src/Model/Core/DeviceServerInternal.php(42): bunq\Http\ApiClient->post('device-server', Array, Array)

17 /app/vendor/bunq/sdk_php/src/Context/ApiContext.php(234): bunq\Model\Core\DeviceServerInternal::create('...', '...', Array, Array, Object(bunq\Context\ApiContext))

18 /app/vendor/bunq/sdk_php/src/Context/ApiContext.php(179): bunq\Context\ApiContext->registerDevice('...', Array)

19 /app/vendor/bunq/sdk_php/src/Context/ApiContext.php(119): bunq\Context\ApiContext->initialize('...', Array)

SDK version and environment

Response id

Not relevant.

Extra info:

This is clearly a bug in the code, but I have no idea why it wasn't triggered until today. I guess this part of the code was never reached?

The relevant method:

    /**
     * @param string $headerName
     *
     * @return string
     */
    private function ensureHeaderIsCorrectlyCased(string $headerName)
    {
        $headerName = ucfirst($headerName);
        $regexResult = preg_match_all(self::REGEX_FOR_LOWERCASE_HEADERS, $headerName, $matches);

        if ($regexResult != self::REGEX_CHECK_FAILED) {
            foreach ($matches[self::INDEX_FIRST] as $match) {
                $matchUpper = strtoupper($match);
                $headerName = preg_replace(vsprintf(self::REGEX_REPLACE, $match), $matchUpper, $headerName);
            }
        }

        return $headerName;
    }

As you can confirm from the code, $match will always be a string, while vsprintf only accepts an array as second argument.

ralphjsmit commented 1 year ago

We are also getting this error. This error is suddenly new from yesterday, nothing changed in our code:

Error

This needs to be merged/fixed ASAP, because our app is now not able to make payouts.

SamMousa commented 1 year ago

It won't be; bunq is not actively participating in this development at all. We've swapped to the PR commit, luckily we are phasing out the use of this API next week so we can hang on for 1 week and then finally rid ourselves of this "library" :)

ralphjsmit commented 1 year ago

@SamMousa Hmm, too bad. Are you planning/going to use the normal JSON api next week? Or switch to a different company/API?

SamMousa commented 1 year ago

Switching away from bank API in general towards voucher API for rewards (our use case).

ralphjsmit commented 1 year ago

Aha, nice! Unfortunately we cannot switch to vouchers, so I guess we'll have to deal with this. Let's hope that this gets "Ali Prio" 😂 (article)

haddocc commented 1 year ago

This is clearly a bug in the code, but I have no idea why it wasn't triggered until today. I guess this part of the code was never reached?

I thought exactly the same. I've analyzed the headers that are passed to this function. Bunq (apparently) started communicating a Access-control-allow-origin-header that triggers this codes. As this piece of code is in place to "correctly case the header name". They expect it to be Access-Control-Allow-Origin I guess, although I don't understand why that is important.