Fix Spectre, first code to create customer.

This commit is contained in:
James Cole
2017-12-19 05:20:37 +01:00
parent 79f700c622
commit 34fc9bc50a
12 changed files with 384 additions and 140 deletions

View File

@@ -0,0 +1,90 @@
<?php
/**
* Customer.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Services\Spectre\Object;
/**
* Class Customer
*/
class Customer extends SpectreObject
{
/** @var int */
private $id;
/** @var string */
private $identifier;
/** @var string */
private $secret;
/**
* @return int
*/
public function getId(): int
{
return $this->id;
}
/**
* @param int $id
*/
public function setId(int $id): void
{
$this->id = $id;
}
/**
* @return string
*/
public function getIdentifier(): string
{
return $this->identifier;
}
/**
* @param string $identifier
*/
public function setIdentifier(string $identifier): void
{
$this->identifier = $identifier;
}
/**
* @return string
*/
public function getSecret(): string
{
return $this->secret;
}
/**
* @param string $secret
*/
public function setSecret(string $secret): void
{
$this->secret = $secret;
}
}

View File

@@ -0,0 +1,32 @@
<?php
/**
* SpectreObject.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Services\Spectre\Object;
/**
* Class SpectreObject
*/
class SpectreObject
{
}

View File

@@ -0,0 +1,63 @@
<?php
/**
* NewCustomerRequest.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Services\Spectre\Request;
/**
* Class NewCustomerRequest
*/
class NewCustomerRequest extends SpectreRequest
{
/** @var array */
protected $customer = [];
/**
*
* @throws \FireflyIII\Exceptions\FireflyException
*/
public function call(): void
{
$data = [
'data' => [
'identifier' => 'default_ff3_customer',
],
];
$uri = '/api/v3/customers/';
$response = $this->sendSignedSpectrePost($uri, $data);
// create customer:
$this->customer = $response['data'];
return;
}
/**
* @return array
*/
public function getCustomer(): array
{
return $this->customer;
}
}

View File

@@ -28,6 +28,7 @@ use FireflyIII\User;
use Log;
use Requests;
use Requests_Exception;
use Requests_Response;
//use FireflyIII\Services\Bunq\Object\ServerPublicKey;
@@ -37,7 +38,7 @@ use Requests_Exception;
abstract class SpectreRequest
{
/** @var string */
protected $clientId = '';
protected $clientId = '';
/**
* @var int
*/
@@ -174,7 +175,7 @@ abstract class SpectreRequest
// base64(sha1_signature(private_key, "Expires-at|request_method|original_url|post_body|md5_of_uploaded_file|")))
// Prepare the signature
$toSign = $this->expiresAt . '|' . strtoupper($method) . '|' . $uri . '|' . $data . ''; // no file so no content there.
Log::debug(sprintf('String to sign: %s', $toSign));
Log::debug(sprintf('String to sign: "%s"', $toSign));
$signature = '';
// Sign the data
@@ -202,92 +203,12 @@ abstract class SpectreRequest
];
}
/**
* @param string $uri
* @param array $headers
*
* @return array
*
* @throws Exception
*/
protected function sendSignedBunqDelete(string $uri, array $headers): array
{
if (0 === strlen($this->server)) {
throw new FireflyException('No bunq server defined');
}
$fullUri = $this->server . $uri;
$signature = $this->generateSignature('delete', $uri, $headers, '');
$headers['X-Bunq-Client-Signature'] = $signature;
try {
$response = Requests::delete($fullUri, $headers);
} catch (Requests_Exception $e) {
return ['Error' => [0 => ['error_description' => $e->getMessage(), 'error_description_translated' => $e->getMessage()]]];
}
$body = $response->body;
$array = json_decode($body, true);
$responseHeaders = $response->headers->getAll();
$statusCode = intval($response->status_code);
$array['ResponseHeaders'] = $responseHeaders;
$array['ResponseStatusCode'] = $statusCode;
Log::debug(sprintf('Response to DELETE %s is %s', $fullUri, $body));
if ($this->isErrorResponse($array)) {
$this->throwResponseError($array);
}
if (!$this->verifyServerSignature($body, $responseHeaders, $statusCode)) {
throw new FireflyException(sprintf('Could not verify signature for request to "%s"', $uri));
}
return $array;
}
/**
* @param string $uri
* @param array $data
* @param array $headers
*
* @return array
*
* @throws Exception
*/
protected function sendSignedBunqPost(string $uri, array $data, array $headers): array
{
$body = json_encode($data);
$fullUri = $this->server . $uri;
$signature = $this->generateSignature('post', $uri, $headers, $body);
$headers['X-Bunq-Client-Signature'] = $signature;
try {
$response = Requests::post($fullUri, $headers, $body);
} catch (Requests_Exception $e) {
return ['Error' => [0 => ['error_description' => $e->getMessage(), 'error_description_translated' => $e->getMessage()]]];
}
$body = $response->body;
$array = json_decode($body, true);
$responseHeaders = $response->headers->getAll();
$statusCode = intval($response->status_code);
$array['ResponseHeaders'] = $responseHeaders;
$array['ResponseStatusCode'] = $statusCode;
if ($this->isErrorResponse($array)) {
$this->throwResponseError($array);
}
if (!$this->verifyServerSignature($body, $responseHeaders, $statusCode)) {
throw new FireflyException(sprintf('Could not verify signature for request to "%s"', $uri));
}
return $array;
}
/**
* @param string $uri
* @param array $data
* @return array
*
* @throws FireflyException
*/
protected function sendSignedSpectreGet(string $uri, array $data): array
@@ -308,11 +229,9 @@ abstract class SpectreRequest
} catch (Requests_Exception $e) {
throw new FireflyException(sprintf('Request Exception: %s', $e->getMessage()));
}
$this->detectError($response);
$statusCode = intval($response->status_code);
if ($statusCode !== 200) {
throw new FireflyException(sprintf('Status code %d: %s', $statusCode, $response->body));
}
$body = $response->body;
$array = json_decode($body, true);
@@ -320,32 +239,9 @@ abstract class SpectreRequest
$array['ResponseHeaders'] = $responseHeaders;
$array['ResponseStatusCode'] = $statusCode;
return $array;
}
/**
* @param string $uri
* @param array $headers
*
* @return array
*/
protected function sendUnsignedBunqDelete(string $uri, array $headers): array
{
$fullUri = $this->server . $uri;
try {
$response = Requests::delete($fullUri, $headers);
} catch (Requests_Exception $e) {
return ['Error' => [0 => ['error_description' => $e->getMessage(), 'error_description_translated' => $e->getMessage()]]];
}
$body = $response->body;
$array = json_decode($body, true);
$responseHeaders = $response->headers->getAll();
$statusCode = $response->status_code;
$array['ResponseHeaders'] = $responseHeaders;
$array['ResponseStatusCode'] = $statusCode;
if ($this->isErrorResponse($array)) {
$this->throwResponseError($array);
if (isset($array['error_class'])) {
$message = $array['error_message'] ?? '(no message)';
throw new FireflyException(sprintf('Error of class %s: %s', $array['error_class'], $message));
}
return $array;
@@ -354,30 +250,59 @@ abstract class SpectreRequest
/**
* @param string $uri
* @param array $data
* @param array $headers
*
* @return array
*
* @throws FireflyException
*/
protected function sendUnsignedBunqPost(string $uri, array $data, array $headers): array
protected function sendSignedSpectrePost(string $uri, array $data): array
{
$body = json_encode($data);
$fullUri = $this->server . $uri;
try {
$response = Requests::post($fullUri, $headers, $body);
} catch (Requests_Exception $e) {
return ['Error' => [0 => ['error_description' => $e->getMessage(), 'error_description_translated' => $e->getMessage()]]];
if (0 === strlen($this->server)) {
throw new FireflyException('No Spectre server defined');
}
$headers = $this->getDefaultHeaders();
$body = json_encode($data);
$fullUri = $this->server . $uri;
$signature = $this->generateSignature('post', $fullUri, $body);
$headers['Signature'] = $signature;
Log::debug('Final headers for spectre signed POST request:', $headers);
try {
$response = Requests::get($fullUri, $headers);
} catch (Requests_Exception $e) {
throw new FireflyException(sprintf('Request Exception: %s', $e->getMessage()));
}
$this->detectError($response);
$body = $response->body;
$array = json_decode($body, true);
$responseHeaders = $response->headers->getAll();
$statusCode = $response->status_code;
$array['ResponseHeaders'] = $responseHeaders;
$array['ResponseStatusCode'] = $statusCode;
if ($this->isErrorResponse($array)) {
$this->throwResponseError($array);
}
$array['ResponseStatusCode'] = $response->status_code;
return $array;
}
/**
* @param Requests_Response $response
*
* @throws FireflyException
*/
private function detectError(Requests_Response $response): void
{
$body = $response->body;
$array = json_decode($body, true);
if (isset($array['error_class'])) {
$message = $array['error_message'] ?? '(no message)';
throw new FireflyException(sprintf('Error of class %s: %s', $array['error_class'], $message));
}
$statusCode = intval($response->status_code);
if ($statusCode !== 200) {
throw new FireflyException(sprintf('Status code %d: %s', $statusCode, $response->body));
}
return;
}
}