diff --git a/app/Http/Controllers/Import/PrerequisitesController.php b/app/Http/Controllers/Import/PrerequisitesController.php index 256d94e828..e7b46c4f7d 100644 --- a/app/Http/Controllers/Import/PrerequisitesController.php +++ b/app/Http/Controllers/Import/PrerequisitesController.php @@ -85,10 +85,10 @@ class PrerequisitesController extends Controller * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector * @throws FireflyException */ - public function postPrerequisites(Request $request, string $bank) + public function post(Request $request, string $bank) { Log::debug(sprintf('Now in postPrerequisites for %s', $bank)); - $class = config(sprintf('firefly.import_pre.%s', $bank)); + $class = strval(config(sprintf('import.prerequisites.%s', $bank))); if (!class_exists($class)) { throw new FireflyException(sprintf('Cannot find class %s', $class)); } diff --git a/app/Import/Prerequisites/SpectrePrerequisites.php b/app/Import/Prerequisites/SpectrePrerequisites.php index cf03ba0048..f9a1102def 100644 --- a/app/Import/Prerequisites/SpectrePrerequisites.php +++ b/app/Import/Prerequisites/SpectrePrerequisites.php @@ -56,7 +56,7 @@ class SpectrePrerequisites implements PrerequisitesInterface public function getViewParameters(): array { $publicKey = $this->getPublicKey(); - $subTitle = strval(trans('bank.spectre_title')); + $subTitle = strval(trans('import.spectre_title')); $subTitleIcon = 'fa-archive'; return compact('publicKey', 'subTitle', 'subTitleIcon'); diff --git a/app/Import/Routine/SpectreRoutine.php b/app/Import/Routine/SpectreRoutine.php new file mode 100644 index 0000000000..5306237cc3 --- /dev/null +++ b/app/Import/Routine/SpectreRoutine.php @@ -0,0 +1,133 @@ +. + */ +declare(strict_types=1); + +namespace FireflyIII\Import\Routine; + +use FireflyIII\Models\ImportJob; +use FireflyIII\Services\Spectre\Object\Customer; +use FireflyIII\Services\Spectre\Request\NewCustomerRequest; +use Preferences; +use Illuminate\Support\Collection; +use Log; + +/** + * Class FileRoutine + */ +class SpectreRoutine implements RoutineInterface +{ + /** @var Collection */ + public $errors; + /** @var Collection */ + public $journals; + /** @var int */ + public $lines = 0; + /** @var ImportJob */ + private $job; + + /** + * ImportRoutine constructor. + */ + public function __construct() + { + $this->journals = new Collection; + $this->errors = new Collection; + } + + /** + * @return Collection + */ + public function getErrors(): Collection + { + return $this->errors; + } + + /** + * @return Collection + */ + public function getJournals(): Collection + { + return $this->journals; + } + + /** + * @return int + */ + public function getLines(): int + { + return $this->lines; + } + + /** + * + */ + public function run(): bool + { + if ('configured' !== $this->job->status) { + Log::error(sprintf('Job %s is in state "%s" so it cannot be started.', $this->job->key, $this->job->status)); + + return false; + } + set_time_limit(0); + Log::info(sprintf('Start with import job %s using Spectre.', $this->job->key)); + // create customer if user does not have one: + $customer = $this->getCustomer(); + + + return true; + } + + /** + * @param ImportJob $job + */ + public function setJob(ImportJob $job) + { + $this->job = $job; + } + + /** + * @return Customer + */ + protected function createCustomer(): Customer + { + $newCustomerRequest = new NewCustomerRequest($this->job->user); + $newCustomerRequest->call(); + echo '
';
+ print_r($newCustomerRequest->getCustomer());
+ exit;
+
+ }
+
+ /**
+ * @return Customer
+ */
+ protected function getCustomer(): Customer
+ {
+ $preference = Preferences::getForUser($this->job->user, 'spectre_customer', null);
+ if (is_null($preference)) {
+ return $this->createCustomer();
+ }
+ var_dump($preference->data);
+ exit;
+ }
+
+
+}
diff --git a/app/Services/Spectre/Object/Customer.php b/app/Services/Spectre/Object/Customer.php
new file mode 100644
index 0000000000..21f2f2f0f2
--- /dev/null
+++ b/app/Services/Spectre/Object/Customer.php
@@ -0,0 +1,90 @@
+.
+ */
+
+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;
+ }
+
+
+
+
+
+}
\ No newline at end of file
diff --git a/app/Services/Spectre/Object/SpectreObject.php b/app/Services/Spectre/Object/SpectreObject.php
new file mode 100644
index 0000000000..e41db10601
--- /dev/null
+++ b/app/Services/Spectre/Object/SpectreObject.php
@@ -0,0 +1,32 @@
+.
+ */
+
+declare(strict_types=1);
+
+namespace FireflyIII\Services\Spectre\Object;
+
+/**
+ * Class SpectreObject
+ */
+class SpectreObject
+{
+
+}
\ No newline at end of file
diff --git a/app/Services/Spectre/Request/NewCustomerRequest.php b/app/Services/Spectre/Request/NewCustomerRequest.php
new file mode 100644
index 0000000000..93cbef13c7
--- /dev/null
+++ b/app/Services/Spectre/Request/NewCustomerRequest.php
@@ -0,0 +1,63 @@
+.
+ */
+
+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;
+ }
+
+
+}
\ No newline at end of file
diff --git a/app/Services/Spectre/Request/SpectreRequest.php b/app/Services/Spectre/Request/SpectreRequest.php
index eaaa284694..c93e77c036 100644
--- a/app/Services/Spectre/Request/SpectreRequest.php
+++ b/app/Services/Spectre/Request/SpectreRequest.php
@@ -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;
+ }
}
diff --git a/resources/lang/en_US/form.php b/resources/lang/en_US/form.php
index 6b7076a00c..84f57f87fc 100644
--- a/resources/lang/en_US/form.php
+++ b/resources/lang/en_US/form.php
@@ -200,6 +200,7 @@ return [
'app_secret' => 'App secret',
'public_key' => 'Public key',
'country_code' => 'Country code',
+ 'provider_code' => 'Bank or data-provider',
'due_date' => 'Due date',
diff --git a/resources/views/import/spectre/input-fields.twig b/resources/views/import/spectre/input-fields.twig
index 03aae3faf2..93c21d595d 100644
--- a/resources/views/import/spectre/input-fields.twig
+++ b/resources/views/import/spectre/input-fields.twig
@@ -10,18 +10,18 @@
- {{ trans('bank.spectre_input_fields_title') }}
+ {{ trans('import.spectre_input_fields_title') }}
- {{ trans('bank.spectre_input_fields_text',{provider: data.provider.data.name, country: data.country})|raw }}
+ {{ trans('import.spectre_input_fields_text',{provider: data.provider.data.name, country: data.country})|raw }}
- {{ trans('bank.spectre_instructions_english') }}
+ {{ trans('import.spectre_instructions_english') }}
-
+
{{ data.provider.data.instruction|nl2br }}
diff --git a/resources/views/import/spectre/prerequisites.twig b/resources/views/import/spectre/prerequisites.twig
index 1b225e6a12..c521d532f0 100644
--- a/resources/views/import/spectre/prerequisites.twig
+++ b/resources/views/import/spectre/prerequisites.twig
@@ -5,18 +5,18 @@
{% endblock %}
{% block content %}
-