Skip to content

Commit

Permalink
[Transaction by session] (#8)
Browse files Browse the repository at this point in the history
* transaction-by-session-id: update README

* transaction-by-session-id: endpoint method, request, response & api test

* transaction-by-session-id: tests in progress

* transaction-by-session-id: PurchaseInfoRequest success test

* transaction-by-session-id: finished PurchaseInfoRequest tests
  • Loading branch information
mysiar authored May 18, 2022
1 parent e14986b commit 7a03232
Show file tree
Hide file tree
Showing 13 changed files with 347 additions and 6 deletions.
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@

## API endpoints implemented

| API endpoint | Gateway method |
|:-----------------------------|:------------------|
| /api/v1/testAccess | testAccess |
| /api/v1/payment/methods | methods |
| /api/v1/transaction/register | purchase |
| /api/v1/transaction/verify | completePurchase |
| API endpoint | Gateway method |
|:---------------------------------|:-----------------|
| /api/v1/testAccess | testAccess |
| /api/v1/payment/methods | methods |
| /api/v1/transaction/register | purchase |
| /api/v1/transaction/verify | completePurchase |
| /api/v1/transaction/by/sessionId | purchaseInfo |

## Install

Expand Down
11 changes: 11 additions & 0 deletions src/Gateway.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Omnipay\Common\Message\AbstractRequest;
use Omnipay\Przelewy24\Message\CompletePurchaseRequest;
use Omnipay\Przelewy24\Message\MethodsRequest;
use Omnipay\Przelewy24\Message\PurchaseInfoRequest;
use Omnipay\Przelewy24\Message\PurchaseRequest;
use Omnipay\Przelewy24\Message\TestAccessRequest;

Expand Down Expand Up @@ -140,4 +141,14 @@ public function completePurchase(array $options = []): CompletePurchaseRequest
{
return $this->createRequest(CompletePurchaseRequest::class, $options);
}

/**
* @return AbstractRequest|PurchaseInfoRequest
*/
public function purchaseInfo(string $sessionId): PurchaseInfoRequest
{
return $this->createRequest(PurchaseInfoRequest::class, [
'sessionId' => $sessionId,
]);
}
}
5 changes: 5 additions & 0 deletions src/Message/AbstractResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,9 @@ public function isSuccessful(): bool
{
return self::HTTP_OK === $this->getCode();
}

protected function getAmountFromInternal(int $amount): string
{
return bcdiv((string) $amount, '100', 2);
}
}
36 changes: 36 additions & 0 deletions src/Message/PurchaseInfoRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

declare(strict_types=1);

namespace Omnipay\Przelewy24\Message;

class PurchaseInfoRequest extends AbstractRequest
{
public function getSessionId(): string
{
return $this->getParameter('sessionId');
}

public function setSessionId(string $value): self
{
return $this->setParameter('sessionId', $value);
}

public function getData(): array
{
$this->validate('sessionId');

return [
'sessionId' => $this->getSessionId(),
];
}

public function sendData($data)
{
$httpResponse = $this->sendRequest('GET', sprintf('transaction/by/sessionId/%s', $data['sessionId']), []);

$responseData = json_decode($httpResponse->getBody()->getContents(), true);

return $this->response = new PurchaseInfoResponse($this, $responseData);
}
}
82 changes: 82 additions & 0 deletions src/Message/PurchaseInfoResponse.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?php

declare(strict_types=1);

namespace Omnipay\Przelewy24\Message;

use Omnipay\Common\Message\RequestInterface;
use Symfony\Component\HttpFoundation\Response;

