Skip to content

Commit

Permalink
feat: add support for request custom headers 'X-AH-ExecutionMode'
Browse files Browse the repository at this point in the history
  • Loading branch information
Miguel Vela Romera committed Feb 24, 2020
1 parent b0b003b commit 5f6f563
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 20 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@ To do this we need to transform our payment request to an API request:

Now we have an API Request that we can execute using our API Connection:

$apiResponse = $apiConnection->execute($apiRequest);
$requestHeaders = []; // Optional request headers
$apiResponse = $apiConnection->execute($apiRequest, $requestHeaders);

### Handling the responses

Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "payvision/payvision-sdk-php",
"description": "Payvision PHP SDK",
"type": "library",
"version": "4.0.0",
"version": "4.1.0",
"license": "MIT",
"require": {
"php": "^7.0.13|^7.1",
Expand Down
2 changes: 1 addition & 1 deletion src/Application/Payments/Service/Marshaller.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ private function marshall($object, string $targetObject)
return JsonToObject::build($targetObject, $json);
} catch (Exception $exception) {
throw new Exception(
\sprintf('Error while marshalling object: %1', $exception->getMessage())
\sprintf('Error while marshalling object: %s', $exception->getMessage())
);
}
}
Expand Down
70 changes: 53 additions & 17 deletions src/Infrastructure/ApiConnection.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,16 @@ public function __construct(

/**
* @param Request $request
* @param array $requestHeaders
* @return mixed
* @throws ApiException
* @throws BuilderException
* @throws ErrorResponse
*/
public function execute(Request $request)
public function execute(Request $request, array $requestHeaders = [])
{
$this->validateResponseClasses($request);
$jsonResponse = $this->doRequest($request);
$jsonResponse = $this->doRequest($request, $requestHeaders);
return $this->handleResponse($jsonResponse, $request);
}

Expand All @@ -103,14 +104,15 @@ public function executeAndReturnArray(Request $request): array

/**
* @param Request $request
* @param RequestHeaderCollection $requestHeaderCollection
* @return array
* @throws ApiException
*/
private function get(Request $request): array
private function get(Request $request, RequestHeaderCollection $requestHeaderCollection): array
{
$guzzleResponse = $this->client->get(
$request->getUri(),
$this->buildRequestArray($request)
$this->buildRequestArray($request, $requestHeaderCollection)
);

$this->lastJsonRequest = $request->getPathParams();
Expand All @@ -119,7 +121,7 @@ private function get(Request $request): array
$json = \json_decode($contents, true);

if (!\is_array($json)) {
$this->logDebugData($this->lastJsonRequest, ['_raw_response' => $contents]);
$this->logDebugData($this->lastJsonRequest, ['_raw_response' => $contents], $requestHeaderCollection);
throw new ApiException(
\sprintf('Response is not JSON: %1$s', $contents),
ApiException::INVALID_RESPONSE
Expand All @@ -131,16 +133,17 @@ private function get(Request $request): array

/**
* @param Request $request
* @param RequestHeaderCollection $requestHeaderCollection
* @return array
* @throws ApiException
*/
private function post(Request $request): array
private function post(Request $request, RequestHeaderCollection $requestHeaderCollection): array
{
// Build request according to request object
$jsonRequest = $this->prepareJsonRequest($request);
$guzzleResponse = $this->client->post(
$request->getUri(),
$this->buildRequestArray($request, $jsonRequest)
$this->buildRequestArray($request, $requestHeaderCollection, $jsonRequest)
);

$this->lastJsonRequest = $jsonRequest;
Expand All @@ -149,7 +152,7 @@ private function post(Request $request): array
$json = \json_decode($contents, true);

if (!\is_array($json)) {
$this->logDebugData($this->lastJsonRequest, ['_raw_response' => $contents]);
$this->logDebugData($this->lastJsonRequest, ['_raw_response' => $contents], $requestHeaderCollection);
throw new ApiException(
\sprintf('Response is not JSON: %1$s', $contents),
ApiException::INVALID_RESPONSE
Expand All @@ -162,13 +165,23 @@ private function post(Request $request): array
/**
* @param array $jsonRequest
* @param array $jsonResponse
* @param RequestHeaderCollection $requestHeaderCollection
* @return null
*/
private function logDebugData(array $jsonRequest, array $jsonResponse)
{
private function logDebugData(
array $jsonRequest,
array $jsonResponse,
RequestHeaderCollection $requestHeaderCollection
) {
$debugData = \sprintf(
'%1$sRequest:%1$s%2$s%1$sResponse:%1$s%3$s%1$s',
'%1$s%2$sRequest:%1$s%3$s%1$sResponse:%1$s%4$s%1$s',
\PHP_EOL,
\count($requestHeaderCollection) > 0 ?
\sprintf(
'Request headers:%1$s%2$s%1$s',
\PHP_EOL,
\json_encode($requestHeaderCollection->getHeaders(), \JSON_PRETTY_PRINT)
) : '',
\json_encode($jsonRequest, \JSON_PRETTY_PRINT),
\json_encode($jsonResponse, \JSON_PRETTY_PRINT)
);
Expand Down Expand Up @@ -237,17 +250,19 @@ private function handleResponse(

/**
* @param Request $request
* @param array $requestHeaders
* @return array
* @throws ApiException
*/
private function doRequest(Request $request): array
private function doRequest(Request $request, array $requestHeaders = []): array
{
$requestHeaderCollection = $this->buildRequestHeaderCollection($requestHeaders);
switch ($request->getMethod()) {
case Request::METHOD_GET:
$jsonResponse = $this->get($request);
$jsonResponse = $this->get($request, $requestHeaderCollection);
break;
case Request::METHOD_POST:
$jsonResponse = $this->post($request);
$jsonResponse = $this->post($request, $requestHeaderCollection);
break;
default:
throw new ApiException(
Expand All @@ -258,7 +273,7 @@ private function doRequest(Request $request): array
}

if ($this->debug) {
$this->logDebugData($this->lastJsonRequest, $jsonResponse);
$this->logDebugData($this->lastJsonRequest, $jsonResponse, $requestHeaderCollection);
}

return $jsonResponse;
Expand Down Expand Up @@ -287,19 +302,40 @@ private function prepareJsonRequest(Request $request): array

/**
* @param Request $request
* @param RequestHeaderCollection $requestHeaderCollection
* @param array $jsonRequest
* @return array
*/
private function buildRequestArray(Request $request, array $jsonRequest = null): array
{
private function buildRequestArray(
Request $request,
RequestHeaderCollection $requestHeaderCollection,
array $jsonRequest = null
): array {
$returnValue = [
'query' => $request->getPathParams(),
];

if (\count($requestHeaderCollection) > 0) {
$returnValue['headers'] = $requestHeaderCollection->getHeaders();
}

if ($jsonRequest !== null) {
$returnValue['json'] = $jsonRequest;
}

return $returnValue;
}

/**
* @param string[],array<string> $headers
* @return RequestHeaderCollection
*/
private function buildRequestHeaderCollection(array $headers): RequestHeaderCollection
{
$requestHeader = new RequestHeaderCollection();
foreach ($headers as $key => $value) {
$requestHeader->add($key, $value);
}
return $requestHeader;
}
}
55 changes: 55 additions & 0 deletions src/Infrastructure/RequestHeaderCollection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

declare(strict_types=1);

namespace Payvision\SDK\Infrastructure;

use ArrayIterator;
use Countable;
use IteratorAggregate;
use Traversable;

class RequestHeaderCollection implements IteratorAggregate, Countable
{
const HEADER_EXECUTION_MODE = 'X-AH-ExecutionMode';

/**
* @var string[],array<string>
*/
protected $headers = [];

/**
* @param string $header
* @param string $value
* @return $this
*/
public function add(string $header, string $value): self
{
$this->headers[$header] = $value;
return $this;
}

/**
* @return ArrayIterator|Traversable
*/
public function getIterator()
{
return new ArrayIterator($this->headers);
}

/**
* @return array
*/
public function getHeaders(): array
{
return $this->headers;
}

/**
* @return int
*/
public function count(): int
{
return \count($this->headers);
}
}
37 changes: 37 additions & 0 deletions tests/Test/Unit/Infrastructure/RequestHeaderCollectionTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

/**
* @copyright Copyright (c) 2018-2019 Payvision B.V. (https://www.payvision.com/)
* @license proprietary
*/

namespace Payvision\SDK\Test\Unit\Infrastructure;

use Payvision\SDK\Infrastructure\RequestHeaderCollection;
use PHPUnit\Framework\TestCase;

class RequestHeaderCollectionTest extends TestCase
{
/**
* @return null
*/
public function testAddRequestHeaderCollectionSuccessfully()
{
$requestHeaders = new RequestHeaderCollection();
$this->assertEquals(0, $requestHeaders->count());

$requestHeaders->add(RequestHeaderCollection::HEADER_EXECUTION_MODE, 'test');
$this->assertEquals(1, $requestHeaders->count());

foreach ($requestHeaders as $key => $value) {
$this->assertEquals(RequestHeaderCollection::HEADER_EXECUTION_MODE, $key);
$this->assertEquals('test', $value);
}

$headers = $requestHeaders->getHeaders();
$this->assertArrayHasKey(RequestHeaderCollection::HEADER_EXECUTION_MODE, $headers);
$this->assertEquals($headers[RequestHeaderCollection::HEADER_EXECUTION_MODE], 'test');
}
}

0 comments on commit 5f6f563

Please sign in to comment.