PayPal IPN Listener
, (*1)
A PayPal IPN (Instant Payment Notification) listener for PHP, (*2)
Index
Prerequisites
- PHP >=7.1.0
- A good understanding of how the PayPal Instant Payment Notification system works (see here)
Installation
composer require mike182uk/paypal-ipn-listener
Architecture
This package is made up of several components that work together:, (*3)
-
Listener
- Listens for and processes the IPN messages
-
Verifier
- Verifies the IPN message with PayPal
-
Service
- Communicates with PayPal
-
Message
- Wrapper around the IPN message
-
MessageFactory
- Creates a new message instance from a data source
-
EventDispatcher
- Dispatches events
The listener creates a Message
using a MessageFactory
. The Message
is passed to the Verifier
which uses a Service
to communicate with PayPal. The Listener
uses the EventDispatcher
to dispatch events relating to the outcome of the IPN message verification., (*4)
The MessageFactory
and Service
components are swappable components., (*5)
This package provides 2 message factories:, (*6)
-
Mdb\PayPal\Ipn\MessageFactory\InputStreamMessageFactory
- Creates a message from the php://input
stream
-
Mdb\PayPal\Ipn\MessageFactory\ArrayMessageFactory
- Creates a message from an array passed to the setData
method
This package provides 1 service:, (*7)
-
Mdb\PayPal\Ipn\Service\GuzzleService
- Uses Guzzle to communicate with PayPal
Usage
You can either build up the listener object manually or you can use a listener builder. This package provides 2 listener builders:, (*8)
-
Mdb\PayPal\Ipn\ListenerBuilder\Guzzle\InputStreamListenerBuilder
- Builds a listener using the guzzle service and the input stream message factory
-
Mdb\PayPal\Ipn\ListenerBuilder\Guzzle\ArrayListenerBuilder
- Builds a listener using the guzzle service and the array message factory
Using a listener builder is the preferred way of building up a listener object., (*9)
Using a listener builder
use Mdb\PayPal\Ipn\ListenerBuilder\Guzzle\InputStreamListenerBuilder as ListenerBuilder;
$listener = (new ListenerBuilder)->build();
Building up the listener manually
use GuzzleHttp\Client;
use Mdb\PayPal\Ipn\InputStream;
use Mdb\PayPal\Ipn\Listener;
use Mdb\PayPal\Ipn\MessageFactory\InputStreamMessageFactory;
use Mdb\PayPal\Ipn\Service\GuzzleService;
use Mdb\PayPal\Ipn\Verifier;
use Symfony\Component\EventDispatcher\EventDispatcher;
$service = new GuzzleService(
new Client(),
'https://www.sandbox.paypal.com/cgi-bin/webscr'
);
$verifier = new Verifier($service);
$messageFactory = new InputStreamMessageFactory(new InputStream());
$listener = new Listener(
$messageFactory,
$verifier,
new EventDispatcher()
);
A lot of plumbing is needed to create the listener manually. The job of the listener builder is to abstract away this logic., (*10)
Subscribing to events
Once you have created the listener object you can subscribe to the events that it will dispatch:, (*11)
use Mdb\PayPal\Ipn\Event\MessageVerifiedEvent;
use Mdb\PayPal\Ipn\Event\MessageInvalidEvent;
use Mdb\PayPal\Ipn\Event\MessageVerificationFailureEvent;
$listener->onVerified(function (MessageVerifiedEvent $event) {
$ipnMessage = $event->getMessage();
// IPN message was verified, everything is ok! Do your processing logic here...
});
$listener->onInvalid(function (MessageInvalidEvent $event) {
$ipnMessage = $event->getMessage();
// IPN message was was invalid, something is not right! Do your logging here...
});
$listener->onVerificationFailure(function (MessageVerificationFailureEvent $event) {
$error = $event->getError();
// Something bad happend when trying to communicate with PayPal! Do your logging here...
});
You can use any callable when subscribing to an event:, (*12)
class IpnProcessor
{
public function onVerified(MessageVerifiedEvent $event)
{
$message = $event->getMessage();
// ...
}
}
$listener->onVerified(array(new IpnProcessor, 'onVerified'));
class IpnProcessor
{
public static function onVerified(MessageVerifiedEvent $event)
{
$message = $event->getMessage();
// ...
}
}
$listener->onVerified(array('IpnProcessor', 'onVerified'));
Listening for IPN messages
The last thing you need to do to kick of the process is listen for an IPN message:, (*13)
$listener->listen();
Full Example
use Mdb\PayPal\Ipn\Event\MessageVerifiedEvent;
use Mdb\PayPal\Ipn\Event\MessageInvalidEvent;
use Mdb\PayPal\Ipn\Event\MessageVerificationFailureEvent;
use Mdb\PayPal\Ipn\ListenerBuilder\Guzzle\InputStreamListenerBuilder as ListenerBuilder;
$listener = (new ListenerBuilder)->build();
$listener->onVerified(function (MessageVerifiedEvent $event) {
$ipnMessage = $event->getMessage();
// IPN message was verified, everything is ok! Do your processing logic here...
});
$listener->onInvalid(function (MessageInvalidEvent $event) {
$ipnMessage = $event->getMessage();
// IPN message was was invalid, something is not right! Do your logging here...
});
$listener->onVerificationFailure(function (MessageVerificationFailureEvent $event) {
$error = $event->getError();
// Something bad happend when trying to communicate with PayPal! Do your logging here...
});
$listener->listen();
Sandbox mode
When using one of the provided listener builders you can set your listener to use PayPal's sandbox for testing purposes:, (*14)
$listenerBuilder = new ListenerBuilder();
$listenerBuilder->useSandbox(); // use PayPal sandbox
$listener = $listenerBuilder->build();
You can find some full usage examples in the examples directory., (*15)
Extending
To create your own service you must implement Mdb\PayPal\Ipn\Service
., (*16)
To create your own message factory you must implement Mdb\PayPal\Ipn\MessageFactory
., (*17)
To create your own listener builder it is best to extend Mdb\PayPal\Ipn\ListenerBuilder
as this provides most of the boilerplate code needed to create a listener builder., (*18)
You will notice that when using any of the provided guzzle listener builders that there is a useSandbox
method exposed. You can add this functionality to your listener builder by using the Mdb\PayPal\Ipn\ListenerBuilder\ModeDependentServiceEndpoint
trait (see Mdb\PayPal\Ipn\ListenerBuilder\GuzzleListenerBuilder
for usage example)., (*19)
Notes
Testing
PayPal provides an IPN simulator here., (*20)