Updates for gocardless requisition updates
This commit is contained in:
parent
1815a86bb9
commit
0d4aa5db0f
|
|
@ -8,15 +8,14 @@ use Illuminate\Support\Collection;
|
||||||
use Illuminate\Support\Facades\Http;
|
use Illuminate\Support\Facades\Http;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class Client
|
class NordigenClient
|
||||||
{
|
{
|
||||||
private string $baseUrl;
|
private string $baseUrl = 'https://bankaccountdata.gocardless.com/api/v2';
|
||||||
private string $accessToken;
|
|
||||||
private PendingRequest $httpClient;
|
private PendingRequest $httpClient;
|
||||||
|
|
||||||
public function __construct(string $baseUrl, string $accessToken)
|
public function __construct(private string $accessToken)
|
||||||
{
|
{
|
||||||
$this->baseUrl = rtrim($baseUrl, '/');
|
|
||||||
$this->accessToken = $accessToken;
|
$this->accessToken = $accessToken;
|
||||||
$this->httpClient = Http::withHeaders([
|
$this->httpClient = Http::withHeaders([
|
||||||
'Authorization' => "Bearer {$this->accessToken}",
|
'Authorization' => "Bearer {$this->accessToken}",
|
||||||
|
|
@ -39,7 +38,7 @@ class Client
|
||||||
|
|
||||||
$response = $this->httpClient->get("{$this->baseUrl}/requisitions/", $params);
|
$response = $this->httpClient->get("{$this->baseUrl}/requisitions/", $params);
|
||||||
|
|
||||||
return $this->handlePaginatedResponse($response, 'requisitions');
|
return $this->handlePaginatedResponse($response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -94,6 +93,7 @@ class Client
|
||||||
do {
|
do {
|
||||||
$requisitions = $this->getRequisitions($limit, $offset);
|
$requisitions = $this->getRequisitions($limit, $offset);
|
||||||
|
|
||||||
|
nlog($requisitions);
|
||||||
if ($requisitions->isEmpty()) {
|
if ($requisitions->isEmpty()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -122,7 +122,7 @@ class Client
|
||||||
|
|
||||||
$response = $this->httpClient->get("{$this->baseUrl}/agreements/", $params);
|
$response = $this->httpClient->get("{$this->baseUrl}/agreements/", $params);
|
||||||
|
|
||||||
return $this->handlePaginatedResponse($response, 'agreements');
|
return $this->handlePaginatedResponse($response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -198,14 +198,11 @@ class Client
|
||||||
*/
|
*/
|
||||||
public function getInstitutions(int $limit = 100, ?string $offset = null): Collection
|
public function getInstitutions(int $limit = 100, ?string $offset = null): Collection
|
||||||
{
|
{
|
||||||
$params = ['limit' => $limit];
|
$params = [];
|
||||||
if ($offset) {
|
|
||||||
$params['offset'] = $offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = $this->httpClient->get("{$this->baseUrl}/institutions/", $params);
|
$response = $this->httpClient->get("{$this->baseUrl}/institutions/", $params);
|
||||||
|
|
||||||
return $this->handlePaginatedResponse($response, 'institutions');
|
return $this->handlePaginatedResponse($response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -230,7 +227,7 @@ class Client
|
||||||
|
|
||||||
$response = $this->httpClient->get("{$this->baseUrl}/institutions/", $params);
|
$response = $this->httpClient->get("{$this->baseUrl}/institutions/", $params);
|
||||||
|
|
||||||
return $this->handlePaginatedResponse($response, 'institutions');
|
return $this->handlePaginatedResponse($response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -273,7 +270,7 @@ class Client
|
||||||
|
|
||||||
$response = $this->httpClient->get("{$this->baseUrl}/enduser-agreements/", $params);
|
$response = $this->httpClient->get("{$this->baseUrl}/enduser-agreements/", $params);
|
||||||
|
|
||||||
return $this->handlePaginatedResponse($response, 'enduser_agreements');
|
return $this->handlePaginatedResponse($response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -330,7 +327,7 @@ class Client
|
||||||
|
|
||||||
$response = $this->httpClient->get("{$this->baseUrl}/accounts/", $params);
|
$response = $this->httpClient->get("{$this->baseUrl}/accounts/", $params);
|
||||||
|
|
||||||
return $this->handlePaginatedResponse($response, 'accounts');
|
return $this->handlePaginatedResponse($response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -447,7 +444,7 @@ class Client
|
||||||
|
|
||||||
$response = $this->httpClient->get("{$this->baseUrl}/accounts/{$accountId}/transactions/", $params);
|
$response = $this->httpClient->get("{$this->baseUrl}/accounts/{$accountId}/transactions/", $params);
|
||||||
|
|
||||||
return $this->handlePaginatedResponse($response, 'transactions');
|
return $this->handlePaginatedResponse($response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -475,7 +472,7 @@ class Client
|
||||||
|
|
||||||
$response = $this->httpClient->get("{$this->baseUrl}/transactions/", $params);
|
$response = $this->httpClient->get("{$this->baseUrl}/transactions/", $params);
|
||||||
|
|
||||||
return $this->handlePaginatedResponse($response, 'transactions');
|
return $this->handlePaginatedResponse($response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -527,7 +524,7 @@ class Client
|
||||||
|
|
||||||
$response = $this->httpClient->get("{$this->baseUrl}/accounts/{$accountId}/transactions/", $params);
|
$response = $this->httpClient->get("{$this->baseUrl}/accounts/{$accountId}/transactions/", $params);
|
||||||
|
|
||||||
return $this->handlePaginatedResponse($response, 'transactions');
|
return $this->handlePaginatedResponse($response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -550,7 +547,7 @@ class Client
|
||||||
|
|
||||||
$response = $this->httpClient->get("{$this->baseUrl}/accounts/{$accountId}/transactions/", $params);
|
$response = $this->httpClient->get("{$this->baseUrl}/accounts/{$accountId}/transactions/", $params);
|
||||||
|
|
||||||
return $this->handlePaginatedResponse($response, 'transactions');
|
return $this->handlePaginatedResponse($response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -573,7 +570,7 @@ class Client
|
||||||
|
|
||||||
$response = $this->httpClient->get("{$this->baseUrl}/accounts/{$accountId}/transactions/", $params);
|
$response = $this->httpClient->get("{$this->baseUrl}/accounts/{$accountId}/transactions/", $params);
|
||||||
|
|
||||||
return $this->handlePaginatedResponse($response, 'transactions');
|
return $this->handlePaginatedResponse($response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -598,7 +595,7 @@ class Client
|
||||||
|
|
||||||
$response = $this->httpClient->get("{$this->baseUrl}/accounts/{$accountId}/transactions/", $params);
|
$response = $this->httpClient->get("{$this->baseUrl}/accounts/{$accountId}/transactions/", $params);
|
||||||
|
|
||||||
return $this->handlePaginatedResponse($response, 'transactions');
|
return $this->handlePaginatedResponse($response);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== PAYMENTS ====================
|
// ==================== PAYMENTS ====================
|
||||||
|
|
@ -615,7 +612,7 @@ class Client
|
||||||
|
|
||||||
$response = $this->httpClient->get("{$this->baseUrl}/payments/", $params);
|
$response = $this->httpClient->get("{$this->baseUrl}/payments/", $params);
|
||||||
|
|
||||||
return $this->handlePaginatedResponse($response, 'payments');
|
return $this->handlePaginatedResponse($response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -672,7 +669,7 @@ class Client
|
||||||
|
|
||||||
$response = $this->httpClient->get("{$this->baseUrl}/mandates/", $params);
|
$response = $this->httpClient->get("{$this->baseUrl}/mandates/", $params);
|
||||||
|
|
||||||
return $this->handlePaginatedResponse($response, 'mandates');
|
return $this->handlePaginatedResponse($response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -729,7 +726,7 @@ class Client
|
||||||
|
|
||||||
$response = $this->httpClient->get("{$this->baseUrl}/refunds/", $params);
|
$response = $this->httpClient->get("{$this->baseUrl}/refunds/", $params);
|
||||||
|
|
||||||
return $this->handlePaginatedResponse($response, 'refunds');
|
return $this->handlePaginatedResponse($response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -766,7 +763,7 @@ class Client
|
||||||
|
|
||||||
$response = $this->httpClient->get("{$this->baseUrl}/events/", $params);
|
$response = $this->httpClient->get("{$this->baseUrl}/events/", $params);
|
||||||
|
|
||||||
return $this->handlePaginatedResponse($response, 'events');
|
return $this->handlePaginatedResponse($response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -793,7 +790,7 @@ class Client
|
||||||
|
|
||||||
$response = $this->httpClient->get("{$this->baseUrl}/webhooks/", $params);
|
$response = $this->httpClient->get("{$this->baseUrl}/webhooks/", $params);
|
||||||
|
|
||||||
return $this->handlePaginatedResponse($response, 'webhooks');
|
return $this->handlePaginatedResponse($response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -841,20 +838,16 @@ class Client
|
||||||
/**
|
/**
|
||||||
* Handle paginated response
|
* Handle paginated response
|
||||||
*/
|
*/
|
||||||
private function handlePaginatedResponse(Response $response, string $dataKey): Collection
|
private function handlePaginatedResponse(Response $response): Collection
|
||||||
{
|
{
|
||||||
if (!$response->successful()) {
|
if (!$response->successful()) {
|
||||||
$this->logError('Paginated request failed', $response);
|
$this->logError('Paginated request failed', $response);
|
||||||
return collect();
|
return collect();
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = $response->json();
|
$data = $response->json()['results'];
|
||||||
|
|
||||||
if (!isset($data[$dataKey])) {
|
return collect($data);
|
||||||
return collect();
|
|
||||||
}
|
|
||||||
|
|
||||||
return collect($data[$dataKey]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -875,7 +868,8 @@ class Client
|
||||||
*/
|
*/
|
||||||
private function logError(string $message, Response $response): void
|
private function logError(string $message, Response $response): void
|
||||||
{
|
{
|
||||||
Log::error($message, [
|
nlog([
|
||||||
|
'message' => $message,
|
||||||
'status' => $response->status(),
|
'status' => $response->status(),
|
||||||
'body' => $response->body(),
|
'body' => $response->body(),
|
||||||
'headers' => $response->headers()
|
'headers' => $response->headers()
|
||||||
|
|
@ -177,6 +177,21 @@ class Nordigen
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function validAgreement($institution_id, $_accounts)
|
||||||
|
{
|
||||||
|
|
||||||
|
$nc = new \App\Helpers\Bank\Nordigen\Http\NordigenClient($this->client->getAccessToken());
|
||||||
|
$requisitions = $nc->getAllRequisitions();
|
||||||
|
|
||||||
|
$requisitions->filter(function($requisition) use ($institution_id, $_accounts){
|
||||||
|
if($requisition['institution_id'] == $institution_id && !empty(array_intersect($requisition['accounts'], $_accounts))){
|
||||||
|
return $requisition;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public function getRequisition(string $requisitionId)
|
public function getRequisition(string $requisitionId)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
|
@ -196,11 +211,30 @@ class Nordigen
|
||||||
try {
|
try {
|
||||||
$out = new \stdClass();
|
$out = new \stdClass();
|
||||||
|
|
||||||
$out->data = $this->client->account($account_id)->getAccountDetails()['account'];
|
|
||||||
$out->metadata = $this->client->account($account_id)->getAccountMetaData();
|
$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']);
|
$out->institution = $this->client->institution->getInstitution($out->metadata['institution_id']);
|
||||||
|
|
||||||
|
if($out->metadata['status'] == 'READY'){
|
||||||
|
$out->data = $this->client->account($account_id)->getAccountDetails()['account'];
|
||||||
|
$out->balances = $this->client->account($account_id)->getAccountBalances()['balances'];
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
|
||||||
|
$out->data = [
|
||||||
|
'iban' => $out->metadata['iban'],
|
||||||
|
'ownerName' => $out->metadata['owner_name'],
|
||||||
|
];
|
||||||
|
$out->balances = [
|
||||||
|
[
|
||||||
|
'balanceType' => '',
|
||||||
|
'balanceAmount' => [
|
||||||
|
'amount' => 0,
|
||||||
|
'currency' => '',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
$it = new AccountTransformer();
|
$it = new AccountTransformer();
|
||||||
return $it->transform($out);
|
return $it->transform($out);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -139,7 +139,7 @@ class TransactionTransformer implements BankRevenueInterface
|
||||||
(array_key_exists('creditorName', $transaction) ?
|
(array_key_exists('creditorName', $transaction) ?
|
||||||
$transaction['creditorName'] : null);
|
$transaction['creditorName'] : null);
|
||||||
|
|
||||||
return [
|
$data = [
|
||||||
'transaction_id' => 0,
|
'transaction_id' => 0,
|
||||||
'nordigen_transaction_id' => $transactionId,
|
'nordigen_transaction_id' => $transactionId,
|
||||||
'amount' => abs($amount),
|
'amount' => abs($amount),
|
||||||
|
|
@ -153,8 +153,16 @@ class TransactionTransformer implements BankRevenueInterface
|
||||||
'base_type' => $base_type,
|
'base_type' => $base_type,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// $data['currency_code'] = $this->makeHash($data);
|
||||||
|
|
||||||
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// private function makeHash($data)
|
||||||
|
// {
|
||||||
|
// return hash('sha1', $data['amount'].$data['date'].$data['description'].$data['participant'].$data['participant_name'].$data['base_type']);
|
||||||
|
// }
|
||||||
|
|
||||||
private function convertCurrency(string $code)
|
private function convertCurrency(string $code)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invoice Ninja (https://invoiceninja.com).
|
|
||||||
*
|
|
||||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2025. Invoice Ninja LLC (https://invoiceninja.com)
|
|
||||||
*
|
|
||||||
* @license https://www.elastic.co/licensing/elastic-license
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace App\Http\Controllers\Bank;
|
|
||||||
|
|
||||||
use App\Helpers\Bank\Nordigen\Nordigen;
|
|
||||||
use App\Http\Controllers\BaseController;
|
|
||||||
use App\Http\Requests\Nordigen\ConfirmNordigenBankIntegrationRequest;
|
|
||||||
use App\Http\Requests\Nordigen\ConnectNordigenBankIntegrationRequest;
|
|
||||||
use App\Jobs\Bank\ProcessBankTransactionsNordigen;
|
|
||||||
use App\Models\BankIntegration;
|
|
||||||
use App\Models\Company;
|
|
||||||
use App\Utils\Ninja;
|
|
||||||
use Cache;
|
|
||||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
|
||||||
use Illuminate\Contracts\View\View;
|
|
||||||
use Illuminate\Http\JsonResponse;
|
|
||||||
use Illuminate\Http\RedirectResponse;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Nordigen\NordigenPHP\Exceptions\NordigenExceptions\NordigenException;
|
|
||||||
|
|
||||||
class NordigenController extends BaseController
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Handles the initial bank connection flow
|
|
||||||
*/
|
|
||||||
public function connect(ConnectNordigenBankIntegrationRequest $request): View|RedirectResponse
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles reconnects confirm / requisition updates
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function confirm(ConfirmNordigenBankIntegrationRequest $request): View|RedirectResponse
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the list of available banking institutions from Nordigen
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function institutions(Request $request): JsonResponse
|
|
||||||
{
|
|
||||||
if (!(config('ninja.nordigen.secret_id') && config('ninja.nordigen.secret_key'))) {
|
|
||||||
return response()->json(['message' => 'Not yet authenticated with Nordigen Bank Integration service'], 400);
|
|
||||||
}
|
|
||||||
|
|
||||||
$nordigen = new Nordigen();
|
|
||||||
|
|
||||||
return response()->json($nordigen->getInstitutions());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -46,6 +46,10 @@ class ConnectNordigenBankIntegrationRequest extends Request
|
||||||
$input['institution_id'] = $context['institution_id'];
|
$input['institution_id'] = $context['institution_id'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(isset($context['bank_account_id'])){
|
||||||
|
$input['bank_account_id'] = $context['bank_account_id'];
|
||||||
|
}
|
||||||
|
|
||||||
$input['redirect'] = ($context['is_react'] ?? false)
|
$input['redirect'] = ($context['is_react'] ?? false)
|
||||||
? config('ninja.react_url') . '/#/settings/bank_accounts'
|
? config('ninja.react_url') . '/#/settings/bank_accounts'
|
||||||
: config('ninja.app_url');
|
: config('ninja.app_url');
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,8 @@ class BankTransaction extends BaseModel
|
||||||
'vendor_id',
|
'vendor_id',
|
||||||
'amount',
|
'amount',
|
||||||
'participant',
|
'participant',
|
||||||
'participant_name'
|
'participant_name',
|
||||||
|
'currency_code'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue