Skip to content

Commit

Permalink
Merge pull request #11 from superbrave/splits-transaction-status-to-c…
Browse files Browse the repository at this point in the history
…omplete-authorise-and-capture

Splits transaction status to complete authorise and capture
  • Loading branch information
kiettran authored Mar 3, 2020
2 parents da7868d + ef6f3b1 commit 61e5a6f
Show file tree
Hide file tree
Showing 28 changed files with 654 additions and 87 deletions.
5 changes: 3 additions & 2 deletions src/Gateway.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use DateTime;
use Omnipay\Common\AbstractGateway;
use Omnipay\Common\Message\RequestInterface;
use Omnipay\IcepayPayments\Message\CompleteAuthoriseAndCaptureRequest;
use Omnipay\IcepayPayments\Message\CreateTransactionRequest;
use Omnipay\IcepayPayments\Message\RefundRequest;
use Omnipay\IcepayPayments\Message\TransactionStatusRequest;
Expand Down Expand Up @@ -108,7 +109,7 @@ public function authorize(array $parameters = []): RequestInterface
*/
public function completeAuthorize(array $parameters = []): RequestInterface
{
return $this->fetchTransaction($parameters);
return $this->createRequest(CompleteAuthoriseAndCaptureRequest::class, $parameters);
}

/**
Expand Down Expand Up @@ -144,7 +145,7 @@ public function refund(array $parameters = []): RequestInterface
*/
public function capture(array $parameters = []): RequestInterface
{
return $this->fetchTransaction($parameters);
return $this->createRequest(CompleteAuthoriseAndCaptureRequest::class, $parameters);
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/Message/AbstractResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ abstract class AbstractResponse extends OmnipayAbstractResponse
*/
public function isSuccessful(): bool
{
return isset($this->data['contractId']);
return isset($this->data['contractId']) && isset($this->data['transactionId']);
}

/**
Expand All @@ -110,6 +110,6 @@ public function isCancelled(): bool
*/
public function getTransactionReference(): ?string
{
return $this->data['transactionId'] ?? ($this->data['providerTransactionId'] ?? null);
return $this->data['transactionId'] ?? null;
}
}
58 changes: 58 additions & 0 deletions src/Message/CompleteAuthoriseAndCaptureRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

namespace Omnipay\IcepayPayments\Message;

use Omnipay\Common\Message\ResponseInterface;
use Symfony\Component\HttpFoundation\Request;

/**
* The request for retrieving the payment transaction status when the CompleteAuthorise and Capture happens.
* The payment transaction status can be different from what we get back as data from Icepay.
*/
class CompleteAuthoriseAndCaptureRequest extends AbstractRequest
{
/**
* {@inheritdoc}
*/
public function getData(): array
{
$data = parent::getData();

$data['ContractProfileId'] = $this->getContractProfileId();

return $data;
}

/**
* {@inheritdoc}
*/
public function sendData($data): ResponseInterface
{
$this->sendRequest(
Request::METHOD_POST,
sprintf(
'/transaction/%s',
$this->getTransactionReference()
),
$data
);

return new CompleteAuthoriseAndCaptureResponse(
$this,
$this->getResponseBody()
);
}

/**
* Get the HttpRequest.
* Note: this is not an API request.
*
* @see Omnipay\Common\Message\AbstractRequest::$httpRequest
*
* @return Request
*/
public function getHttpRequest(): Request
{
return $this->httpRequest;
}
}
41 changes: 41 additions & 0 deletions src/Message/CompleteAuthoriseAndCaptureResponse.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

namespace Omnipay\IcepayPayments\Message;

