thephpleague / omnipay

A framework agnostic, multi-gateway payment processing library for PHP 5.6+
http://omnipay.thephpleague.com/
MIT License
5.92k stars 928 forks source link

interception of all raw requests and responses #527

Open 4n70w4 opened 5 years ago

4n70w4 commented 5 years ago

Hi, tell me how can I make any handler and register it in your library or implement it through the http-client so that I can log all the requests and answers? Do you have any idea how this can be implemented without editing the code? This is very useful for developing and debugging, as well as for investigations exceptions in production.

4n70w4 commented 5 years ago

I tried to create a \GuzzleHttp\Client object and add a handler to it.

But the call to Omnipay::create($gateway_name, $client); rejects my object because \GuzzleHttp\Client does not implement your interface \Omnipay\Common\Http\ClientInterface.

Ok. I wrap my object through your \Omnipay\Common\Http\Client($client); But getting an exception: URI must be a string or UriInterface from: vendor/guzzlehttp/psr7/src/functions.php:62

$logger = (new \Monolog\Logger('omnipay'))->pushHandler(
    new \Monolog\Handler\RotatingFileHandler('/var/www/app/current/var/logs/omnipay.log')
);

$s = \GuzzleHttp\Middleware::log($logger, new \GuzzleHttp\MessageFormatter(MessageFormatter::DEBUG));

$handlerStack = \GuzzleHttp\HandlerStack::create();
$handlerStack->push($s);
$client = new \GuzzleHttp\Client(['handler' => $handlerStack]);

$wrap = new \Omnipay\Common\Http\Client($client);

$gateway = Omnipay::create($gateway_name, $wrap);
4n70w4 commented 5 years ago

However, I can directly (bypassing your Omnipay::create() factory) create a gateway object and pass my \GuzzleHttp\Client object to it! Although it does not implement the \Omnipay\Common\Http\Client Interface.

The request will succeed and the logging to the file will be executed! But without the factory is not convenient, because need a lot of gateways.

$logger = (new \Monolog\Logger('omnipay'))->pushHandler(
    new \Monolog\Handler\RotatingFileHandler('/var/www/app/current/var/logs/omnipay.log')
);

$s = \GuzzleHttp\Middleware::log($logger, new \GuzzleHttp\MessageFormatter(MessageFormatter::DEBUG));

$handlerStack = \GuzzleHttp\HandlerStack::create();
$handlerStack->push($s);
$client = new \GuzzleHttp\Client(['handler' => $handlerStack]);

$gateway = new \Omnipay\Bitcoin\Gateway($client);

Tell me where I made a mistake, or in your library something is wrong.

4n70w4 commented 5 years ago

@Namek @greydnls

you had a similar discussion. Do you have a solution to this question?

Namek commented 5 years ago

sorry, it's been super long time ago, I even (gladly) don't work with PHP anymore

nocive commented 5 years ago

Bump! Dealing with the same use scenario (setting a handler to be able to log the requests & responses) and facing the exact same issue.

nocive commented 5 years ago

Ok, I figured this out, you have to instantiate the php-http/guzzle6 adapter instead of guzzle's client directly. For those out there potentially struggling with the same, took me 2 days to figure this out, so I hope this saves you the trouble:

public function __construct($httpClient = null, RequestFactory $requestFactory = null)
{
    $stack = HandlerStack::create();
    $stack->push(Middleware::log(new \Monolog\Logger('ffs'), new MessageFormatter()));
    $httpClient = new \Http\Adapter\Guzzle6\Client(new \GuzzleHttp\Client(['handler' => $stack]));

    parent::__construct($httpClient, $requestFactory);
}

Notice the client instantiation, you have to instantiate the guzzle adapter and feed it the guzzle client.

cc @4n70w4

4n70w4 commented 5 years ago

@nocive does it work in production?

nocive commented 5 years ago

@4n70w4 sure, why wouldn’t it? That should be up to your logger configuration, not guzzle or omnipay.

In the example above you have to replace \Monolog\Logger(‘ffs’) with your own logger instance.