mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-09 06:55:43 -06:00
Bunq code.
This commit is contained in:
parent
4b46a3d298
commit
93068659e5
43
app/Services/Bunq/Id/BunqId.php
Normal file
43
app/Services/Bunq/Id/BunqId.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* BunqId.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Services\Bunq\Id;
|
||||
|
||||
/**
|
||||
* Class BunqId
|
||||
*
|
||||
* @package FireflyIII\Services\Bunq\Id
|
||||
*/
|
||||
class BunqId
|
||||
{
|
||||
/** @var int */
|
||||
private $id = 0;
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getId(): int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
*/
|
||||
public function setId(int $id)
|
||||
{
|
||||
$this->id = $id;
|
||||
}
|
||||
|
||||
|
||||
}
|
25
app/Services/Bunq/Id/DeviceServerId.php
Normal file
25
app/Services/Bunq/Id/DeviceServerId.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* DeviceServerId.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Services\Bunq\Id;
|
||||
|
||||
|
||||
/**
|
||||
* Class DeviceServerId
|
||||
*
|
||||
* @package Bunq\Id
|
||||
*/
|
||||
class DeviceServerId extends BunqId
|
||||
{
|
||||
|
||||
}
|
24
app/Services/Bunq/Id/DeviceSessionId.php
Normal file
24
app/Services/Bunq/Id/DeviceSessionId.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
/**
|
||||
* DeviceSessionId.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Services\Bunq\Id;
|
||||
|
||||
|
||||
/**
|
||||
* Class DeviceSessionId
|
||||
*
|
||||
* @package Bunq\Id
|
||||
*/
|
||||
class DeviceSessionId extends BunqId
|
||||
{
|
||||
|
||||
}
|
24
app/Services/Bunq/Id/InstallationId.php
Normal file
24
app/Services/Bunq/Id/InstallationId.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
/**
|
||||
* InstallationId.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Services\Bunq\Id;
|
||||
|
||||
|
||||
/**
|
||||
* Class InstallationId
|
||||
*
|
||||
* @package Bunq\Id
|
||||
*/
|
||||
class InstallationId extends BunqId
|
||||
{
|
||||
|
||||
}
|
23
app/Services/Bunq/Object/BunqObject.php
Normal file
23
app/Services/Bunq/Object/BunqObject.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* BunqObject.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Services\Bunq\Object;
|
||||
|
||||
/**
|
||||
* Class BunqObject
|
||||
*
|
||||
* @package FireflyIII\Services\Bunq\Object
|
||||
*/
|
||||
class BunqObject
|
||||
{
|
||||
|
||||
}
|
51
app/Services/Bunq/Object/ServerPublicKey.php
Normal file
51
app/Services/Bunq/Object/ServerPublicKey.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
/**
|
||||
* ServerPublicKey.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Services\Bunq\Object;
|
||||
|
||||
/**
|
||||
* Class ServerPublicKey
|
||||
*
|
||||
* @package Bunq\Object
|
||||
*/
|
||||
class ServerPublicKey extends BunqObject
|
||||
{
|
||||
/** @var string */
|
||||
private $publicKey = '';
|
||||
|
||||
/**
|
||||
* ServerPublicKey constructor.
|
||||
*
|
||||
* @param array $response
|
||||
*/
|
||||
public function __construct(array $response) {
|
||||
$this->publicKey = $response['server_public_key'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $publicKey
|
||||
*/
|
||||
public function setPublicKey(string $publicKey)
|
||||
{
|
||||
$this->publicKey = $publicKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getPublicKey(): string
|
||||
{
|
||||
return $this->publicKey;
|
||||
}
|
||||
|
||||
|
||||
}
|
134
app/Services/Bunq/Object/UserPerson.php
Normal file
134
app/Services/Bunq/Object/UserPerson.php
Normal file
@ -0,0 +1,134 @@
|
||||
<?php
|
||||
/**
|
||||
* UserPerson.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Services\Bunq\Object;
|
||||
|
||||
use Carbon\Carbon;
|
||||
|
||||
/**
|
||||
* Class UserPerson
|
||||
*
|
||||
* @package Bunq\Object
|
||||
*/
|
||||
class UserPerson extends BunqObject
|
||||
{
|
||||
private $addressMain;
|
||||
private $addressPostal;
|
||||
/** @var array */
|
||||
private $aliases = [];
|
||||
private $avatar;
|
||||
/** @var array */
|
||||
private $billingContracts = [];
|
||||
/** @var string */
|
||||
private $countryOfBirth = '';
|
||||
/** @var Carbon */
|
||||
private $created;
|
||||
private $customer;
|
||||
private $customerLimit;
|
||||
private $dailyLimit;
|
||||
/** @var Carbon */
|
||||
private $dateOfBirth;
|
||||
/** @var string */
|
||||
private $displayName = '';
|
||||
/** @var string */
|
||||
private $documentCountry = '';
|
||||
/** @var string */
|
||||
private $documentNumber = '';
|
||||
/** @var string */
|
||||
private $documentType = '';
|
||||
/** @var string */
|
||||
private $firstName = '';
|
||||
/** @var string */
|
||||
private $gender = '';
|
||||
/** @var int */
|
||||
private $id = 0;
|
||||
/** @var string */
|
||||
private $language = '';
|
||||
/** @var string */
|
||||
private $lastName = '';
|
||||
/** @var string */
|
||||
private $legalName = '';
|
||||
/** @var string */
|
||||
private $middleName = '';
|
||||
/** @var string */
|
||||
private $nationality = '';
|
||||
/** @var array */
|
||||
private $notificationFilters = [];
|
||||
/** @var string */
|
||||
private $placeOfBirth = '';
|
||||
/** @var string */
|
||||
private $publicNickName = '';
|
||||
/** @var string */
|
||||
private $publicUuid = '';
|
||||
private $region;
|
||||
/** @var int */
|
||||
private $sessionTimeout = 0;
|
||||
/** @var string */
|
||||
private $status = '';
|
||||
/** @var string */
|
||||
private $subStatus = '';
|
||||
/** @var string */
|
||||
private $taxResident = '';
|
||||
/** @var Carbon */
|
||||
private $updated;
|
||||
/** @var int */
|
||||
private $versionTos = 0;
|
||||
|
||||
/**
|
||||
* UserPerson constructor.
|
||||
*
|
||||
* @param array $data
|
||||
*/
|
||||
public function __construct(array $data)
|
||||
{
|
||||
$this->id = intval($data['id']);
|
||||
$this->created = Carbon::createFromFormat('Y-m-d H:i:s.u', $data['created']);
|
||||
$this->updated = Carbon::createFromFormat('Y-m-d H:i:s.u', $data['updated']);
|
||||
$this->status = $data['status'];
|
||||
$this->subStatus = $data['sub_status'];
|
||||
$this->publicUuid = $data['public_uuid'];
|
||||
$this->displayName = $data['display_name'];
|
||||
$this->publicNickName = $data['public_nick_name'];
|
||||
$this->language = $data['language'];
|
||||
$this->region = $data['region'];
|
||||
$this->sessionTimeout = intval($data['session_timeout']);
|
||||
$this->firstName = $data['first_name'];
|
||||
$this->middleName = $data['middle_name'];
|
||||
$this->lastName = $data['last_name'];
|
||||
$this->legalName = $data['legal_name'];
|
||||
$this->taxResident = $data['tax_resident'];
|
||||
$this->dateOfBirth = Carbon::createFromFormat('Y-m-d', $data['date_of_birth']);
|
||||
$this->placeOfBirth = $data['place_of_birth'];
|
||||
$this->countryOfBirth = $data['country_of_birth'];
|
||||
$this->nationality = $data['nationality'];
|
||||
$this->gender = $data['gender'];
|
||||
$this->versionTos = intval($data['version_terms_of_service']);
|
||||
$this->documentNumber = $data['document_number'];
|
||||
$this->documentType = $data['document_type'];
|
||||
$this->documentCountry = $data['document_country_of_issuance'];
|
||||
|
||||
// create aliases
|
||||
// create avatar
|
||||
// create daily limit
|
||||
// create notification filters
|
||||
// create address main, postal
|
||||
// document front, back attachment
|
||||
// customer, customer_limit
|
||||
// billing contracts
|
||||
|
||||
// echo '<pre>';
|
||||
// print_r($data);
|
||||
// var_dump($this);
|
||||
// echo '</pre>';
|
||||
}
|
||||
|
||||
}
|
374
app/Services/Bunq/Request/BunqRequest.php
Normal file
374
app/Services/Bunq/Request/BunqRequest.php
Normal file
@ -0,0 +1,374 @@
|
||||
<?php
|
||||
/**
|
||||
* BunqRequest.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Services\Bunq\Request;
|
||||
|
||||
use Bunq\Object\ServerPublicKey;
|
||||
use Exception;
|
||||
use Monolog\Handler\StreamHandler;
|
||||
use Monolog\Logger;
|
||||
use Requests;
|
||||
use Requests_Exception;
|
||||
|
||||
/**
|
||||
* Class BunqRequest
|
||||
*
|
||||
* @package Bunq\Request
|
||||
*/
|
||||
abstract class BunqRequest
|
||||
{
|
||||
/** @var bool */
|
||||
protected $fake = false;
|
||||
/** @var string */
|
||||
protected $secret = '';
|
||||
/** @var Logger */
|
||||
private $logger;
|
||||
/** @var string */
|
||||
private $privateKey = '';
|
||||
/** @var string */
|
||||
private $server = '';
|
||||
/** @var ServerPublicKey */
|
||||
private $serverPublicKey;
|
||||
private $upperCaseHeaders
|
||||
= [
|
||||
'x-bunq-client-response-id' => 'X-Bunq-Client-Response-Id',
|
||||
'x-bunq-client-request-id' => 'X-Bunq-Client-Request-Id',
|
||||
];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
|
||||
// create a log channel
|
||||
$this->logger = new Logger('bunq-request');
|
||||
$this->logger->pushHandler(new StreamHandler('logs/bunq.log', Logger::DEBUG));
|
||||
$this->logger->debug('Hallo dan');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
abstract public function call(): void;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getServer(): string
|
||||
{
|
||||
return $this->server;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $server
|
||||
*/
|
||||
public function setServer(string $server)
|
||||
{
|
||||
$this->server = $server;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $fake
|
||||
*/
|
||||
public function setFake(bool $fake)
|
||||
{
|
||||
$this->fake = $fake;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $privateKey
|
||||
*/
|
||||
public function setPrivateKey(string $privateKey)
|
||||
{
|
||||
$this->privateKey = $privateKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $secret
|
||||
*/
|
||||
public function setSecret(string $secret)
|
||||
{
|
||||
$this->secret = $secret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ServerPublicKey $serverPublicKey
|
||||
*/
|
||||
public function setServerPublicKey(ServerPublicKey $serverPublicKey)
|
||||
{
|
||||
$this->serverPublicKey = $serverPublicKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $method
|
||||
* @param string $uri
|
||||
* @param array $headers
|
||||
* @param string $data
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function generateSignature(string $method, string $uri, array $headers, string $data): string
|
||||
{
|
||||
if (strlen($this->privateKey) === 0) {
|
||||
throw new Exception('No private key present.');
|
||||
}
|
||||
if (strtolower($method) === 'get') {
|
||||
$data = '';
|
||||
}
|
||||
|
||||
$uri = str_replace(['https://api.bunq.com', 'https://sandbox.public.api.bunq.com'], '', $uri);
|
||||
$toSign = strtoupper($method) . ' ' . $uri . "\n";
|
||||
$headersToSign = ['Cache-Control', 'User-Agent'];
|
||||
ksort($headers);
|
||||
foreach ($headers as $name => $value) {
|
||||
if (in_array($name, $headersToSign) || substr($name, 0, 7) === 'X-Bunq-') {
|
||||
$toSign .= $name . ': ' . $value . "\n";
|
||||
}
|
||||
}
|
||||
$toSign .= "\n" . $data;
|
||||
$signature = '';
|
||||
|
||||
openssl_sign($toSign, $signature, $this->privateKey, OPENSSL_ALGO_SHA256);
|
||||
$signature = base64_encode($signature);
|
||||
|
||||
return $signature;
|
||||
}
|
||||
|
||||
protected function getDefaultHeaders(): array
|
||||
{
|
||||
return [
|
||||
'X-Bunq-Client-Request-Id' => uniqid('sander'),
|
||||
'Cache-Control' => 'no-cache',
|
||||
'User-Agent' => 'pre-Firefly III test thing',
|
||||
'X-Bunq-Language' => 'en_US',
|
||||
'X-Bunq-Region' => 'nl_NL',
|
||||
'X-Bunq-Geolocation' => '0 0 0 0 NL',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param array $response
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getKeyFromResponse(string $key, array $response): array
|
||||
{
|
||||
if (isset($response['Response'])) {
|
||||
foreach ($response['Response'] as $entry) {
|
||||
$currentKey = key($entry);
|
||||
$data = current($entry);
|
||||
if ($currentKey === $key) {
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $uri
|
||||
* @param array $data
|
||||
* @param array $headers
|
||||
*
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function sendSignedBunqGet(string $uri, array $data, array $headers): array
|
||||
{
|
||||
if (strlen($this->server) === 0) {
|
||||
throw new Exception('No bunq server defined');
|
||||
}
|
||||
|
||||
$body = json_encode($data);
|
||||
$fullUri = $this->server . $uri;
|
||||
$signature = $this->generateSignature('get', $uri, $headers, $body);
|
||||
$headers['X-Bunq-Client-Signature'] = $signature;
|
||||
try {
|
||||
$response = Requests::get($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);
|
||||
if ($this->isErrorResponse($array)) {
|
||||
$this->throwResponseError($array);
|
||||
}
|
||||
$responseHeaders = $response->headers->getAll();
|
||||
$statusCode = $response->status_code;
|
||||
if (!$this->verifyServerSignature($body, $responseHeaders, $statusCode)) {
|
||||
throw new Exception(sprintf('Could not verify signature for request to "%s"', $uri));
|
||||
}
|
||||
$array['ResponseHeaders'] = $responseHeaders;
|
||||
|
||||
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);
|
||||
if ($this->isErrorResponse($array)) {
|
||||
$this->throwResponseError($array);
|
||||
}
|
||||
$responseHeaders = $response->headers->getAll();
|
||||
$statusCode = $response->status_code;
|
||||
if (!$this->verifyServerSignature($body, $responseHeaders, $statusCode)) {
|
||||
throw new Exception(sprintf('Could not verify signature for request to "%s"', $uri));
|
||||
}
|
||||
$array['ResponseHeaders'] = $responseHeaders;
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $uri
|
||||
* @param array $data
|
||||
* @param array $headers
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function sendUnsignedBunqPost(string $uri, array $data, array $headers): 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()],]];
|
||||
}
|
||||
$body = $response->body;
|
||||
$responseHeaders = $response->headers->getAll();
|
||||
$array = json_decode($body, true);
|
||||
if ($this->isErrorResponse($array)) {
|
||||
$this->throwResponseError($array);
|
||||
}
|
||||
$array['ResponseHeaders'] = $responseHeaders;
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $response
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isErrorResponse(array $response): bool
|
||||
{
|
||||
$key = key($response);
|
||||
if ($key === 'Error') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $response
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
private function throwResponseError(array $response)
|
||||
{
|
||||
echo '<hr><pre>' . print_r($response, true) . '</pre><hr>';
|
||||
$message = [];
|
||||
if (isset($response['Error'])) {
|
||||
foreach ($response['Error'] as $error) {
|
||||
$message[] = $error['error_description'];
|
||||
}
|
||||
}
|
||||
throw new Exception(join(', ', $message));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $body
|
||||
* @param array $headers
|
||||
* @param int $statusCode
|
||||
*
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
private function verifyServerSignature(string $body, array $headers, int $statusCode): bool
|
||||
{
|
||||
$this->logger->debug('Going to verify signature for body+headers+status');
|
||||
$dataToVerify = $statusCode . "\n";
|
||||
$verifyHeaders = [];
|
||||
|
||||
// false when no public key is present
|
||||
if (is_null($this->serverPublicKey)) {
|
||||
$this->logger->error('No public key present in class, so return FALSE.');
|
||||
|
||||
return false;
|
||||
}
|
||||
//$this->logger->debug('Given headers', $headers);
|
||||
foreach ($headers as $header => $value) {
|
||||
|
||||
// skip non-bunq headers or signature
|
||||
if (substr($header, 0, 7) !== 'x-bunq-' || $header === 'x-bunq-server-signature') {
|
||||
continue;
|
||||
}
|
||||
// need to have upper case variant of header:
|
||||
if (!isset($this->upperCaseHeaders[$header])) {
|
||||
throw new Exception(sprintf('No upper case variant for header "%s"', $header));
|
||||
}
|
||||
$header = $this->upperCaseHeaders[$header];
|
||||
$verifyHeaders[$header] = $value[0];
|
||||
}
|
||||
// sort verification headers:
|
||||
ksort($verifyHeaders);
|
||||
|
||||
//$this->logger->debug('Final headers for verification', $verifyHeaders);
|
||||
|
||||
// add them to data to sign:
|
||||
foreach ($verifyHeaders as $header => $value) {
|
||||
$dataToVerify .= $header . ': ' . trim($value) . "\n";
|
||||
}
|
||||
|
||||
$signature = $headers['x-bunq-server-signature'][0];
|
||||
$dataToVerify .= "\n" . $body;
|
||||
|
||||
//$this->logger->debug(sprintf('Signature to verify: "%s"', $signature));
|
||||
|
||||
$result = openssl_verify($dataToVerify, base64_decode($signature), $this->serverPublicKey->getPublicKey(), OPENSSL_ALGO_SHA256);
|
||||
|
||||
if (is_int($result) && $result < 1) {
|
||||
$this->logger->error(sprintf('Result of verification is %d, return false.', $result));
|
||||
|
||||
return false;
|
||||
}
|
||||
if (!is_int($result)) {
|
||||
$this->logger->error(sprintf('Result of verification is a boolean (%d), return false.', $result));
|
||||
}
|
||||
$this->logger->info('Signature is a match, return true.');
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
149
app/Services/Bunq/Request/InstallationTokenRequest.php
Normal file
149
app/Services/Bunq/Request/InstallationTokenRequest.php
Normal file
@ -0,0 +1,149 @@
|
||||
<?php
|
||||
/**
|
||||
* InstallationTokenRequest.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Services\Bunq\Request;
|
||||
|
||||
use FireflyIII\Services\Bunq\Id\InstallationId;
|
||||
|
||||
/**
|
||||
* Class InstallationTokenRequest
|
||||
*
|
||||
* @package FireflyIII\Services\Bunq\Request
|
||||
*/
|
||||
class InstallationTokenRequest extends BunqRequest
|
||||
{
|
||||
/** @var InstallationId */
|
||||
private $installationId;
|
||||
/** @var InstallationToken */
|
||||
private $installationToken;
|
||||
/** @var string */
|
||||
private $publicKey = '';
|
||||
/** @var ServerPublicKey */
|
||||
private $serverPublicKey;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function call(): void
|
||||
{
|
||||
$uri = '/v1/installation';
|
||||
$data = ['client_public_key' => $this->publicKey,];
|
||||
$headers = $this->getDefaultHeaders();
|
||||
$response = [];
|
||||
if ($this->fake) {
|
||||
$response = json_decode(
|
||||
'{"Response":[{"Id":{"id":875936}},{"Token":{"id":13172597,"created":"2017-08-05 11:46:07.061740","updated":"2017-08-05 11:46:07.061740","token":"35278fcc8b0615261fe23285e6d2e6ccd05ac4c93454981bd5e985ec453e5b5d"}},{"ServerPublicKey":{"server_public_key":"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAon5y6OZGvTN8kIqPBdro\ndG8TWVw6sl34hAWI47NK6Pi7gmnTtd\/k9gfwq56iI4Er8uMM5e4QmjD++XrBIqcw\nHohDVK03li3xsyJPZ4EBSUOkv4VKXKL\/quqlSgDmPnxtT39BowUZl1um5QbTm0hW\npGI\/0bK7jQk7mbEan9yDOpXnczKgfNlo4o+zbFquPdUfA5LE8R8X057dB6ab7eqA\n9Aybo+I6xyrsOOztufg3Yfe5RA6a0Sikqe\/L8HCP+9TJByUI2pwydPou3KONfYhK\n1NQJZ+RCZ6V+jmcuzKe2vq0jhBZd26wNscl48Sm7etJeuBOpHE+MgO24JiTEYlLS\nVQIDAQAB\n-----END PUBLIC KEY-----\n"}}]}',
|
||||
true
|
||||
);
|
||||
}
|
||||
if (!$this->fake) {
|
||||
$response = $this->sendUnsignedBunqPost($uri, $data, $headers);
|
||||
}
|
||||
//echo '<hr><pre>' . json_encode($response) . '</pre><hr>';
|
||||
|
||||
$this->installationId = $this->extractInstallationId($response);
|
||||
$this->serverPublicKey = $this->extractServerPublicKey($response);
|
||||
$this->installationToken = $this->extractInstallationToken($response);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return InstallationId
|
||||
*/
|
||||
public function getInstallationId(): InstallationId
|
||||
{
|
||||
return $this->installationId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return InstallationToken
|
||||
*/
|
||||
public function getInstallationToken(): InstallationToken
|
||||
{
|
||||
return $this->installationToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getPublicKey(): string
|
||||
{
|
||||
return $this->publicKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $publicKey
|
||||
*/
|
||||
public function setPublicKey(string $publicKey)
|
||||
{
|
||||
$this->publicKey = $publicKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ServerPublicKey
|
||||
*/
|
||||
public function getServerPublicKey(): ServerPublicKey
|
||||
{
|
||||
return $this->serverPublicKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $fake
|
||||
*/
|
||||
public function setFake(bool $fake)
|
||||
{
|
||||
$this->fake = $fake;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $response
|
||||
*
|
||||
* @return InstallationId
|
||||
*/
|
||||
private function extractInstallationId(array $response): InstallationId
|
||||
{
|
||||
$installationId = new InstallationId;
|
||||
$data = $this->getKeyFromResponse('Id', $response);
|
||||
$installationId->setId(intval($data['id']));
|
||||
|
||||
return $installationId;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $response
|
||||
*
|
||||
* @return InstallationToken
|
||||
*/
|
||||
private function extractInstallationToken(array $response): InstallationToken
|
||||
{
|
||||
|
||||
$data = $this->getKeyFromResponse('Token', $response);
|
||||
$installationToken = new InstallationToken($data);
|
||||
|
||||
return $installationToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $response
|
||||
*
|
||||
* @return ServerPublicKey
|
||||
*/
|
||||
private function extractServerPublicKey(array $response): ServerPublicKey
|
||||
{
|
||||
$data = $this->getKeyFromResponse('ServerPublicKey', $response);
|
||||
$serverPublicKey = new ServerPublicKey($data);
|
||||
|
||||
return $serverPublicKey;
|
||||
}
|
||||
}
|
89
app/Services/Bunq/Token/BunqToken.php
Normal file
89
app/Services/Bunq/Token/BunqToken.php
Normal file
@ -0,0 +1,89 @@
|
||||
<?php
|
||||
/**
|
||||
* BunqToken.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Services\Bunq\Token;
|
||||
|
||||
|
||||
use Carbon\Carbon;
|
||||
|
||||
/**
|
||||
* Class BunqToken
|
||||
*
|
||||
* @package Bunq\Token
|
||||
*/
|
||||
class BunqToken
|
||||
{
|
||||
/** @var Carbon */
|
||||
private $created;
|
||||
/** @var int */
|
||||
private $id = 0;
|
||||
/** @var string */
|
||||
private $token = '';
|
||||
/** @var Carbon */
|
||||
private $updated;
|
||||
|
||||
/**
|
||||
* BunqToken constructor.
|
||||
*
|
||||
* @param array $response
|
||||
*/
|
||||
public function __construct(array $response)
|
||||
{
|
||||
$this->makeTokenFromResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Carbon
|
||||
*/
|
||||
public function getCreated(): Carbon
|
||||
{
|
||||
return $this->created;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getId(): int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getToken(): string
|
||||
{
|
||||
return $this->token;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Carbon
|
||||
*/
|
||||
public function getUpdated(): Carbon
|
||||
{
|
||||
return $this->updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $response
|
||||
*/
|
||||
protected function makeTokenFromResponse(array $response): void
|
||||
{
|
||||
$this->id = $response['id'];
|
||||
$this->created = Carbon::createFromFormat('Y-m-d H:i:s.u', $response['created']);
|
||||
$this->updated = Carbon::createFromFormat('Y-m-d H:i:s.u', $response['updated']);
|
||||
$this->token = $response['token'];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
24
app/Services/Bunq/Token/InstallationToken.php
Normal file
24
app/Services/Bunq/Token/InstallationToken.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
/**
|
||||
* InstallationToken.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Services\Bunq\Token;
|
||||
|
||||
/**
|
||||
* Class InstallationToken
|
||||
*
|
||||
* @package FireflyIII\Services\Bunq\Token
|
||||
*/
|
||||
class InstallationToken extends BunqToken
|
||||
{
|
||||
|
||||
|
||||
}
|
25
app/Services/Bunq/Token/SessionToken.php
Normal file
25
app/Services/Bunq/Token/SessionToken.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
/**
|
||||
* SessionToken.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* This software may be modified and distributed under the terms of the
|
||||
* Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Bunq\Token;
|
||||
|
||||
namespace FireflyIII\Services\Bunq\Token;
|
||||
|
||||
/**
|
||||
* Class SessionToken
|
||||
*
|
||||
* @package FireflyIII\Services\Bunq\Token
|
||||
*/
|
||||
class SessionToken extends BunqToken
|
||||
{
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user