Improved extraction of bunq data.

This commit is contained in:
James Cole 2017-08-26 06:21:22 +02:00
parent 4b2abb6f25
commit 0f229e4d7b
No known key found for this signature in database
GPG Key ID: C16961E655E74B5E
14 changed files with 605 additions and 22 deletions

View File

@ -34,7 +34,7 @@ class BankController extends Controller
$object->setUser(auth()->user());
if ($object->hasPrerequisites()) {
return redirect(route('import.banq.prerequisites', [$bank]));
return redirect(route('import.bank.prerequisites', [$bank]));
}
$class = config(sprintf('firefly.import_info.%s', $bank));
/** @var InformationInterface $object */

View File

@ -0,0 +1,69 @@
<?php
/**
* Alias.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 Alias
*
* @package FireflyIII\Services\Bunq\Object
*/
class Alias extends BunqObject
{
/** @var string */
private $name = '';
/** @var string */
private $type = '';
/** @var string */
private $value = '';
/**
* Alias constructor.
*
* @param array $data
*/
public function __construct(array $data)
{
$this->type = $data['type'];
$this->name = $data['name'];
$this->value = $data['value'];
return;
}
/**
* @return string
*/
public function getName(): string
{
return $this->name;
}
/**
* @return string
*/
public function getType(): string
{
return $this->type;
}
/**
* @return string
*/
public function getValue(): string
{
return $this->value;
}
}

View File

@ -0,0 +1,58 @@
<?php
/**
* Currency.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 Amount
*
* @package FireflyIII\Services\Bunq\Object
*/
class Amount extends BunqObject
{
/** @var string */
private $currency = '';
/** @var string */
private $value = '';
/**
* Amount constructor.
*
* @param array $data
*/
public function __construct(array $data)
{
$this->currency = $data['currency'];
$this->value = $data['value'];
return;
}
/**
* @return string
*/
public function getCurrency(): string
{
return $this->currency;
}
/**
* @return string
*/
public function getValue(): string
{
return $this->value;
}
}

View File

@ -0,0 +1,23 @@
<?php
/**
* Avatar.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 Avatar
*
* @package FireflyIII\Services\Bunq\Object
*/
class Avatar extends BunqObject
{
}

View File

@ -12,6 +12,8 @@ declare(strict_types=1);
namespace FireflyIII\Services\Bunq\Object;
use Carbon\Carbon;
/**
* Class MonetaryAccountBank
*
@ -19,13 +21,133 @@ namespace FireflyIII\Services\Bunq\Object;
*/
class MonetaryAccountBank extends BunqObject
{
/** @var array */
private $aliases = [];
/** @var Avatar */
private $avatar;
/** @var Amount */
private $balance;
/** @var Carbon */
private $created;
/** @var string */
private $currency = '';
/** @var Amount */
private $dailyLimit;
/** @var Amount */
private $dailySpent;
/** @var string */
private $description = '';
/** @var int */
private $id = 0;
/** @var MonetaryAccountProfile */
private $monetaryAccountProfile;
/** @var array */
private $notificationFilters = [];
/** @var Amount */
private $overdraftLimit;
/** @var string */
private $publicUuid = '';
/** @var string */
private $reason = '';
/** @var string */
private $reasonDescription = '';
/** @var MonetaryAccountSetting */
private $setting;
/** @var string */
private $status = '';
/** @var string */
private $subStatus = '';
/** @var Carbon */
private $updated;
/** @var int */
private $userId = 0;
/**
* @return string
*/
public function getDescription(): string
{
return $this->description;
}
/**
* @return int
*/
public function getId(): int
{
return $this->id;
}
/**
* @return array
*/
public function getAliases(): array
{
return $this->aliases;
}
/**
* @return string
*/
public function getCurrency(): string
{
return $this->currency;
}
/**
* @return Amount
*/
public function getBalance(): Amount
{
return $this->balance;
}
/**
* @return MonetaryAccountSetting
*/
public function getSetting(): MonetaryAccountSetting
{
return $this->setting;
}
/**
* MonetaryAccountBank constructor.
*
* @param array $data
*/
public function __construct(array $data) {
public function __construct(array $data)
{
$this->id = $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->balance = new Amount($data['balance']);
$this->currency = $data['currency'];
$this->dailyLimit = new Amount($data['daily_limit']);
$this->dailySpent = new Amount($data['daily_spent']);
$this->description = $data['description'];
$this->publicUuid = $data['public_uuid'];
$this->status = $data['status'];
$this->subStatus = $data['sub_status'];
$this->userId = $data['user_id'];
$this->status = $data['status'];
$this->subStatus = $data['sub_status'];
$this->monetaryAccountProfile = new MonetaryAccountProfile($data['monetary_account_profile']);
$this->setting = new MonetaryAccountSetting($data['setting']);
$this->overdraftLimit = new Amount($data['overdraft_limit']);
$this->publicUuid = $data['public_uuid'];
// create aliases:
foreach ($data['alias'] as $alias) {
$this->aliases[] = new Alias($alias);
}
foreach ($data['notification_filters'] as $filter) {
$this->notificationFilters = new NotificationFilter($filter);
}
return;
}
}

View File

@ -0,0 +1,43 @@
<?php
/**
* MonetaryAccountProfile.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 MonetaryAccountProfile
*
* @package FireflyIII\Services\Bunq\Object
*/
class MonetaryAccountProfile extends BunqObject
{
/** @var string */
private $profileActionRequired = '';
/** @var Amount */
private $profileAmountRequired;
private $profileDrain;
private $profileFill;
/**
* MonetaryAccountProfile constructor.
*
* @param array $data
*/
public function __construct(array $data)
{
$this->profileDrain = null;
$this->profileFill = null;
$this->profileActionRequired = $data['profile_action_required'];
$this->profileAmountRequired = new Amount($data['profile_amount_required']);
return;
}
}

View File

@ -0,0 +1,67 @@
<?php
/**
* MonetaryAccountSetting.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 MonetaryAccountSetting
*
* @package FireflyIII\Services\Bunq\Object
*/
class MonetaryAccountSetting extends BunqObject
{
/** @var string */
private $color = '';
/** @var string */
private $defaultAvatarStatus = '';
/** @var string */
private $restrictionChat = '';
/**
* MonetaryAccountSetting constructor.
*
* @param array $data
*/
public function __construct(array $data)
{
$this->color = $data['color'];
$this->defaultAvatarStatus = $data['default_avatar_status'];
$this->restrictionChat = $data['restriction_chat'];
return;
}
/**
* @return string
*/
public function getColor(): string
{
return $this->color;
}
/**
* @return string
*/
public function getDefaultAvatarStatus(): string
{
return $this->defaultAvatarStatus;
}
/**
* @return string
*/
public function getRestrictionChat(): string
{
return $this->restrictionChat;
}
}

View File

@ -0,0 +1,32 @@
<?php
/**
* NotificationFilter.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 NotificationFilter
*
* @package FireflyIII\Services\Bunq\Object
*/
class NotificationFilter extends BunqObject
{
/**
* NotificationFilter constructor.
*
* @param array $data
*/
public function __construct(array $data) {
var_dump($data);
exit;
}
}

View File

@ -94,4 +94,14 @@ class UserCompany extends BunqObject
}
/**
* @return int
*/
public function getId(): int
{
return $this->id;
}
}

View File

@ -0,0 +1,79 @@
<?php
/**
* ListMonetaryAccountRequest.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\Object\MonetaryAccountBank;
use FireflyIII\Services\Bunq\Token\SessionToken;
use Illuminate\Support\Collection;
/**
* Class ListMonetaryAccountRequest
*
* @package FireflyIII\Services\Bunq\Request
*/
class ListMonetaryAccountRequest extends BunqRequest
{
/** @var Collection */
private $monetaryAccounts;
/** @var SessionToken */
private $sessionToken;
/** @var int */
private $userId = 0;
/**
* @return Collection
*/
public function getMonetaryAccounts(): Collection
{
return $this->monetaryAccounts;
}
/**
*
*/
public function call(): void
{
$this->monetaryAccounts = new Collection;
$uri = sprintf('/v1/user/%d/monetary-account', $this->userId);
$data = [];
$headers = $this->getDefaultHeaders();
$headers['X-Bunq-Client-Authentication'] = $this->sessionToken->getToken();
$response = $this->sendSignedBunqGet($uri, $data, $headers);
// create device server objects:
$raw = $this->getArrayFromResponse('MonetaryAccountBank', $response);
foreach ($raw as $entry) {
$account = new MonetaryAccountBank($entry);
$this->monetaryAccounts->push($account);
}
return;
}
/**
* @param SessionToken $sessionToken
*/
public function setSessionToken(SessionToken $sessionToken)
{
$this->sessionToken = $sessionToken;
}
/**
* @param int $userId
*/
public function setUserId(int $userId)
{
$this->userId = $userId;
}
}

View File

@ -12,8 +12,12 @@ declare(strict_types=1);
namespace FireflyIII\Support\Import\Information;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Services\Bunq\Object\Alias;
use FireflyIII\Services\Bunq\Object\MonetaryAccountBank;
use FireflyIII\Services\Bunq\Request\DeleteDeviceSessionRequest;
use FireflyIII\Services\Bunq\Request\DeviceSessionRequest;
use FireflyIII\Services\Bunq\Request\ListMonetaryAccountRequest;
use FireflyIII\Services\Bunq\Request\ListUserRequest;
use FireflyIII\Services\Bunq\Token\SessionToken;
use FireflyIII\User;
@ -35,20 +39,52 @@ class BunqInformation implements InformationInterface
/**
* Returns a collection of accounts. Preferrably, these follow a uniform Firefly III format so they can be managed over banks.
*
* @return Collection
* The format for these bank accounts is basically this:
*
* id: bank specific id
* name: bank appointed name
* number: account number (usually IBAN)
* currency: ISO code of currency
* balance: current balance
*
*
* any other fields are optional but can be useful:
* image: logo or account specific thing
* color: any associated color.
*
* @return array
*/
public function getAccounts(): Collection
public function getAccounts(): array
{
Log::debug('Now in getAccounts()');
$sessionToken = $this->startSession();
$this->getUserInformation($sessionToken);
$id = $this->getUserInformation($sessionToken);
// get list of Bunq accounts:
$accounts = $this->getMonetaryAccounts($sessionToken, $id);
$return = [];
/** @var MonetaryAccountBank $account */
foreach ($accounts as $account) {
$current = [
'id' => $account->getId(),
'name' => $account->getDescription(),
'currency' => $account->getCurrency(),
'balance' => $account->getBalance()->getValue(),
'color' => $account->getSetting()->getColor(),
];
/** @var Alias $alias */
foreach ($account->getAliases() as $alias) {
if ($alias->getType() === 'IBAN') {
$current['number'] = $alias->getValue();
}
}
$return[] = $current;
}
$this->closeSession($sessionToken);
return new Collection;
return $return;
}
/**
@ -78,19 +114,49 @@ class BunqInformation implements InformationInterface
$request->setServerPublicKey($serverPublicKey);
$request->setSessionToken($sessionToken);
$request->call();
return;
}
/**
* @param SessionToken $sessionToken
* @param int $userId
*
* @return Collection
*/
private function getUserInformation(SessionToken $sessionToken): void
private function getMonetaryAccounts(SessionToken $sessionToken, int $userId): Collection
{
$apiKey = Preferences::getForUser($this->user, 'bunq_api_key')->data;
$serverPublicKey = Preferences::getForUser($this->user, 'bunq_server_public_key')->data;
$server = config('firefly.bunq.server');
$privateKey = Preferences::getForUser($this->user, 'bunq_private_key')->data;
$request = new ListUserRequest;
$apiKey = Preferences::getForUser($this->user, 'bunq_api_key')->data;
$serverPublicKey = Preferences::getForUser($this->user, 'bunq_server_public_key')->data;
$server = config('firefly.bunq.server');
$privateKey = Preferences::getForUser($this->user, 'bunq_private_key')->data;
$request = new ListMonetaryAccountRequest;
$request->setSessionToken($sessionToken);
$request->setSecret($apiKey);
$request->setServerPublicKey($serverPublicKey);
$request->setServer($server);
$request->setPrivateKey($privateKey);
$request->setUserId($userId);
$request->call();
return $request->getMonetaryAccounts();
}
/**
* @param SessionToken $sessionToken
*
* @return int
* @throws FireflyException
*/
private function getUserInformation(SessionToken $sessionToken): int
{
$apiKey = Preferences::getForUser($this->user, 'bunq_api_key')->data;
$serverPublicKey = Preferences::getForUser($this->user, 'bunq_server_public_key')->data;
$server = config('firefly.bunq.server');
$privateKey = Preferences::getForUser($this->user, 'bunq_private_key')->data;
$request = new ListUserRequest;
$request->setSessionToken($sessionToken);
$request->setSecret($apiKey);
$request->setServerPublicKey($serverPublicKey);
@ -98,12 +164,15 @@ class BunqInformation implements InformationInterface
$request->setPrivateKey($privateKey);
$request->call();
// return the first that isn't null?
// get all objects, try to find ID.
var_dump($request->getUserCompany());
var_dump($request->getUserLight());
var_dump($request->getUserPerson());
return;
$company = $request->getUserCompany();
if ($company->getId() > 0) {
return $company->getId();
}
$user = $request->getUserPerson();
if ($user->getId() > 0) {
return $user->getId();
}
throw new FireflyException('Expected user or company from Bunq, but got neither.');
}
/**

View File

@ -33,7 +33,17 @@ interface InformationInterface
/**
* Returns a collection of accounts. Preferrably, these follow a uniform Firefly III format so they can be managed over banks.
*
* @return Collection
* The format for these bank accounts is basically this:
*
* id: bank specific id
* name: bank appointed name
* number: account number (usually IBAN)
* currency: ISO code of currency
*
* any other fields are optional but can be useful:
* image: logo or account specific thing
*
* @return array
*/
public function getAccounts(): Collection;
public function getAccounts(): array;
}

View File

@ -68,7 +68,8 @@ class BunqPrerequisites implements PrerequisitesInterface
{
$apiKey = Preferences::getForUser($this->user, 'bunq_api_key', false);
return ($apiKey->data === false);
return ($apiKey->data === false || is_null($apiKey->data));
}
/**

View File

@ -46,7 +46,7 @@ return [
'bunq' => 'FireflyIII\Support\Import\Information\BunqInformation',
],
'bunq' => [
'server' => 'https://api.bunq.com',
'server' => 'https://sandbox.public.api.bunq.com',
],
'default_export_format' => 'csv',
'default_import_format' => 'csv',