class PurchaseInfoResponse extends AbstractResponse
{
/**
* @var string[]
*/
private $info = [];

public function __construct(RequestInterface $request, $data)
{
parent::__construct($request, $data);
if (isset($data['data'])) {
$this->info = $this->formatInfo($data['data']);
}
}

/**
* @return string[]
*/
public function getInfo(): array
{
return $this->info;
}

public function getCode(): int
{
if (isset($this->data['responseCode']) && isset($this->data['error']) && strlen($this->data['error']) > 0) {
return Response::HTTP_NOT_FOUND;
}

if (isset($this->data['code'])) {
return $this->data['code'];
}

return self::HTTP_OK;
}

/**
* @param string[] $data
* @return string[]
*/
private function formatInfo(array $data): array
{
$formatted = $data;

// format
if (isset($formatted['amount'])) {
$formatted['amount'] = $this->getAmountFromInternal((int) $formatted['amount']);
}

// replace keys
$formatted = $this->replaceInfoKeys($formatted, 'clientEmail', 'email');
$formatted = $this->replaceInfoKeys($formatted, 'clientName', 'name');
$formatted = $this->replaceInfoKeys($formatted, 'clientAddress', 'address');
$formatted = $this->replaceInfoKeys($formatted, 'clientCity', 'city');
$formatted = $this->replaceInfoKeys($formatted, 'clientPostcode', 'postcode');

return $formatted;
}

/**
* @param string[] $data
* @return string[]
*/
private function replaceInfoKeys(array $data, string $oldKey, string $newKey): array
{
if (isset($data[$oldKey])) {
$data[$newKey] = $data[$oldKey];
unset($data[$oldKey]);
}

return $data;
}
}
20 changes: 20 additions & 0 deletions tests-api/GatewayTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Omnipay\Omnipay;
use Omnipay\Przelewy24\Message\AbstractResponse;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\VarDumper\VarDumper;

class GatewayTest extends TestCase
Expand Down Expand Up @@ -99,6 +100,25 @@ public function testComplete(): void

VarDumper::dump($response->getCode());
VarDumper::dump($response->getMessage());

$this->assertSame(Response::HTTP_OK, $response->getCode());
$this->assertTrue($response->isSuccessful());
}

public function testPurchaseInfo(): void
{
$sessionId = '20c62d6b-5ff0-46a0-97eb-eea0dd5b4a93'; // real existing session
$response = $this->gateway->purchaseInfo($sessionId)->send();

VarDumper::dump($response->getCode());
VarDumper::dump($response->getInfo());

$this->assertSame(Response::HTTP_OK, $response->getCode());
$this->assertTrue($response->isSuccessful());
$this->assertCount(18, $response->getInfo());

$response = $this->gateway->purchaseInfo('not-existing')->send();
$this->assertSame(Response::HTTP_NOT_FOUND, $response->getCode());
}

public function testPurchaseCard(): void
Expand Down
11 changes: 11 additions & 0 deletions tests/GatewayTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Omnipay\Przelewy24\Gateway;
use Omnipay\Przelewy24\Message\CompletePurchaseRequest;
use Omnipay\Przelewy24\Message\MethodsRequest;
use Omnipay\Przelewy24\Message\PurchaseInfoRequest;
use Omnipay\Przelewy24\Message\PurchaseRequest;
use Omnipay\Przelewy24\Message\TestAccessRequest;
use Omnipay\Tests\GatewayTestCase;
Expand Down Expand Up @@ -169,4 +170,14 @@ public function it_should_create_a_complete_purchase()
$this->assertInstanceOf(CompletePurchaseRequest::class, $request);
$this->assertSame('10.00', $request->getAmount());
}

/**
* @test
*/
public function it_should_create_a_purchase_info()
{
$request = $this->gateway->purchaseInfo('session-id');
$this->assertInstanceOf(PurchaseInfoRequest::class, $request);
$this->assertSame('session-id', $request->getSessionId());
}
}
95 changes: 95 additions & 0 deletions tests/Message/PurchaseInfoRequestTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<?php

declare(strict_types=1);

namespace Message;

use Omnipay\Przelewy24\Message\PurchaseInfoRequest;
use Omnipay\Przelewy24\Message\PurchaseInfoResponse;
use Omnipay\Tests\TestCase;
use Symfony\Component\HttpFoundation\Response;

