107 lines
3.6 KiB
PHP
107 lines
3.6 KiB
PHP
<?php
|
|
|
|
namespace App\Enums;
|
|
|
|
use App\Services\Banking\CredentialField;
|
|
|
|
enum BankingProvider: string
|
|
{
|
|
case IndexaCapital = 'indexacapital';
|
|
case Binance = 'binance';
|
|
case Bitpanda = 'bitpanda';
|
|
case Coinbase = 'coinbase';
|
|
case InteractiveBrokers = 'interactivebrokers';
|
|
case Wise = 'wise';
|
|
case EnableBanking = 'enablebanking';
|
|
|
|
/**
|
|
* Whether the provider authenticates with user-supplied API keys
|
|
* rather than EnableBanking's hosted OAuth flow.
|
|
*/
|
|
public function usesApiKey(): bool
|
|
{
|
|
return $this !== self::EnableBanking;
|
|
}
|
|
|
|
/**
|
|
* The account type that this provider's pending accounts default to.
|
|
*/
|
|
public function defaultAccountType(): AccountType
|
|
{
|
|
return match ($this) {
|
|
self::IndexaCapital, self::Binance, self::Bitpanda, self::Coinbase, self::InteractiveBrokers => AccountType::Investment,
|
|
self::Wise, self::EnableBanking => AccountType::Checking,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* The credential inputs this provider collects, each mapped to the
|
|
* encrypted connection column it is stored in, with its validation rules.
|
|
*
|
|
* Single source of truth for credential shape: the connect controllers,
|
|
* the update request and the update controller all derive from this so a
|
|
* new provider is described in exactly one place. Empty for consent-based
|
|
* providers that authenticate without user-supplied credentials.
|
|
*
|
|
* @return array<int, CredentialField>
|
|
*/
|
|
public function credentialFields(): array
|
|
{
|
|
return match ($this) {
|
|
self::IndexaCapital, self::Wise => [
|
|
new CredentialField('api_token', 'api_token', ['required', 'string', 'min:10']),
|
|
],
|
|
self::Binance => [
|
|
new CredentialField('api_key', 'api_token', ['required', 'string', 'min:10']),
|
|
new CredentialField('api_secret', 'api_secret', ['required', 'string', 'min:10']),
|
|
],
|
|
self::Bitpanda => [
|
|
new CredentialField('api_key', 'api_token', ['required', 'string', 'min:10']),
|
|
],
|
|
self::Coinbase => [
|
|
new CredentialField('api_key_name', 'api_token', ['required', 'string', 'regex:/^(organizations\/[a-z0-9-]+\/apiKeys\/[a-z0-9-]+|[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})$/i']),
|
|
new CredentialField('private_key', 'api_secret', ['required', 'string', 'min:40']),
|
|
],
|
|
self::InteractiveBrokers => [
|
|
new CredentialField('token', 'api_token', ['required', 'string', 'min:10']),
|
|
new CredentialField('query_id', 'api_secret', ['required', 'string', 'min:3']),
|
|
],
|
|
self::EnableBanking => [],
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Validation rules for this provider's credential inputs, keyed by input
|
|
* name. Shared by the connect Form Requests and the update request.
|
|
*
|
|
* @return array<string, array<int, mixed>>
|
|
*/
|
|
public function credentialRules(): array
|
|
{
|
|
$rules = [];
|
|
|
|
foreach ($this->credentialFields() as $field) {
|
|
$rules[$field->input] = $field->rules;
|
|
}
|
|
|
|
return $rules;
|
|
}
|
|
|
|
/**
|
|
* Map validated request input to the encrypted connection columns.
|
|
*
|
|
* @param array<string, mixed> $input
|
|
* @return array<string, mixed>
|
|
*/
|
|
public function credentialColumns(array $input): array
|
|
{
|
|
$columns = [];
|
|
|
|
foreach ($this->credentialFields() as $field) {
|
|
$columns[$field->column] = $input[$field->input];
|
|
}
|
|
|
|
return $columns;
|
|
}
|
|
}
|