Problem with connecting to websocket in binance api futures

I am trying to connect to user data stream in binance api futures, but I get 504 Gateway Time Out error. It breaks where I dump $connector variable in my code. Here is my function where it breaks.

    public function userData(&$balance_callback, &$execution_callback = false)
    {
        $response = $this->httpRequest("v1/listenKey", "POST", []);

        $this->listenKey = $response['listenKey'];
        $this->info['balanceCallback'] = $balance_callback;
        $this->info['executionCallback'] = $execution_callback;

        $this->subscriptions['@userdata'] = true;

        $loop = \React\EventLoop\Factory::create();
        $loop->addPeriodicTimer(30*60, function () {
            $listenKey = $this->listenKey;
            $this->httpRequest("v1/listenKey?listenKey={$listenKey}", "PUT", []);
        });
        $connector = new \Ratchet\Client\Connector($loop);

        // @codeCoverageIgnoreStart
        // phpunit can't cover async function

        $connector($this->getWsEndpoint() . $this->listenKey)->then(function ($ws) {

        var_dump($connector);  // HERE IT BREAKS

            $ws->on('message', function ($data) use ($ws) {
                if ($this->subscriptions['@userdata'] === false) {
                    //$this->subscriptions[$endpoint] = null;
                    $ws->close();
                    return; //return $ws->close();
                }
                $json = json_decode($data);
                $type = $json->e;
                if ($type === "outboundAccountPosition") {
                    $balances = $this->balanceHandler($json->B);
                    $this->info['balanceCallback']($this, $balances);
                } elseif ($type === "executionReport") {
                    $report = $this->executionHandler($json);
                    if ($this->info['executionCallback']) {
                        $this->info['executionCallback']($this, $report);
                    }
                }
            });
            $ws->on('close', function ($code = null, $reason = null) {
                // WPCS: XSS OK.
                echo "userData: WebSocket Connection closed! ({$code} - {$reason})" . PHP_EOL;
            });
        }, function ($e) {
            // WPCS: XSS OK.
            echo "userData: Could not connect: {$e->getMessage()}" . PHP_EOL;
        });

        $loop->run();
    }

    private function getWsEndpoint() : string
    {
        return $this->stream;
    }

and $stream variable value is

protected $stream = 'wss://fstream.binance.com';

In my controller I call userData function

    $api = new Binance\API($key, $secret);
    $api->userData($call1, $call2);

I am using php 7 and jaggedsoft/php-binance-api package for this.

  1. What’s the error message?
  2. Can you subscribe to websocket server by other tools, like websocat?
  1. There is no error message, it just takes long to open request and then it shows ‘504 Gateway Time-out’ error.

  2. I am having trouble installing websocat, but when I try here https://www.piesocket.com/websocket-tester it establishes connection, but it probably doesn’t mean anything.

Also, when I changed

$response = $this->httpRequest("v1/listenKey", "POST", []); 

to

$response = $this->httpRequest("v1/userDataStream", "POST", []);

I got error

userData: WebSocket Connection closed! (1006 - Underlying connection closed)

If there is no problem connecting to websocket server from your side, there may be an issue in your code.

Here is a PHP library is written in PHP but only for spot, I suggest checking how it implements the websocket part, which may help your futures implementation.

Futures API is quite similar to spot, easy to understand both if you figure out how it works on spot side.

I tried this, altered it to correspond to futures api, and I get ‘504 timed out’ error here on line 58. binance-connector-php/Websocket.php at 897d3d87857f81fef51884b3a3e11bdebaead9c7 · binance/binance-connector-php · GitHub Where I call $conn->on( there it breaks . If I dump $conn variable just above I successfully get object(Ratchet\Client\WebSocket)#48 (6) { and etc etc .

can you share the code?

@dino

In my controller

$callbacks = [
         'message' => function ($api, $msg) {
                echo $msg.PHP_EOL;
                    },
     'ping' => function ($api, $msg) {
	        echo "received ping from server".PHP_EOL;
	        }
	];

	$listenKey = $api->getListenKey();
	$api->customUserData($listenKey, $callbacks);

in file where is api config

public function getListenKey()
{
    $response = $this->httpRequest("v1/listenKey", "POST", []);
    $this->listenKey = $response['listenKey'];

    return $this->listenKey;
}

public function handleCallBack($url, $callback)
{   
    if (is_array($callback)) {
        foreach ($callback as $event => $func) {
            if (gettype($event) == "integer") {
                throw new InvalidArgumentException("callback", json_encode($callback), "Array has event type as key, e.g. ['message' => function() {}]", "Please find example at https://github.com/binance/binance-connector-php");
            }
        }
    }
    $this->createWSConnection($url)->then(function ($conn) use ($callback) {
        $this->wsConnection = $conn;

       if (is_callable($callback)) {

            $conn->on('message', function ($msg) use ($conn, $callback) {
                $callback($conn, $msg);
            });
        }

        if (is_array($callback)) {
            foreach ($callback as $event => $func) {

                $event = strtolower(strval($event));
                if (in_array($event, ['message', 'ping', 'pong', 'close'])) {
                    
                    $conn->on($event, function ($msg) use ($conn, $func) {
                             // HERE IT BREAKS!!!

                        call_user_func($func, $conn, $msg);
                    });
                }
            }
        }
    }, function ($e) {
        $this->logger->error("Could not connect: {$e->getMessage()}".PHP_EOL);
    });
}

private function createWSConnection($url)
{
    if ($this->wsConnector) {
        return call_user_func($this->wsConnector, $url);
    } else {
        return \Ratchet\Client\connect($url);
    }
}

public function customUserData($listenKey, $callback)
{
    $url = $this->getWsEndpoint() . $this->listenKey;
    $this->handleCallBack($url, $callback);
}

@dino Also if it is any help. I tried and created websocket request in postman. And I passed in url this value

wss://fstream.binance.com/ws/?somelistenkey

where somelistenkey is generated through my getListenKey method, and I passed in JSON request bellow some payload like this

  {
     "method": "LIST_SUBSCRIPTIONS",
     "id": 1
  }

and the response was successful and it connected and showed data. Maybe this will help in some way. Any help is appreciated. Thank you anyhow :slight_smile: