Skip to content

Commit

Permalink
Merge pull request #14 from DarkSide666/master
Browse files Browse the repository at this point in the history
Creating test user service; Add fraud prevention headers
  • Loading branch information
s-patompong authored Apr 7, 2019
2 parents eed6426 + ec2ab99 commit 233ca3d
Show file tree
Hide file tree
Showing 12 changed files with 294 additions and 12 deletions.
24 changes: 24 additions & 0 deletions src/HMRC/Environment/Environment.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ class Environment
/** @var string */
private $env;

/** @var array of request headers which will be added in all requests in this environment */
private $requestHeaders = [];

private function __construct()
{
$this->env = self::SANDBOX;
Expand Down Expand Up @@ -73,6 +76,27 @@ public function setToLive()
$this->env = self::LIVE;
}

/**
* Sets Request headers which will be included in all Requests.
* This can be nicely used to include fraud prevention headers, for example.
*
* @param array $headers
*/
public function setDefaultRequestHeaders(array $headers)
{
$this->requestHeaders = $headers;
}

/**
* Returns default request headers.
*
* @return array
*/
public function getDefaultRequestHeaders(): array
{
return $this->requestHeaders;
}

/**
* @param string $env
*
Expand Down
9 changes: 5 additions & 4 deletions src/HMRC/Oauth2/Provider.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace HMRC\Oauth2;

use HMRC\Environment\Environment;
use HMRC\Request\RequestURL;
use League\OAuth2\Client\Provider\GenericProvider;

class Provider extends GenericProvider
Expand Down Expand Up @@ -38,12 +39,12 @@ protected function getScopeSeparator()

private function optionFromEnvironments(): array
{
$subDomain = Environment::getInstance()->isLive() ? 'api' : 'test-api';
$host = Environment::getInstance()->isLive() ? RequestURL::LIVE : RequestURL::SANDBOX;

return [
'urlAuthorize' => "https://{$subDomain}.service.hmrc.gov.uk/oauth/authorize",
'urlAccessToken' => "https://{$subDomain}.service.hmrc.gov.uk/oauth/token",
'urlResourceOwnerDetails' => "https://{$subDomain}.service.hmrc.gov.uk/oauth/resource",
'urlAuthorize' => "{$host}/oauth/authorize",
'urlAccessToken' => "{$host}/oauth/token",
'urlResourceOwnerDetails' => "{$host}/oauth/resource",
];
}

Expand Down
31 changes: 28 additions & 3 deletions src/HMRC/Request/Request.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ abstract class Request
/** @var string Content type of the request */
protected $contentType = 'json';

/**
* Array of additional headers to add in each request.
*
* @var array
*/
protected $headers = [];

public function __construct()
{
$this->client = new Client();
Expand Down Expand Up @@ -60,9 +67,16 @@ protected function getAuthorizationHeader(string $token): string

protected function getHeaders(): array
{
return [
RequestHeader::ACCEPT => $this->getAcceptHeader(),
];
return array_merge(
// headers set in environment
Environment::getInstance()->getDefaultRequestHeaders(),
// headers set for this request
$this->headers,
// and more
[
RequestHeader::ACCEPT => $this->getAcceptHeader(),
]
);
}

protected function getURI(): string
Expand Down Expand Up @@ -131,6 +145,17 @@ public function setClient(Client $client): self
return $this;
}

/**
* Adds additional header or array of headers.
*
* @param string|array $key
* @param string $value
*/
public function addHeader($key, $value = null)
{
$this->headers = array_merge($this->headers, is_array($key) ? $key : [$key => $value]);
}

abstract protected function getMethod(): string;

abstract protected function getApiPath(): string;
Expand Down
60 changes: 60 additions & 0 deletions src/HMRC/Request/RequestHeader.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,64 @@ abstract class RequestHeader

/** @var string authorization header for request */
public const AUTHORIZATION = 'Authorization';

// Fraud prevention headers below
// https://developer.service.hmrc.gov.uk/api-documentation/docs/fraud-prevention

/** @var string A string representing the connection method used for the request. */
public const GOV_CLIENT_CONNECTION_METHOD = 'Gov-Client-Connection-Method';

/** @var string The public IP address (IPv4 or IPv6) from which the originating device makes the request. */
public const GOV_CLIENT_PUBLIC_IP = 'Gov-Client-Public-IP';

