Reputation: 23778
Q | A |
---|---|
Yii version | 1.1.14 |
PHP version | 5.6.4 |
Guzzle version | 6.* |
Operating system | Ubuntu |
I am facing an issue and the problem is not related to the corrupt install of php or the php-fpm as the same code runs properly outside Yii framework.
Interestingly this happens when i create a pool of requests to be executed inside the Yii framework but if i dont use GuzzleHttp\Pool
and just send a single request and try to use the promise everything works fine.
Here are the classes used and the code, I am using a custom written php client for dejavoo IPOSTransact Gateway and use it inside a console job to open batch and settle the payments.
Below is the code when sending a single request from the console command
class DejavooSettlementCommand extends CConsoleCommand
{
public function run($args)
{
Yii::import("application.components.PaymentHelper");
Yii::import("application.modules.dejavoo.models.*");
//get all the merchants from the database
$merchants = DejavooMerchants::getMerchantsArray();
$iposTransact = new IposTransact();
$iposTransact->setAuthToken($merchants[0]['ipos_transact_token']);
$iposTransact->setTpn($merchants[0]['merchant_id']);
$iposTransact->initClient(Transact::class);
$promise = $iposTransact->getOpenBatch();
$promise->then(function ($response) {
echo "here";
Yii::log("Resolved the promise :" . $response->getBody(), CLogger::LEVEL_TRACE);
})->wait();
}
}
The above code runs and returns the response correctly.
Below is the code that i use for sending the concurrent requests in console command file
class DejavooSettlementCommand extends CConsoleCommand
{
public function run($args)
{
Yii::import("application.components.PaymentHelper");
Yii::import("application.modules.dejavoo.models.*");
//get all the merchants from the database
$merchants = DejavooMerchants::getMerchantsArray();
$iposTransact = new IposTransact();
$iposTransact->setAuthToken($merchants[0]['ipos_transact_token']);
$iposTransact->initClient(Transact::class);
$iposTransact->sendOpenBatchRequest($merchants);
}
}
The above code throws the following exception
PHP Error[2]: include(Throwable.php): failed to open stream: No such file or directory
in file /var/www/html/Bottle360/yii/framework/YiiBase.php at line 427
#0 /var/www/html/Bottle360/yii/framework/YiiBase.php(427): autoload()
#1 unknown(0): autoload()
#2 unknown(0): spl_autoload_call()
#3 /var/www/html/Bottle360/vendor/guzzlehttp/guzzle/src/Exception/GuzzleException.php(6): interface_exists()
#4 /var/www/html/Bottle360/vendor/composer/ClassLoader.php(571): include()
#5 /var/www/html/Bottle360/vendor/composer/ClassLoader.php(428): Composer\Autoload\includeFile()
#6 unknown(0): Composer\Autoload\ClassLoader->loadClass()
#7 /var/www/html/Bottle360/vendor/guzzlehttp/guzzle/src/Exception/TransferException.php(5): spl_autoload_call()
#8 /var/www/html/Bottle360/vendor/composer/ClassLoader.php(571): include()
#9 /var/www/html/Bottle360/vendor/composer/ClassLoader.php(428): Composer\Autoload\includeFile()
#10 unknown(0): Composer\Autoload\ClassLoader->loadClass()
#11 /var/www/html/Bottle360/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php(13): spl_autoload_call()
#12 /var/www/html/Bottle360/vendor/composer/ClassLoader.php(571): include()
#13 /var/www/html/Bottle360/vendor/composer/ClassLoader.php(428): Composer\Autoload\includeFile()
#14 unknown(0): Composer\Autoload\ClassLoader->loadClass()
#15 /var/www/html/Bottle360/vendor/guzzlehttp/guzzle/src/Exception/ConnectException.php(12): spl_autoload_call()
#16 /var/www/html/Bottle360/vendor/composer/ClassLoader.php(571): include()
#17 /var/www/html/Bottle360/vendor/composer/ClassLoader.php(428): Composer\Autoload\includeFile()
#18 unknown(0): Composer\Autoload\ClassLoader->loadClass()
#19 /var/www/html/Bottle360/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php(200): spl_autoload_call()
#20 /var/www/html/Bottle360/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php(155): createRejection()
#21 /var/www/html/Bottle360/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php(105): finishError()
#22 /var/www/html/Bottle360/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php(202): finish()
#23 /var/www/html/Bottle360/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php(130): GuzzleHttp\Handler\CurlMultiHandler->processMessages()
#24 /var/www/html/Bottle360/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php(145): GuzzleHttp\Handler\CurlMultiHandler->tick()
#25 /var/www/html/Bottle360/vendor/guzzlehttp/promises/src/Promise.php(248): GuzzleHttp\Handler\CurlMultiHandler->execute()
#26 /var/www/html/Bottle360/vendor/guzzlehttp/promises/src/Promise.php(224): GuzzleHttp\Promise\Promise->invokeWaitFn()
#27 /var/www/html/Bottle360/vendor/guzzlehttp/promises/src/Promise.php(269): GuzzleHttp\Promise\Promise->waitIfPending()
#28 /var/www/html/Bottle360/vendor/guzzlehttp/promises/src/Promise.php(226): GuzzleHttp\Promise\Promise->invokeWaitList()
#29 /var/www/html/Bottle360/vendor/guzzlehttp/promises/src/Promise.php(62): GuzzleHttp\Promise\Promise->waitIfPending()
#30 /var/www/html/Bottle360/vendor/guzzlehttp/promises/src/EachPromise.php(108): GuzzleHttp\Promise\Promise->wait()
#31 /var/www/html/Bottle360/vendor/guzzlehttp/promises/src/Promise.php(248): GuzzleHttp\Promise\EachPromise->GuzzleHttp\Promise\{closure}()
#32 /var/www/html/Bottle360/vendor/guzzlehttp/promises/src/Promise.php(224): GuzzleHttp\Promise\Promise->invokeWaitFn()
#33 /var/www/html/Bottle360/vendor/guzzlehttp/promises/src/Promise.php(269): GuzzleHttp\Promise\Promise->waitIfPending()
#34 /var/www/html/Bottle360/vendor/guzzlehttp/promises/src/Promise.php(226): GuzzleHttp\Promise\Promise->invokeWaitList()
#35 /var/www/html/Bottle360/vendor/guzzlehttp/promises/src/Promise.php(62): GuzzleHttp\Promise\Promise->waitIfPending()
#36 /var/www/html/Bottle360/protected/commands/DejavooSettlementCommand.php(88): GuzzleHttp\Promise\Promise->wait()
#37 /var/www/html/Bottle360/protected/commands/DejavooSettlementCommand.php(15): DejavooSettlementCommand->test()
#38 /var/www/html/Bottle360/yii/framework/console/CConsoleCommandRunner.php(71): DejavooSettlementCommand->run()
#39 /var/www/html/Bottle360/yii/framework/console/CConsoleApplication.php(92): CConsoleCommandRunner->run()
#40 /var/www/html/Bottle360/yii/framework/base/CApplication.php(180): CConsoleApplication->processRequest()
#41 /var/www/html/Bottle360/cronjob.php(11): CConsoleApplication->run()
Yii component IposTransact.php
that extends the base component Transact
class stripping off extra code from the class
<?php
namespace application\components;
use GuzzleHttp\Pool;
use GuzzleHttp\Psr7\Response;
use b360\paymentgateways\dejavoo\Transact;
use GuzzleHttp\Exception\RequestException;
use application\modules\dejavoo\models\DejavooOpenBatchLogs;
use b360\dejavoo\finals\TransactParams;
use b360\dejavoo\Transact as DejavooTransact;
use CLogger;
use Exception;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Promise\Promise;
use Psr\Http\Message\ResponseInterface;
use Yii;
class IposTransact extends Transact
{
/**
* @return Promise
*/
public function getOpenBatch()
{
\Yii::log("sending openbatch from IposTransact ", CLogger::LEVEL_TRACE);
//sends request to the spin proxy sale endpoint
return $this->getClient()->openBatch();
}
public function sendOpenBatchRequest($batches)
{
//call parent implementation
$pool = parent::sendOpenBatchRequest($batches);
$pool->promise()->wait();
// print_r($pool->each);
print_r($pool);
}
}
Base Yii component Transact.php
that is extended by IposTransact.php
class above
<?php
namespace b360\paymentgateways\dejavoo;
use CApplicationComponent;
use GuzzleHttp\Psr7\Response;
use b360\dejavoo\finals\TransactParams;
use b360\dejavoo\Transact as DejavooTransact;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Pool;
use Psr\Http\Message\ResponseInterface;
class Transact extends CApplicationComponent
{
//holds the auth token
/**
* @var mixed
*/
protected $authToken;
//holds the merchant ID
/**
* @var mixed
*/
protected $tpn;
//hold the environment sandbox/live
/**
* @var mixed
*/
protected $env;
//guzzel HTTP client
/**
* @var mixed
*/
private $client;
//holds the current request response
/**
* @var mixed
*/
public $response;
//saves the request params
/**
* @var mixed
*/
public $request;
/**
* Initializes the client for the Dejavoo gate way.
*/
public function initClient($clientType)
{
//initilize the client
$client = new $clientType(
$this->getTpn(),
$this->getAuthToken(),
$this->getEnv()
);
//set the client
$this->setClient($client);
}
/**
* Sends open batch requests to the IPOS Transact API
*
* @param array $merchants the array of the merchants
* to open the batches for settlement
*
*/
public function sendOpenBatchRequest($merchants)
{
//prepare default options
$defaultOptions = [
'merchantAuthentication' => [
TransactParams::MERCHANT_ID => $this->getTPN(),
],
'transactionRequest' => [
TransactParams::TRANSACTION_TYPE => DejavooTransact::TRANSACTION_TYPE_OPEN_BATCH,
],
];
$requests = function ($merchants) use (&$defaultOptions) {
foreach ($merchants as $merchant) {
yield function () use (&$merchant, &$defaultOptions) {
$this->setTpn($merchant['merchant_id']);
$this->initClient(DejavooTransact::class);
//set the request property for the logs usage
$this->setRequest($defaultOptions);
return $this->getClient()->openBatch();
};
}
};
//pool the requests to make concurrent requests and get the responses via promise
$pool = new Pool(
$this->getClient()->getHttpClient(),
$requests($merchants),
[
"concurrency" => 2,
"fulfilled" => function (ResponseInterface $response) {
//set the reesponse property
$this->setResponse($response);
$res=$response->getBody();
\Yii::log("Response: {$res}");
//save the open batch logs to db
// $this->saveOpenBatchLogs();
},
"rejected" => function (RequestException $response) {
echo "rejected";
},
]
);
return $pool;
}
Dejavoo php client class Transact.php
<?php
namespace b360\dejavoo;
use b360\dejavoo\finals\TransactParams;
use CLogger;
use GuzzleHttp\Client;
use GuzzleHttp\Pool;
use GuzzleHttp\Psr7\Request;
class Transact
{
//holds the auth token
protected $authToken;
//holds the merchant ID
protected $tpn;
//guzzel HTTP client
private $client;
//holds the current request response
public $response;
//base urls for sandbox and live
const BASE_URL_SANDBOX = 'https://payment.ipospays.tech/';
const BASE_URL = ''; //note: need to ask for live url once live
//sandbox and live mode
const MODE_SANDBOX = 'sandbox';
const MODE_LIVE = 'live';
//request types
const REQUEST_POST = 'POST';
const REQUEST_GET = 'GET';
/**
* Sets the GuzzleHttp\Client object
*
* @param string $mode the sasndbox or the live moe to be used for the request
*
* @return void
*/
public function setHttpClient($mode)
{
$baseUrl = $mode === self::MODE_LIVE ? self::BASE_URL : self::BASE_URL_SANDBOX;
$this->client = new Client(
[
// Base URI is used with relative requests
'base_uri' => $baseUrl,
// You can set any number of default request options.
'timeout' => 0,
]
);
}
/**
* Sends a request to the given url.
*
* @param string $type the type of the request
* @param array $options the array for payload or custom headers
*
* @return $response|PromiseInterface
*/
public function sendRequest($type, $options = [])
{
//set the headers request
$headers = [
'Content-Type' => 'application/json',
'token' => $this->getAuthToken()
];
if ($type == self::REQUEST_POST) {
//json encode the body params for the payload
$body = json_encode($options);
//initialize the request
$request = new Request($type, self::TRANSACT_URL, $headers, $body);
} else {
//initialize the request
$request = new Request($type, self::TRANSACT_URL, $headers);
}
//send request
return $this->getHttpClient()->sendAsync($request);
}
/**
* Sends the Refund request to the Transact API
*
* @return Request the guzzel requests object
*/
public function openBatch()
{
$defaultOptions = array_merge(
$this->getAuthenticationParams(),
[
"transactionRequest" => [
TransactParams::TRANSACTION_TYPE => self::TRANSACTION_TYPE_OPEN_BATCH
]
]
);
return $this->sendRequest(self::REQUEST_POST, $defaultOptions);
}
}
Now the same code i.e using the GuzzelHttp\Pool
that throws the listed exception above inside Yii1.1.14
if I extract that code in a simple .php
file, that code works like a charm.
Note: this rules out the Yii extended component (IposTransact.php
) and base component (Transact.php
) and only involves the dejvoo-php client class Transact.php
<?php
require dirname(__FILE__) . DIRECTORY_SEPARATOR . 'vendor/autoload.php';
use b360\dejavoo\Transact;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Pool;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Psr7\Response;
use Psr\Http\Message\ResponseInterface;
$merchants = [
[
"merchant_id" => "125852036987",
"ipos_transact_token" => "THE_TOKEN"
],
[
"merchant_id" => "214523698741",
"ipos_transact_token" => "THE_TOKEN"
]
];
$pool = sendOpenBatchRequest($merchants);
$pool->promise()->wait();
function sendOpenBatchRequest($merchants)
{
$tpn = "124521452112";
$token = "THE_TOKEN";
$transact = new Transact($tpn, $token);
$requests = function ($merchants) use (&$transact) {
foreach ($merchants as $merchant) {
yield function () use (&$merchant, &$transact) {
return $transact->openBatch();
};
}
};
//pool the requests to make concurrent requests and get the responses via promise
$pool = new Pool(
$transact->getHttpClient(),
$requests($merchants),
[
"concurrency" => 2,
"fulfilled" => function (ResponseInterface $response) {
//set the reesponse property
$res = $response->getBody();
echo $res;
},
"rejected" => function (RequestException $response) {
echo "rejected";
},
]
);
return $pool;
}
Any help or suggestions are welcome.
Regards,
Muhammad Omer Aslam
Upvotes: 0
Views: 18