From 203f64e20121cb52cd9b0871201fdc49abecf371 Mon Sep 17 00:00:00 2001 From: Steffen Brem Date: Thu, 6 Oct 2016 14:37:44 +0200 Subject: [PATCH 1/4] Added NotifyAction to omnipay bridge. --- src/Action/NotifyAction.php | 54 +++++++++++++++++++++++++++++++++++ src/OmnipayGatewayFactory.php | 4 ++- 2 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 src/Action/NotifyAction.php diff --git a/src/Action/NotifyAction.php b/src/Action/NotifyAction.php new file mode 100644 index 0000000..9df03c9 --- /dev/null +++ b/src/Action/NotifyAction.php @@ -0,0 +1,54 @@ + + */ +class NotifyAction extends BaseApiAwareAction implements GatewayAwareInterface +{ + use GatewayAwareTrait; + + /** + * {@inheritdoc} + */ + public function execute($request) + { + RequestNotSupportedException::assertSupports($this, $request); + + $details = ArrayObject::ensureArrayObject($request->getModel()); + + $response = $this->omnipayGateway->fetchTransaction($details->toUnsafeArray())->send(); + + $data = $response->getData(); + + if (is_array($data)) { + $details->replace($data); + } + + $details['_reference'] = $response->getTransactionReference(); + $details['_status'] = $response->isSuccessful() ? 'captured' : 'failed'; + $details['_status_code'] = $response->getCode(); + $details['_status_message'] = $response->isSuccessful() ? '' : $response->getMessage(); + + throw new HttpResponse('OK', 200); + } + + /** + * {@inheritdoc} + */ + public function supports($request) + { + return + $request instanceof Notify && + $request->getModel() instanceof \ArrayAccess + ; + } +} diff --git a/src/OmnipayGatewayFactory.php b/src/OmnipayGatewayFactory.php index aced18b..f7dcdf9 100644 --- a/src/OmnipayGatewayFactory.php +++ b/src/OmnipayGatewayFactory.php @@ -11,6 +11,7 @@ use Payum\Core\GatewayFactoryInterface; use Payum\OmnipayBridge\Action\CaptureAction; use Payum\OmnipayBridge\Action\ConvertPaymentAction; +use Payum\OmnipayBridge\Action\NotifyAction; use Payum\OmnipayBridge\Action\OffsiteCaptureAction; use Payum\OmnipayBridge\Action\StatusAction; @@ -50,6 +51,7 @@ protected function populateConfig(ArrayObject $config) 'payum.action.capture_offsite' => new OffsiteCaptureAction(), 'payum.action.convert_payment' => new ConvertPaymentAction(), 'payum.action.status' => new StatusAction(), + 'payum.action.notify' => new NotifyAction(), ]); if (false == $config['payum.api']) { @@ -91,4 +93,4 @@ protected function populateConfig(ArrayObject $config) }; } } -} \ No newline at end of file +} From 28b7d2458ead0b66a28192f40c1d9ae0c9444f20 Mon Sep 17 00:00:00 2001 From: Steffen Brem Date: Thu, 6 Oct 2016 17:15:22 +0200 Subject: [PATCH 2/4] * Reference isn't needed, since it will already be known. * Add `fetchTransaction` requirement to supports. --- src/Action/NotifyAction.php | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/Action/NotifyAction.php b/src/Action/NotifyAction.php index 9df03c9..c194d7c 100644 --- a/src/Action/NotifyAction.php +++ b/src/Action/NotifyAction.php @@ -27,13 +27,8 @@ public function execute($request) $response = $this->omnipayGateway->fetchTransaction($details->toUnsafeArray())->send(); - $data = $response->getData(); + $details->replace((array)$response->getData()); - if (is_array($data)) { - $details->replace($data); - } - - $details['_reference'] = $response->getTransactionReference(); $details['_status'] = $response->isSuccessful() ? 'captured' : 'failed'; $details['_status_code'] = $response->getCode(); $details['_status_message'] = $response->isSuccessful() ? '' : $response->getMessage(); @@ -48,7 +43,8 @@ public function supports($request) { return $request instanceof Notify && - $request->getModel() instanceof \ArrayAccess + $request->getModel() instanceof \ArrayAccess && + method_exists($this->omnipayGateway, 'fetchTransaction') ; } } From a299d43737505b19c133b16f11c7910d6b95ae73 Mon Sep 17 00:00:00 2001 From: Steffen Brem Date: Mon, 10 Oct 2016 15:26:07 +0200 Subject: [PATCH 3/4] * Only use the interfaces and traits, no inheritance anymore. * Added some basic unit tests for the action. --- src/Action/NotifyAction.php | 27 +++++--- tests/Action/NotifyActionTest.php | 100 ++++++++++++++++++++++++++++++ tests/MollieGateway.php | 20 ++++++ 3 files changed, 140 insertions(+), 7 deletions(-) create mode 100644 tests/Action/NotifyActionTest.php create mode 100644 tests/MollieGateway.php diff --git a/src/Action/NotifyAction.php b/src/Action/NotifyAction.php index c194d7c..8f295e5 100644 --- a/src/Action/NotifyAction.php +++ b/src/Action/NotifyAction.php @@ -2,19 +2,26 @@ namespace Payum\OmnipayBridge\Action; +use Omnipay\Common\GatewayInterface; +use Payum\Core\Action\ActionInterface; +use Payum\Core\ApiAwareInterface; +use Payum\Core\ApiAwareTrait; use Payum\Core\Bridge\Spl\ArrayObject; use Payum\Core\Exception\RequestNotSupportedException; -use Payum\Core\GatewayAwareInterface; -use Payum\Core\GatewayAwareTrait; use Payum\Core\Reply\HttpResponse; use Payum\Core\Request\Notify; /** * @author Steffen Brem */ -class NotifyAction extends BaseApiAwareAction implements GatewayAwareInterface +class NotifyAction implements ApiAwareInterface, ActionInterface { - use GatewayAwareTrait; + use ApiAwareTrait; + + public function __construct() + { + $this->apiClass = GatewayInterface::class; + } /** * {@inheritdoc} @@ -25,7 +32,11 @@ public function execute($request) $details = ArrayObject::ensureArrayObject($request->getModel()); - $response = $this->omnipayGateway->fetchTransaction($details->toUnsafeArray())->send(); + if (method_exists($this->api, 'fetchTransaction')) { + $response = $this->api->fetchTransaction($details->toUnsafeArray())->send(); + } else if (method_exists($this->api, 'acceptNotification')) { + $response = $this->api->acceptNotification($details->toUnsafeArray())->send(); + } $details->replace((array)$response->getData()); @@ -43,8 +54,10 @@ public function supports($request) { return $request instanceof Notify && - $request->getModel() instanceof \ArrayAccess && - method_exists($this->omnipayGateway, 'fetchTransaction') + $request->getModel() instanceof \ArrayAccess && ( + method_exists($this->api, 'fetchTransaction') || + method_exists($this->api, 'acceptNotification') + ) ; } } diff --git a/tests/Action/NotifyActionTest.php b/tests/Action/NotifyActionTest.php new file mode 100644 index 0000000..53da259 --- /dev/null +++ b/tests/Action/NotifyActionTest.php @@ -0,0 +1,100 @@ + + */ +class NotifyActionTest extends GenericActionTest +{ + protected $actionClass = NotifyAction::class; + + protected function setUp() + { + $this->action = new $this->actionClass(); + $this->action->setApi(new MollieGateway()); + } + + /** + * @test + */ + public function shouldSetStatusCapturedWhenSuccessful() + { + $model = new \ArrayObject([]); + + $responseMock = $this->getMock(OmnipayResponseInterface::class); + $responseMock + ->method('isSuccessful') + ->willReturn(true) + ; + + $requestMock = $this->getMock(OmnipayRequestInterface::class); + $requestMock + ->expects($this->once()) + ->method('send') + ->willReturn($responseMock) + ; + + $action = new NotifyAction(); + + $gateway = new MollieGateway(); + $gateway->returnFetchTransaction = $requestMock; + $action->setApi($gateway); + + try { + $action->execute(new Notify($model)); + } catch (HttpResponse $e) { + $this->assertEquals(200, $e->getStatusCode()); + } + + $details = iterator_to_array($model); + + $this->assertEquals('captured', $details['_status']); + } + + /** + * @test + */ + public function shouldSetStatusFailedWhenNotSuccessful() + { + $model = new \ArrayObject([]); + + $responseMock = $this->getMock(OmnipayResponseInterface::class); + $responseMock + ->method('isSuccessful') + ->willReturn(false) + ; + + $requestMock = $this->getMock(OmnipayRequestInterface::class); + $requestMock + ->expects($this->once()) + ->method('send') + ->willReturn($responseMock) + ; + + $action = new NotifyAction(); + + $gateway = new MollieGateway(); + $gateway->returnFetchTransaction = $requestMock; + $action->setApi($gateway); + + try { + $action->execute(new Notify($model)); + } catch (HttpResponse $e) { + $this->assertEquals(200, $e->getStatusCode()); + } + + $details = iterator_to_array($model); + + $this->assertEquals('failed', $details['_status']); + } +} diff --git a/tests/MollieGateway.php b/tests/MollieGateway.php new file mode 100644 index 0000000..675fa4f --- /dev/null +++ b/tests/MollieGateway.php @@ -0,0 +1,20 @@ + + */ +class MollieGateway extends AbstractGateway +{ + public $returnFetchTransaction; + + public function getName() {} + + public function fetchTransaction() + { + return $this->returnFetchTransaction; + } +} From 43f09e4d1b97540bbde2641aa5fa5eab3cbe7ea8 Mon Sep 17 00:00:00 2001 From: Steffen Brem Date: Mon, 10 Oct 2016 17:07:06 +0200 Subject: [PATCH 4/4] Added $requestClass. --- tests/Action/NotifyActionTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/Action/NotifyActionTest.php b/tests/Action/NotifyActionTest.php index 53da259..6472545 100644 --- a/tests/Action/NotifyActionTest.php +++ b/tests/Action/NotifyActionTest.php @@ -18,6 +18,8 @@ class NotifyActionTest extends GenericActionTest { protected $actionClass = NotifyAction::class; + protected $requestClass = Notify::class; + protected function setUp() { $this->action = new $this->actionClass();