/** @var string The public TCP port that the originating device uses when initiating the request. */
public const GOV_CLIENT_PUBLIC_PORT = 'Gov-Client-Public-Port';

/** @var string An identifier unique to an originating device. This should be generated by an application and persistently stored on the device. */
public const GOV_CLIENT_DEVICE_ID = 'Gov-Client-Device-ID';

/** @var string A key-value data structure containing the user identifiers. The keys should indicate accounts the user holds. */
public const GOV_CLIENT_USER_IDS = 'Gov-Client-User-IDs';

/** @var string The local timezone of the originating device, expressed as UTC±<hh>:<mm>. */
public const GOV_CLIENT_TIMEZONE = 'Gov-Client-Timezone';

/** @var string A list of all local IP addresses (IPv4 and IPv6) available to the originating device. */
public const GOV_CLIENT_LOCAL_IPS = 'Gov-Client-Local-IPs';

/** @var string Information related to the originating device’s screens */
public const GOV_CLIENT_SCREENS = 'Gov-Client-Screens';

/** @var string The number of pixels of the window on the originating device in which the user initiated (directly or indirectly) the API call to HMRC. */
public const GOV_CLIENT_WINDOW_SIZE = 'Gov-Client-Window-Size';

/** @var string An attempt to identify the operating system family, version, device manufacturer and model of the originating device. */
public const GOV_CLIENT_USER_AGENT = 'Gov-Client-User-Agent';

/** @var string A list of browser plugins on the originating device. */
public const GOV_CLIENT_BROWSER_PLUGINS = 'Gov-Client-Browser-Plugins';

/** @var string JavaScript-reported user agent string from the originating device. */
public const GOV_CLIENT_BROWSER_JS_USER_AGENT = 'Gov-Client-Browser-JS-User-Agent';

/** @var string Whether the Do Not Track option is enabled on the browser. */
public const GOV_CLIENT_BROWSER_DO_NOT_TRACK = 'Gov-Client-Browser-Do-Not-Track';

/** @var string A list of key-value data structures containing details of the multi-factor authentication (MFA) statuses related to the API call */
public const GOV_CLIENT_MULTI_FACTOR = 'Gov-Client-Multi-Factor';

/** @var string A key-value data structure of software versions involved in handling a request */
public const GOV_VENDOR_VERSION = 'Gov-Vendor-Version';

/** @var string A key-value data structure of hashed license keys relating to the vendor software initiating the API request on the originating device. */
public const GOV_VENDOR_LICENSE_IDS = 'Gov-Vendor-License-IDs';

/** @var string The public IP address of the servers to which the originating device sent their requests. */
public const GOV_VENDOR_PUBLIC_IP = 'Gov-Vendor-Public-IP';

/** @var string The list of MAC addresses available on the originating device. */
public const GOV_CLIENT_MAC_ADDRESSES = 'Gov-Client-MAC-Addresses';

/** @var string A list that details hops over the internet between services that terminate TLS. */
public const GOV_VENDOR_FORWARDED = 'Gov-Vendor-Forwarded';
}
26 changes: 26 additions & 0 deletions src/HMRC/Request/RequestHeaderValue.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,30 @@ abstract class RequestHeaderValue
{
/** @var string header value application/json */
public const APPLICATION_JSON = 'application/json';

// header values for GOV_CLIENT_CONNECTION_METHOD header

/** @var string Installed mobile application connecting directly to HMRC */
public const MOBILE_APP_DIRECT = 'MOBILE_APP_DIRECT';

/** @var string Installed desktop application connecting directly to HMRC */
public const DESKTOP_APP_DIRECT = 'DESKTOP_APP_DIRECT';

/** @var string Installed mobile application connecting through intermediary servers to HMRC */
public const MOBILE_APP_VIA_SERVER = 'MOBILE_APP_VIA_SERVER';

/** @var string Installed desktop application connecting through intermediary servers to HMRC */
public const DESKTOP_APP_VIA_SERVER = 'DESKTOP_APP_VIA_SERVER';

/** @var string Web application connecting through intermediary servers to HMRC */
public const WEB_APP_VIA_SERVER = 'WEB_APP_VIA_SERVER';

/** @var string Batch process connecting directly to HMRC */
public const BATCH_PROCESS_DIRECT = 'BATCH_PROCESS_DIRECT';

/** @var string The application connects directly to HMRC but the method does not fit into the architectures described above. */
public const OTHER_DIRECT = 'OTHER_DIRECT';

/** @var string The application connects through intermediary servers to HMRC but the method does not fit into the architectures described above. */
public const OTHER_VIA_SERVER = 'OTHER_VIA_SERVER';
}
4 changes: 2 additions & 2 deletions src/HMRC/Request/RequestWithAccessToken.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ public function fire()

