2023-11-30 16:00:50 +01:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* Invoice Ninja (https://invoiceninja.com).
|
|
|
|
*
|
|
|
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
|
|
|
*
|
|
|
|
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
|
|
|
|
*
|
|
|
|
* @license https://www.elastic.co/licensing/elastic-license
|
2023-12-01 14:30:33 +01:00
|
|
|
*
|
|
|
|
* Documentation of Api-Usage: https://developer.gocardless.com/bank-account-data/overview
|
2023-12-13 15:37:19 +01:00
|
|
|
*
|
|
|
|
* Institutions: Are Banks or Payment-Providers, which manages bankaccounts.
|
|
|
|
*
|
|
|
|
* Accounts: Accounts are existing bank_accounts at a specific institution.
|
|
|
|
*
|
|
|
|
* Requisitions: Are registered/active user-flows to authenticate one or many accounts. After completition, the accoundId could be used to fetch data for this account. After the access expires, the user could create a new requisition to connect accounts again.
|
2023-11-30 16:00:50 +01:00
|
|
|
*/
|
|
|
|
|
2023-12-01 14:30:33 +01:00
|
|
|
namespace App\Helpers\Bank\Nordigen;
|
2023-11-30 16:00:50 +01:00
|
|
|
|
|
|
|
use App\Helpers\Bank\Nordigen\Transformer\AccountTransformer;
|
2023-12-11 16:13:26 +01:00
|
|
|
use App\Helpers\Bank\Nordigen\Transformer\TransactionTransformer;
|
2023-12-13 16:18:18 +01:00
|
|
|
use Log;
|
2023-11-30 16:00:50 +01:00
|
|
|
|
|
|
|
class Nordigen
|
|
|
|
{
|
2023-12-11 16:13:26 +01:00
|
|
|
public bool $test_mode; // https://developer.gocardless.com/bank-account-data/sandbox
|
2023-11-30 16:00:50 +01:00
|
|
|
|
2023-12-01 14:30:33 +01:00
|
|
|
public string $sandbox_institutionId = "SANDBOXFINANCE_SFIN0000";
|
2023-11-30 16:00:50 +01:00
|
|
|
|
2023-12-01 14:30:33 +01:00
|
|
|
protected \Nordigen\NordigenPHP\API\NordigenClient $client;
|
2023-11-30 16:00:50 +01:00
|
|
|
|
2023-12-13 15:37:19 +01:00
|
|
|
public function __construct()
|
2023-11-30 16:00:50 +01:00
|
|
|
{
|
2023-12-11 16:13:26 +01:00
|
|
|
$this->test_mode = config('ninja.nordigen.test_mode');
|
|
|
|
|
2023-12-13 15:37:19 +01:00
|
|
|
if (!(config('ninja.nordigen.secret_id') && config('ninja.nordigen.secret_key')))
|
|
|
|
throw new \Exception('missing nordigen credentials');
|
|
|
|
|
|
|
|
$this->client = new \Nordigen\NordigenPHP\API\NordigenClient(config('ninja.nordigen.secret_id'), config('ninja.nordigen.secret_key'));
|
2023-12-04 08:14:52 +01:00
|
|
|
|
|
|
|
$this->client->createAccessToken(); // access_token is valid 24h -> so we dont have to implement a refresh-cycle
|
2023-11-30 16:00:50 +01:00
|
|
|
}
|
|
|
|
|
2023-12-01 14:30:33 +01:00
|
|
|
// metadata-section for frontend
|
2023-11-30 16:00:50 +01:00
|
|
|
public function getInstitutions()
|
|
|
|
{
|
2023-12-01 14:30:33 +01:00
|
|
|
if ($this->test_mode)
|
2023-12-15 13:10:45 +01:00
|
|
|
return [$this->client->institution->getInstitution($this->sandbox_institutionId)];
|
2023-12-01 14:30:33 +01:00
|
|
|
|
2023-11-30 16:00:50 +01:00
|
|
|
return $this->client->institution->getInstitutions();
|
|
|
|
}
|
|
|
|
|
2023-12-01 14:30:33 +01:00
|
|
|
// requisition-section
|
2023-12-06 08:27:18 +01:00
|
|
|
public function createRequisition(string $redirect, string $initutionId, string $reference)
|
2023-12-01 14:30:33 +01:00
|
|
|
{
|
|
|
|
if ($this->test_mode && $initutionId != $this->sandbox_institutionId)
|
|
|
|
throw new \Exception('invalid institutionId while in test-mode');
|
|
|
|
|
2023-12-13 15:37:19 +01:00
|
|
|
return $this->client->requisition->createRequisition($redirect, $initutionId, null, $reference);
|
2023-12-01 14:30:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public function getRequisition(string $requisitionId)
|
|
|
|
{
|
2023-12-20 12:22:24 +01:00
|
|
|
try {
|
|
|
|
return $this->client->requisition->getRequisition($requisitionId);
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
if (strpos($e->getMessage(), "Invalid Requisition ID") !== false)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
throw $e;
|
|
|
|
}
|
2023-12-01 14:30:33 +01:00
|
|
|
}
|
|
|
|
|
2023-12-09 09:27:59 +01:00
|
|
|
// TODO: return null on not found
|
2023-12-01 14:30:33 +01:00
|
|
|
public function getAccount(string $account_id)
|
2023-11-30 16:00:50 +01:00
|
|
|
{
|
2023-12-12 07:23:53 +01:00
|
|
|
try {
|
|
|
|
$out = new \stdClass();
|
2023-11-30 16:00:50 +01:00
|
|
|
|
2023-12-12 07:23:53 +01:00
|
|
|
$out->data = $this->client->account($account_id)->getAccountDetails()["account"];
|
|
|
|
$out->metadata = $this->client->account($account_id)->getAccountMetaData();
|
|
|
|
$out->balances = $this->client->account($account_id)->getAccountBalances()["balances"];
|
|
|
|
$out->institution = $this->client->institution->getInstitution($out->metadata["institution_id"]);
|
2023-11-30 16:00:50 +01:00
|
|
|
|
2023-12-12 07:23:53 +01:00
|
|
|
$it = new AccountTransformer();
|
|
|
|
return $it->transform($out);
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
if (strpos($e->getMessage(), "Invalid Account ID") !== false)
|
2023-12-20 12:22:24 +01:00
|
|
|
return false;
|
2023-11-30 16:00:50 +01:00
|
|
|
|
2023-12-12 07:23:53 +01:00
|
|
|
throw $e;
|
|
|
|
}
|
2023-11-30 16:00:50 +01:00
|
|
|
}
|
|
|
|
|
2023-12-01 14:30:33 +01:00
|
|
|
public function isAccountActive(string $account_id)
|
2023-11-30 16:00:50 +01:00
|
|
|
{
|
2023-12-01 14:30:33 +01:00
|
|
|
try {
|
|
|
|
$account = $this->client->account($account_id)->getAccountMetaData();
|
|
|
|
|
|
|
|
if ($account["status"] != "READY")
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
} catch (\Exception $e) {
|
2023-12-12 07:23:53 +01:00
|
|
|
if (strpos($e->getMessage(), "Invalid Account ID") !== false)
|
|
|
|
return false;
|
2023-12-01 14:30:33 +01:00
|
|
|
|
2023-12-12 07:23:53 +01:00
|
|
|
throw $e;
|
|
|
|
}
|
2023-11-30 16:00:50 +01:00
|
|
|
}
|
|
|
|
|
2023-12-09 17:16:01 +01:00
|
|
|
/**
|
|
|
|
* this method returns booked transactions from the bank_account, pending transactions are not part of the result
|
|
|
|
* @todo @turbo124 should we include pending transactions within the integration-process and mark them with a specific category?!
|
|
|
|
*/
|
2023-12-01 14:30:33 +01:00
|
|
|
public function getTransactions(string $accountId, string $dateFrom = null)
|
2023-11-30 16:00:50 +01:00
|
|
|
{
|
2023-12-09 17:16:01 +01:00
|
|
|
$transactionResponse = $this->client->account($accountId)->getAccountTransactions($dateFrom);
|
|
|
|
|
2023-12-11 16:13:26 +01:00
|
|
|
$it = new TransactionTransformer();
|
2023-12-09 17:16:01 +01:00
|
|
|
return $it->transform($transactionResponse);
|
2023-12-01 14:30:33 +01:00
|
|
|
}
|
2023-11-30 16:00:50 +01:00
|
|
|
}
|