/**
* The response after complete authorise and capture request.
* For this response, we explicitly check what the status is of the payment transaction at Icepay.
*/
class CompleteAuthoriseAndCaptureResponse extends AbstractResponse
{
/**
* {@inheritdoc}
*/
public function isSuccessful(): bool
{
return isset($this->data['status']) && in_array($this->data['status'], [
self::RESPONSE_STATUS_COMPLETED,
self::RESPONSE_STATUS_SETTLED,
]);
}

/**
* {@inheritdoc}
*
* In case there is no status 'cancelled' available in the response (yet), check if there is statusCode in the
* queryString. Icepay calls a postback to the completeUrl with data of the payment transaction as queryString.
*/
public function isCancelled(): bool
{
return isset($this->data['status']) && $this->data['status'] === self::RESPONSE_STATUS_CANCELLED
|| $this->request->getHttpRequest()->get('statusCode') === self::RESPONSE_STATUS_CANCELLED;
}

/**
* {@inheritdoc}
*/
public function getTransactionReference(): ?string
{
return $this->request->getTransactionReference();
}
}
2 changes: 1 addition & 1 deletion src/Message/CreateTransactionRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public function getData(): array
'TotalGrossAmountCents' => $this->getAmountInteger(),
'TotalNetAmountCents' => $this->getAmountInteger(),
],
'Description' => $this->getTransactionId(),
'Description' => $this->getDescription(),
],
];

Expand Down
7 changes: 2 additions & 5 deletions src/Message/CreateTransactionResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,7 @@ class CreateTransactionResponse extends AbstractResponse
public function isSuccessful(): bool
{
return parent::isSuccessful()
&& ($this->getTransactionReference() !== null)
&& in_array($this->data['transactionStatusCode'], [
self::RESPONSE_STATUS_STARTED,
]);
&& (isset($this->data['transactionStatusCode']) && $this->data['transactionStatusCode'] === self::RESPONSE_STATUS_STARTED);
}

/**
Expand All @@ -32,6 +29,6 @@ public function isRedirect(): bool
*/
public function getRedirectUrl(): string
{
return $this->data['acquirerRequestUri'];
return $this->data['acquirerRequestUri'] ?? '';
}
}
10 changes: 2 additions & 8 deletions src/Message/TransactionStatusRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,10 @@ public function sendData($data): ResponseInterface
$data
);

$response = array_merge(
$this->getResponseBody(),
[
'statusCode' => $this->getResponse()->getStatusCode(),
]
);

return new TransactionStatusResponse(
$this,
$response
$this->getResponseBody(),
$this->getResponse()->getStatusCode()
);
}
}
29 changes: 24 additions & 5 deletions src/Message/TransactionStatusResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,47 @@

namespace Omnipay\IcepayPayments\Message;

use Omnipay\Common\Message\RequestInterface;