class PurchaseInfoRequestTest extends TestCase
{
/**
* @var PurchaseInfoRequest
*/
private $request;

public function setUp()
{
$this->request = new PurchaseInfoRequest($this->getHttpClient(), $this->getHttpRequest());
$this->request->initialize([
'sessionId' => '1234567890',
]);
}

public function testGetData(): void
{
$data = $this->request->getData();

$this->assertSame('1234567890', $data['sessionId']);
}

public function testSendSuccess()
{
$this->setMockHttpResponse('PurchaseInfoSuccess.txt');
$response = $this->request->send();

$this->assertInstanceOf(PurchaseInfoResponse::class, $response);
$this->assertTrue($response->isSuccessful());
$this->assertSame(Response::HTTP_OK, $response->getCode());
$this->assertCount(18, $response->getInfo());

$this->assertSame(1234567890, $response->getInfo()['orderId']);
$this->assertSame('20c62d6b-5ff0-46a0-97eb-eea0dd5b4a93', $response->getInfo()['sessionId']);
$this->assertSame(1, $response->getInfo()['status']);
$this->assertSame('12.34', $response->getInfo()['amount']);
$this->assertSame('PLN', $response->getInfo()['currency']);
$this->assertSame('202205161730', $response->getInfo()['date']);
$this->assertSame('202205161730', $response->getInfo()['dateOfTransaction']);
$this->assertSame(154, $response->getInfo()['paymentMethod']);
$this->assertSame('transaction description', $response->getInfo()['description']);
$this->assertSame(0, $response->getInfo()['batchId']);
$this->assertSame("12", $response->getInfo()['fee']);
$this->assertSame("P24-K12-B34-H56", $response->getInfo()['statement']);
$this->assertSame('[email protected]', $response->getInfo()['email']);
$this->assertSame('Franek Dolas', $response->getInfo()['name']);
$this->assertSame('Kościuszki 12', $response->getInfo()['address']);
$this->assertSame('Kraków', $response->getInfo()['city']);
$this->assertSame('30-611', $response->getInfo()['postcode']);
}

public function testSendAuthFailure()
{
$this->setMockHttpResponse('PurchaseInfoAuthFailure.txt');
$response = $this->request->send();

$this->assertInstanceOf(PurchaseInfoResponse::class, $response);
$this->assertFalse($response->isSuccessful());
$this->assertSame(Response::HTTP_UNAUTHORIZED, $response->getCode());
$this->assertSame('Incorrect authentication', $response->getMessage());
}

public function testSendInvalidDataFailure()
{
$this->setMockHttpResponse('PurchaseInfoInvalidDataFailure.txt');
$response = $this->request->send();

$this->assertInstanceOf(PurchaseInfoResponse::class, $response);
$this->assertFalse($response->isSuccessful());
$this->assertSame(Response::HTTP_BAD_REQUEST, $response->getCode());
$this->assertSame('Invalid input data', $response->getMessage());
}

public function testSendNotFoundFailure()
{
$this->setMockHttpResponse('PurchaseInfoNotFoundFailure.txt');
$response = $this->request->send();

$this->assertInstanceOf(PurchaseInfoResponse::class, $response);
$this->assertFalse($response->isSuccessful());
$this->assertSame(Response::HTTP_NOT_FOUND, $response->getCode());
$this->assertSame('Transaction not found', $response->getMessage());
}
}
12 changes: 12 additions & 0 deletions tests/Mock/PurchaseInfoAuthFailure.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
HTTP/1.1 201 Created
Server: nginx/1.4.4
Date: Sat, 16 May 2022 17:30:00 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Cache-Control: no-cache, no-store
X-Request-Id: 53e398c2-1c9a-4e8b-a3a7-9dcf3cad90b1

{
"error": "Incorrect authentication",
"code": 401
}
12 changes: 12 additions & 0 deletions tests/Mock/PurchaseInfoInvalidDataFailure.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
HTTP/1.1 201 Created
Server: nginx/1.4.4
Date: Sat, 16 May 2022 17:30:00 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Cache-Control: no-cache, no-store
X-Request-Id: 53e398c2-1c9a-4e8b-a3a7-9dcf3cad90b1

{
"error": "Invalid input data",
"code": 400
}
12 changes: 12 additions & 0 deletions tests/Mock/PurchaseInfoNotFound.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
HTTP/1.1 201 Created
Server: nginx/1.4.4
Date: Sat, 16 May 2022 17:30:00 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Cache-Control: no-cache, no-store
X-Request-Id: 53e398c2-1c9a-4e8b-a3a7-9dcf3cad90b1

{
"error": "Transaction not found",
"responseCode": 0
}
12 changes: 12 additions & 0 deletions tests/Mock/PurchaseInfoNotFoundFailure.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
HTTP/1.1 201 Created
Server: nginx/1.4.4
Date: Sat, 16 May 2022 17:30:00 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Cache-Control: no-cache, no-store
X-Request-Id: 53e398c2-1c9a-4e8b-a3a7-9dcf3cad90b1

{
"error": "Transaction not found",
"responseCode": 0
}
Loading

0 comments on commit 7a03232

Please sign in to comment.