protected function getHeaders(): array
{
return array_merge([
return array_merge(parent::getHeaders(), [
RequestHeader::AUTHORIZATION => $this->getAuthorizationHeader($this->accessToken),
], parent::getHeaders());
]);
}
}
5 changes: 2 additions & 3 deletions src/HMRC/Request/RequestWithServerToken.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,9 @@ public function fire()

protected function getHeaders(): array
{
return [
RequestHeader::ACCEPT => $this->getAcceptHeader(),
return array_merge(parent::getHeaders(), [
RequestHeader::AUTHORIZATION => $this->getAuthorizationHeader(ServerToken::getInstance()->get()),
];
]);
}

/**
Expand Down
54 changes: 54 additions & 0 deletions src/HMRC/TestUser/AbstractRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

namespace HMRC\TestUser;

use HMRC\Request\RequestHeader;
use HMRC\Request\RequestHeaderValue;
use HMRC\Request\RequestMethod;
use HMRC\Request\RequestWithServerToken;

abstract class AbstractRequest extends RequestWithServerToken
{
/** @var PostBody */
protected $postBody;

public function __construct(PostBody $postBody)
{
parent::__construct();

$this->postBody = $postBody;
}

protected function getMethod(): string
{
return RequestMethod::POST;
}

protected function getHeaders(): array
{
return array_merge(parent::getHeaders(), [
RequestHeader::CONTENT_TYPE => RequestHeaderValue::APPLICATION_JSON,
]);
}

/**
* @throws \GuzzleHttp\Exception\GuzzleException
* @throws \HMRC\Exceptions\InvalidPostBodyException
* @throws \HMRC\Exceptions\MissingAccessTokenException
*
* @return mixed|Response
*/
public function fire()
{
$this->postBody->validate();

return parent::fire();
}

protected function getHTTPClientOptions(): array
{
return array_merge([
'json' => $this->postBody->toArray(),
], parent::getHTTPClientOptions());
}
}
11 changes: 11 additions & 0 deletions src/HMRC/TestUser/CreateAgentRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace HMRC\TestUser;

class CreateAgentRequest extends AbstractRequest
{
protected function getApiPath(): string
{
return '/create-test-user/agents';
}
}
11 changes: 11 additions & 0 deletions src/HMRC/TestUser/CreateIndividualRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace HMRC\TestUser;

class CreateIndividualRequest extends AbstractRequest
{
protected function getApiPath(): string
{
return '/create-test-user/individuals';
}
}
11 changes: 11 additions & 0 deletions src/HMRC/TestUser/CreateOrganisationRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace HMRC\TestUser;

class CreateOrganisationRequest extends AbstractRequest
{
protected function getApiPath(): string
{
return '/create-test-user/organisations';
}
}
60 changes: 60 additions & 0 deletions src/HMRC/TestUser/PostBody.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

namespace HMRC\TestUser;

use HMRC\Exceptions\InvalidPostBodyException;

class PostBody implements \HMRC\Request\PostBody
{
/** @var array */
private $serviceNames;

/**
* Validate the post body, it should throw an Exception if something is wrong.
*
* @throws InvalidPostBodyException
*/
public function validate()
{
$requiredFields = [
'serviceNames',
];

$emptyFields = [];
foreach ($requiredFields as $requiredField) {
if (is_null($this->{$requiredField})) {
$emptyFields[] = $requiredField;
}
}

if (count($emptyFields) > 0) {
$emptyFieldsString = implode(', ', $emptyFields);

throw new InvalidPostBodyException("Missing post body fields ({$emptyFieldsString}).");
}
}

/**
* Return post body as an array to be used to call.
*
* @return array
*/
public function toArray(): array
{
return [
'serviceNames' => $this->serviceNames,
];
}

/**
* @param array $serviceNames
*
* @return $this
*/
public function setServiceNames(array $serviceNames): self
{
$this->serviceNames = $serviceNames;

return $this;
}
}

0 comments on commit 233ca3d

Please sign in to comment.