/**
* The response after getting the transaction status at Icepay.
* For this response, we check the response (statusCode) of the payment transaction at Icepay.
*/
class TransactionStatusResponse extends AbstractResponse
{
/**
* @var int
*/
private $statusCode;

/**
* TransactionStatusResponse constructor.
*
* @param RequestInterface $request
* @param mixed $data
* @param int $statusCode
*/
public function __construct(RequestInterface $request, $data, int $statusCode)
{
parent::__construct($request, $data);

$this->statusCode = $statusCode;
}

/**
* {@inheritdoc}
*/
public function isSuccessful(): bool
{
return (isset($this->data['status']) && in_array($this->data['status'], [
self::RESPONSE_STATUS_COMPLETED,
self::RESPONSE_STATUS_SETTLED,
])) && (isset($this->data['statusCode']) && $this->data['statusCode'] === 200);
return $this->statusCode === 200;
}

/**
* {@inheritdoc}
*/
public function isCancelled(): bool
{
return parent::isCancelled() || $this->data['statusCode'] === self::RESPONSE_STATUS_CANCELLED;
return isset($this->data['status']) && $this->data['status'] === self::RESPONSE_STATUS_CANCELLED;
}

/**
Expand Down
5 changes: 3 additions & 2 deletions tests/GatewayTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Omnipay\Common\GatewayInterface;
use Omnipay\IcepayPayments\Gateway;
use Omnipay\IcepayPayments\Message\CompleteAuthoriseAndCaptureRequest;
use Omnipay\IcepayPayments\Message\CreateTransactionRequest;
use Omnipay\IcepayPayments\Message\RefundRequest;
use Omnipay\IcepayPayments\Message\TransactionStatusRequest;
Expand Down Expand Up @@ -92,7 +93,7 @@ public function testCompleteAuthorize(): void
{
$request = $this->gateway->completeAuthorize($this->options);

$this->assertInstanceOf(TransactionStatusRequest::class, $request);
$this->assertInstanceOf(CompleteAuthoriseAndCaptureRequest::class, $request);
}

/**
Expand All @@ -102,7 +103,7 @@ public function testCapture(): void
{
$request = $this->gateway->capture($this->options);

$this->assertInstanceOf(TransactionStatusRequest::class, $request);
$this->assertInstanceOf(CompleteAuthoriseAndCaptureRequest::class, $request);
}

/**
Expand Down
78 changes: 78 additions & 0 deletions tests/Message/CompleteAuthoriseAndCaptureRequestTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php

namespace Omnipay\IcepayPayments\Tests\Message;

use GuzzleHttp\Psr7\Request;
use Omnipay\IcepayPayments\Message\CompleteAuthoriseAndCaptureRequest;
use Omnipay\IcepayPayments\Message\CompleteAuthoriseAndCaptureResponse;
use Omnipay\IcepayPayments\Tests\AbstractTestCase;
use Symfony\Component\HttpFoundation\Request as SymfonyRequest;

/**
* Class CompleteAuthoriseAndCaptureRequestTest.
*/
class CompleteAuthoriseAndCaptureRequestTest extends AbstractTestCase
{
/**
* @var CompleteAuthoriseAndCaptureRequest
*/
protected $request;

/**
* Creates a new CompleteAuthoriseAndCaptureRequestTest instance.
*/
protected function setUp(): void
{
parent::setUp();

$this->request = new CompleteAuthoriseAndCaptureRequest($this->httpClient, $this->httpRequest);
$this->request->setBaseUrl('https://www.superbrave.nl');
$this->request->setSecretKey('NjRlYjM3MTctOGI1ZC00MDg4LTgxMDgtOTMyMjQ2NzVlNTM4');
$this->request->setContractProfileId('64eb3717-8b5d-4088-8108-93224675e538');
$this->request->setTransactionReference('e7ca29c8-f1f4-4a4c-a968-0f9667d0519d');
}

/**
* Tests if CompleteAuthoriseAndCaptureRequest::getData validates the basic keys and returns an array of data.
*/
public function testGetData(): void
{
$expectedData = [
'ContractProfileId' => '64eb3717-8b5d-4088-8108-93224675e538',
];
$this->assertEquals($expectedData, $this->request->getData());
}

/**
* Tests if CompleteAuthoriseAndCaptureRequest::sendData returns a CompleteAuthoriseAndCaptureResponse.
*/
public function testSendData(): void
{
$data = [
'AmountInCents' => 1337,
'CurrencyCode' => 'EUR',
'Reference' => '2fad9b1b-a2d3-455c-bc29-b79516fd3257',
'Timestamp' => '2019-03-09T12:00:00Z',
];
$response = $this->request->sendData($data);

$this->assertInstanceOf(CompleteAuthoriseAndCaptureResponse::class, $response);

$expectedRequest = new Request(
SymfonyRequest::METHOD_POST,
'https://www.superbrave.nl/transaction/e7ca29c8-f1f4-4a4c-a968-0f9667d0519d'
);

$this->assertEquals($expectedRequest->getMethod(), $this->clientMock->getLastRequest()->getMethod());
$this->assertEquals($expectedRequest->getUri(), $this->clientMock->getLastRequest()->getUri());
}

/**
* Tests if CompleteAuthoriseAndCaptureRequest getRequest function will return a Symfony HttpRequest object.
*/
public function testGetHttpRequest(): void
{
$this->assertSame($this->httpRequest, $this->request->getHttpRequest());
$this->assertInstanceOf(SymfonyRequest::class, $this->request->getHttpRequest());
}
}
Loading

0 comments on commit 61e5a6f

Please sign in to comment.