forked from apoloz/alfa-bank-sdk
fix(formating)
This commit is contained in:
@@ -59,9 +59,8 @@ try {
|
||||
echo "Beneficiary Request Sent (Mock).\n";
|
||||
|
||||
} catch (\Exception $e) {
|
||||
echo "Error: " . $e->getMessage() . "\n";
|
||||
echo 'Error: ' . $e->getMessage() . "\n";
|
||||
if ($e instanceof \Apoloz\AlfaBank\Exceptions\AlfaBankException) {
|
||||
echo "API Code: " . $e->getErrorCode() . "\n";
|
||||
echo 'API Code: ' . $e->getErrorCode() . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@ require_once __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
use Apoloz\AlfaBank\AlfaBank;
|
||||
use Apoloz\AlfaBank\Enums\Environment;
|
||||
use Apoloz\AlfaBank\Sbp\Requests\GetQrCodeRequest;
|
||||
use Apoloz\AlfaBank\Sbp\Data\QrCodeRequestData;
|
||||
use Apoloz\AlfaBank\Sbp\Requests\GetQrCodeRequest;
|
||||
|
||||
// 1. Initialize SBP
|
||||
$sbp = AlfaBank::sbp(
|
||||
@@ -30,8 +30,8 @@ try {
|
||||
|
||||
if ($response->successful()) {
|
||||
$qrData = $response->dto();
|
||||
echo "QR Payload: " . $qrData->payload . "\n";
|
||||
echo "QR Image URL: " . $qrData->image . "\n";
|
||||
echo 'QR Payload: ' . $qrData->payload . "\n";
|
||||
echo 'QR Image URL: ' . $qrData->image . "\n";
|
||||
} else {
|
||||
echo "Failed to generate QR.\n";
|
||||
}
|
||||
@@ -41,5 +41,5 @@ try {
|
||||
// foreach($paginator as $item) { ... }
|
||||
|
||||
} catch (\Exception $e) {
|
||||
echo "Error: " . $e->getMessage() . "\n";
|
||||
echo 'Error: ' . $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@ $baas = AlfaBank::baas(
|
||||
|
||||
echo "BaaS Connector Initialized.\n";
|
||||
|
||||
|
||||
// --- 2. SBP (Faster Payments) Initialization ---
|
||||
$sbp = AlfaBank::sbp(
|
||||
// SBP usually uses its own mTLS pair found in the sbp_payout/mtls folder
|
||||
@@ -52,4 +51,3 @@ $sbp = AlfaBank::sbp(
|
||||
echo "SBP Connector Initialized.\n";
|
||||
|
||||
// Now you can use $baas->login(...) or $sbp->send(...)
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
use Apoloz\AlfaBank\AlfaBank;
|
||||
use Apoloz\AlfaBank\Data\NominalAccounts\Beneficiaries\AddressData;
|
||||
use Apoloz\AlfaBank\Data\NominalAccounts\Beneficiaries\CreateBeneficiaryRequestData;
|
||||
use Apoloz\AlfaBank\Enums\Environment;
|
||||
use Apoloz\AlfaBank\Requests\NominalAccounts\Beneficiaries\CreateBeneficiaryRequest;
|
||||
use Apoloz\AlfaBank\Data\NominalAccounts\Beneficiaries\CreateBeneficiaryRequestData;
|
||||
use Apoloz\AlfaBank\Data\NominalAccounts\Beneficiaries\AddressData;
|
||||
use Spatie\LaravelData\DataCollection;
|
||||
|
||||
// 1. Initialize
|
||||
@@ -29,7 +29,7 @@ $payload = new CreateBeneficiaryRequestData(
|
||||
countryOfTaxResidence: 'RU',
|
||||
name: 'Ivanov Ivan',
|
||||
addresses: new DataCollection(AddressData::class, [
|
||||
new AddressData('REGISTRATION_ADDRESS', 'Moscow', 'RU')
|
||||
new AddressData('REGISTRATION_ADDRESS', 'Moscow', 'RU'),
|
||||
])
|
||||
// Note: digestSignatures is now optional!
|
||||
);
|
||||
@@ -40,12 +40,12 @@ $payload->sign($baas->getSigner());
|
||||
// 5. Send
|
||||
$response = $baas->send(new CreateBeneficiaryRequest($payload));
|
||||
|
||||
echo "Status: " . $response->status() . "\n";
|
||||
echo "ID: " . $response->dto()->id . "\n";
|
||||
echo 'Status: ' . $response->status() . "\n";
|
||||
echo 'ID: ' . $response->dto()->id . "\n";
|
||||
|
||||
if ($response->successful()) {
|
||||
$data = $response->dto(); // BeneficiaryResponseData
|
||||
echo "Beneficiary creation accepted. ID: {$data->id}, Status: {$data->status}\n";
|
||||
} else {
|
||||
echo "Error: " . $response->body() . "\n";
|
||||
echo 'Error: ' . $response->body() . "\n";
|
||||
}
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
use Apoloz\AlfaBank\AlfaBank;
|
||||
use Apoloz\AlfaBank\Webhooks\WebhookFactory;
|
||||
use Apoloz\AlfaBank\Requests\Webhooks\GetWebhooksRequest;
|
||||
use Apoloz\AlfaBank\Requests\Webhooks\CreateWebhookRequest;
|
||||
use Apoloz\AlfaBank\Data\Webhooks\Subscriptions\WebhookSubscriptionRequestData;
|
||||
use Apoloz\AlfaBank\Requests\Webhooks\CreateWebhookRequest;
|
||||
use Apoloz\AlfaBank\Requests\Webhooks\GetWebhooksRequest;
|
||||
use Apoloz\AlfaBank\Webhooks\WebhookFactory;
|
||||
|
||||
/**
|
||||
* 1. Managing Webhooks (BaaS API)
|
||||
@@ -15,7 +15,7 @@ $baas = AlfaBank::baas('cert.pem', 'key.pem');
|
||||
$baas->login('id', 'secret');
|
||||
|
||||
// List existing webhooks
|
||||
$response = $baas->send(new GetWebhooksRequest());
|
||||
$response = $baas->send(new GetWebhooksRequest);
|
||||
$webhooks = $response->dto(); // DataCollection of WebhookSubscriptionData
|
||||
|
||||
foreach ($webhooks as $webhook) {
|
||||
@@ -38,9 +38,9 @@ $rawPayload = [
|
||||
'transactionId' => 'TX-12345',
|
||||
'amount' => ['amount' => 100.50, 'currencyName' => 'RUR'],
|
||||
'direction' => 'CREDIT',
|
||||
'paymentPurpose' => 'Test payment'
|
||||
]
|
||||
]
|
||||
'paymentPurpose' => 'Test payment',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
// Use the factory to parse the payload into a DTO
|
||||
|
||||
@@ -3,16 +3,15 @@
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
use Apoloz\AlfaBank\AlfaBank;
|
||||
use Apoloz\AlfaBank\Requests\B2C\CreateB2CPaymentRequest;
|
||||
use Apoloz\AlfaBank\Data\B2C\B2CPaymentRequestData;
|
||||
use Apoloz\AlfaBank\Data\B2C\B2CClientData;
|
||||
use Apoloz\AlfaBank\Data\B2C\B2CPaymentRecipientData;
|
||||
use Apoloz\AlfaBank\Data\B2C\B2CPaymentRequestData;
|
||||
use Apoloz\AlfaBank\Requests\B2C\CreateB2CPaymentRequest;
|
||||
use Spatie\LaravelData\DataCollection;
|
||||
|
||||
/**
|
||||
* Example: B2C Payout via SBP (Phone Number).
|
||||
*/
|
||||
|
||||
$baas = AlfaBank::baas(
|
||||
certificatePath: 'path/to/cert.pem',
|
||||
privateKeyPath: 'path/to/key.pem'
|
||||
@@ -29,8 +28,8 @@ $payload = new B2CPaymentRequestData(
|
||||
'phone' => '79001112233',
|
||||
'amount' => 100.00,
|
||||
'nspkBankId' => '100000000001',
|
||||
'sequence' => 'unique-payout-id-1'
|
||||
]
|
||||
'sequence' => 'unique-payout-id-1',
|
||||
],
|
||||
], DataCollection::class)
|
||||
);
|
||||
|
||||
@@ -41,6 +40,5 @@ if ($response->successful()) {
|
||||
$data = $response->dto(); // B2CPaymentResponseData
|
||||
echo "Payout request sent. Status: {$data->status}\n";
|
||||
} else {
|
||||
echo "Error: " . $response->body() . "\n";
|
||||
echo 'Error: ' . $response->body() . "\n";
|
||||
}
|
||||
|
||||
|
||||
@@ -3,18 +3,17 @@
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
use Apoloz\AlfaBank\AlfaBank;
|
||||
use Apoloz\AlfaBank\Utils\CmsSigner;
|
||||
use Apoloz\AlfaBank\Requests\Registries\CreateRegistryRequest;
|
||||
use Apoloz\AlfaBank\Data\Registries\RegistryRequestData;
|
||||
use Apoloz\AlfaBank\Data\Registries\RegistryPaymentData;
|
||||
use Apoloz\AlfaBank\Requests\Registries\SignRegistryRequest;
|
||||
use Apoloz\AlfaBank\Data\Registries\RegistryRequestData;
|
||||
use Apoloz\AlfaBank\Data\Registries\RegistrySignatureData;
|
||||
use Apoloz\AlfaBank\Requests\Registries\CreateRegistryRequest;
|
||||
use Apoloz\AlfaBank\Requests\Registries\SignRegistryRequest;
|
||||
use Apoloz\AlfaBank\Utils\CmsSigner;
|
||||
use Spatie\LaravelData\DataCollection;
|
||||
|
||||
/**
|
||||
* Example: Creating and Signing a Payment Registry (Batch Payments).
|
||||
*/
|
||||
|
||||
$baas = AlfaBank::baas(
|
||||
certificatePath: 'path/to/cert.pem',
|
||||
privateKeyPath: 'path/to/key.pem'
|
||||
@@ -31,8 +30,8 @@ $payload = new RegistryRequestData(
|
||||
'payeeInn' => '770...',
|
||||
'payeeName' => 'Vendor 1',
|
||||
'payerAccount' => '40702...',
|
||||
'purpose' => 'Payment for goods'
|
||||
]
|
||||
'purpose' => 'Payment for goods',
|
||||
],
|
||||
], DataCollection::class)
|
||||
);
|
||||
|
||||
@@ -55,11 +54,10 @@ $signatures = RegistrySignatureData::collect([
|
||||
[
|
||||
'base64Encoded' => $signature,
|
||||
'signatureType' => 'RSA',
|
||||
'certificateUuid' => 'YOUR_CERT_UUID'
|
||||
]
|
||||
'certificateUuid' => 'YOUR_CERT_UUID',
|
||||
],
|
||||
], DataCollection::class);
|
||||
|
||||
$baas->send(new SignRegistryRequest($registryId, $signatures));
|
||||
|
||||
echo "Registry Signed.\n";
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ use Apoloz\AlfaBank\Data\NominalAccounts\Payouts\RecipientData;
|
||||
use Apoloz\AlfaBank\Requests\NominalAccounts\Beneficiaries\CreateBeneficiaryRequest;
|
||||
use Apoloz\AlfaBank\Requests\NominalAccounts\Beneficiaries\ScoreBeneficiaryRequest;
|
||||
use Apoloz\AlfaBank\Requests\NominalAccounts\Payouts\CreatePayoffRequest;
|
||||
use Apoloz\AlfaBank\Utils\CmsSigner;
|
||||
use Spatie\LaravelData\DataCollection;
|
||||
|
||||
/**
|
||||
@@ -50,7 +49,7 @@ try {
|
||||
countryOfTaxResidence: 'RU',
|
||||
name: 'Иванов Иван',
|
||||
addresses: AddressData::collect([
|
||||
new AddressData('REGISTRATION_ADDRESS', 'Moscow', 'RU')
|
||||
new AddressData('REGISTRATION_ADDRESS', 'Moscow', 'RU'),
|
||||
])
|
||||
);
|
||||
|
||||
@@ -63,14 +62,13 @@ try {
|
||||
|
||||
// --- ЭТАП 2: Идентификация Входящего Платежа ---
|
||||
// После создания банк должен проверить бенефициара
|
||||
echo "2. Запуск верификации (скоринга)...";
|
||||
echo '2. Запуск верификации (скоринга)...';
|
||||
$baas->send(new ScoreBeneficiaryRequest($beneficiaryId));
|
||||
echo "Скоринг инициирован.\n";
|
||||
|
||||
|
||||
// --- ЭТАП 3: Выплата (Payoff) ---
|
||||
// Когда бенефициар проверен, можно делать выплату
|
||||
echo "3. Создание выплаты...";
|
||||
echo '3. Создание выплаты...';
|
||||
|
||||
$payoffData = new PayoffRequestData(
|
||||
type: 'PAYMENT_ORDER',
|
||||
@@ -89,14 +87,14 @@ try {
|
||||
digestSignatures: DigestSignatureData::collect([
|
||||
[
|
||||
'base64Encoded' => '...', // Здесь должна быть подпись тела выплаты
|
||||
'signatureType' => 'cms'
|
||||
]
|
||||
'signatureType' => 'cms',
|
||||
],
|
||||
], DataCollection::class)
|
||||
);
|
||||
|
||||
$payoffResponse = $baas->send(new CreatePayoffRequest($payoffData));
|
||||
echo "Выплата создана. ID: " . $payoffResponse->dto()->payoffId . "\n";
|
||||
echo 'Выплата создана. ID: ' . $payoffResponse->dto()->payoffId . "\n";
|
||||
|
||||
} catch (\Exception $e) {
|
||||
echo "Ошибка: " . $e->getMessage() . "\n";
|
||||
echo 'Ошибка: ' . $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
@@ -5,15 +5,14 @@ declare(strict_types=1);
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
use Apoloz\AlfaBank\AlfaBank;
|
||||
use Apoloz\AlfaBank\Data\SelfEmployed\CreateIncomeRequestData;
|
||||
use Apoloz\AlfaBank\Enums\Environment;
|
||||
use Apoloz\AlfaBank\Requests\SelfEmployed\RegisterIncomeRequest;
|
||||
use Apoloz\AlfaBank\Data\SelfEmployed\CreateIncomeRequestData;
|
||||
|
||||
/**
|
||||
* Пример регистрации дохода самозанятого.
|
||||
* Позволяет автоматически задекларировать доход в ФНС от лица самозанятого.
|
||||
*/
|
||||
|
||||
$baas = AlfaBank::baas(
|
||||
certificatePath: __DIR__ . '/../tests/test_cert.pem',
|
||||
privateKeyPath: __DIR__ . '/../tests/test_key.pem',
|
||||
@@ -37,6 +36,5 @@ try {
|
||||
echo "ID запроса: {$dto->requestId}\n";
|
||||
echo "Текущий статус: {$dto->status}\n";
|
||||
} catch (\Exception $e) {
|
||||
echo "Ошибка: " . $e->getMessage() . "\n";
|
||||
echo 'Ошибка: ' . $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ use Apoloz\AlfaBank\Sbp\Requests\Reversal\GetQrcReversalHistoryRequest;
|
||||
* Пример получения истории возвратов по транзакции СБП.
|
||||
* Полезно для отладки частичных возвратов или поиска зависших операций.
|
||||
*/
|
||||
|
||||
$sbp = AlfaBank::sbp(
|
||||
certificatePath: __DIR__ . '/../tests/test_cert.pem',
|
||||
privateKeyPath: __DIR__ . '/../tests/test_key.pem',
|
||||
@@ -27,7 +26,7 @@ try {
|
||||
$response = $sbp->send(new GetQrcReversalHistoryRequest($payrrn, $termNo));
|
||||
$dto = $response->dto();
|
||||
|
||||
echo "Найдено возвратов: " . ($dto->refunds ? $dto->refunds->count() : 0) . "\n";
|
||||
echo 'Найдено возвратов: ' . ($dto->refunds ? $dto->refunds->count() : 0) . "\n";
|
||||
|
||||
if ($dto->refunds) {
|
||||
foreach ($dto->refunds as $refund) {
|
||||
@@ -38,6 +37,5 @@ try {
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
echo "Ошибка: " . $e->getMessage() . "\n";
|
||||
echo 'Ошибка: ' . $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ use Apoloz\AlfaBank\Requests\Files\UploadFileRequest;
|
||||
* Сначала создается бенефициар, банк возвращает ссылку для загрузки паспорта.
|
||||
* Затем SDK загружает файл по этой ссылке.
|
||||
*/
|
||||
|
||||
$baas = AlfaBank::baas(
|
||||
certificatePath: __DIR__ . '/../tests/test_cert.pem',
|
||||
privateKeyPath: __DIR__ . '/../tests/test_key.pem',
|
||||
@@ -34,13 +33,12 @@ try {
|
||||
if ($response->status() === 200) {
|
||||
echo "Файл успешно загружен в банк!\n";
|
||||
} else {
|
||||
echo "Ошибка загрузки: " . $response->body() . "\n";
|
||||
echo 'Ошибка загрузки: ' . $response->body() . "\n";
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
echo "Ошибка: " . $e->getMessage() . "\n";
|
||||
echo 'Ошибка: ' . $e->getMessage() . "\n";
|
||||
} finally {
|
||||
if (is_resource($fileResource)) {
|
||||
fclose($fileResource);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ $config = [
|
||||
|
||||
// BUSINESS DATA:
|
||||
// From your Contract or Internet Bank. Not related to Auth directly.
|
||||
'account_number' => '40702810...'
|
||||
'account_number' => '40702810...',
|
||||
];
|
||||
|
||||
// 2. Инициализация коннектора
|
||||
@@ -56,7 +56,7 @@ try {
|
||||
$tokenData = $baas->authWithCode($authCode, $config['redirect_uri']);
|
||||
|
||||
echo "Access Token получен!\n";
|
||||
echo "Refresh Token: " . $tokenData->refresh_token . "\n";
|
||||
echo 'Refresh Token: ' . $tokenData->refresh_token . "\n";
|
||||
echo "(Сохраните refresh_token в базу данных)\n\n";
|
||||
}
|
||||
|
||||
@@ -67,9 +67,9 @@ try {
|
||||
echo "Обновляем сессию по Refresh Token...\n";
|
||||
$tokenData = $baas->refreshToken($savedRefreshToken);
|
||||
|
||||
echo "Сессия обновлена. Новый Access Token действует " . $tokenData->expires_in . " сек.\n";
|
||||
echo 'Сессия обновлена. Новый Access Token действует ' . $tokenData->expires_in . " сек.\n";
|
||||
if ($tokenData->refresh_token) {
|
||||
echo "Пришел новый Refresh Token (сохраните его): " . $tokenData->refresh_token . "\n";
|
||||
echo 'Пришел новый Refresh Token (сохраните его): ' . $tokenData->refresh_token . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,12 +82,11 @@ try {
|
||||
type: 'FL_RESIDENT'
|
||||
));
|
||||
|
||||
echo "Успешно! Найдено: " . count($response->dto()->beneficiaries) . "\n";
|
||||
echo 'Успешно! Найдено: ' . count($response->dto()->beneficiaries) . "\n";
|
||||
|
||||
} catch (\Exception $e) {
|
||||
echo "Ошибка: " . $e->getMessage() . "\n";
|
||||
echo 'Ошибка: ' . $e->getMessage() . "\n";
|
||||
if (method_exists($e, 'getResponse')) {
|
||||
echo "Body: " . $e->getResponse()->body() . "\n";
|
||||
echo 'Body: ' . $e->getResponse()->body() . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@ $baas = AlfaBank::baas(
|
||||
$link = $baas->getAuthorizationUrl(scopes: ['beneficiaries', 'payment']);
|
||||
echo "1. Перейдите по ссылке для авторизации:\n$link\n\n";
|
||||
|
||||
|
||||
// --- СЦЕНАРИЙ 2: Обмен кода на токен (в callback-скрипте) ---
|
||||
// $code приходит в GET-параметре: /callback?code=...
|
||||
$codeFromUrl = '...код из браузера...';
|
||||
@@ -46,14 +45,14 @@ if ($codeFromUrl !== '...код из браузера...') {
|
||||
// Saloon делает всё сам:
|
||||
$authenticator = $baas->getAccessToken($codeFromUrl);
|
||||
|
||||
echo "Access Token: " . substr($authenticator->getAccessToken(), 0, 20) . "...\n";
|
||||
echo "Refresh Token: " . $authenticator->getRefreshToken() . "\n";
|
||||
echo "Expires At: " . $authenticator->getExpiresAt()->format('Y-m-d H:i:s') . "\n";
|
||||
echo 'Access Token: ' . substr($authenticator->getAccessToken(), 0, 20) . "...\n";
|
||||
echo 'Refresh Token: ' . $authenticator->getRefreshToken() . "\n";
|
||||
echo 'Expires At: ' . $authenticator->getExpiresAt()->format('Y-m-d H:i:s') . "\n";
|
||||
|
||||
// TODO: Сохраните refresh_token в базу данных!
|
||||
|
||||
} catch (\Exception $e) {
|
||||
echo "Ошибка обмена кода: " . $e->getMessage() . "\n";
|
||||
echo 'Ошибка обмена кода: ' . $e->getMessage() . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +77,6 @@ if ($savedRefreshToken !== '...saved_refresh_token...') {
|
||||
echo "Новый Refresh Token получен.\n";
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
echo "Ошибка обновления токена: " . $e->getMessage() . "\n";
|
||||
echo 'Ошибка обновления токена: ' . $e->getMessage() . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@ declare(strict_types=1);
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
use Apoloz\AlfaBank\AlfaBank;
|
||||
use Apoloz\AlfaBank\Requests\Auth\RefreshClientSecretRequest;
|
||||
use Apoloz\AlfaBank\Enums\Environment;
|
||||
use Apoloz\AlfaBank\Requests\Auth\RefreshClientSecretRequest;
|
||||
|
||||
/**
|
||||
* UTILITY SCRIPT: Generate a Client Secret using your TLS certificates.
|
||||
@@ -45,16 +45,16 @@ try {
|
||||
echo "\n-------------------------------------------------------\n";
|
||||
echo "SUCCESS! New Client Secret Generated:\n";
|
||||
echo "-------------------------------------------------------\n";
|
||||
echo "Client ID: " . $data->clientId . "\n";
|
||||
echo "Client Secret: " . $data->clientSecret . "\n";
|
||||
echo 'Client ID: ' . $data->clientId . "\n";
|
||||
echo 'Client Secret: ' . $data->clientSecret . "\n";
|
||||
echo "-------------------------------------------------------\n";
|
||||
echo "IMPORTANT: Save this to your .env file immediately.\n";
|
||||
echo "It will not be shown again.\n";
|
||||
|
||||
} catch (\Exception $e) {
|
||||
echo "\nERROR: Could not generate secret.\n";
|
||||
echo "Message: " . $e->getMessage() . "\n";
|
||||
echo 'Message: ' . $e->getMessage() . "\n";
|
||||
if (method_exists($e, 'getResponse')) {
|
||||
echo "Response: " . $e->getResponse()->body() . "\n";
|
||||
echo 'Response: ' . $e->getResponse()->body() . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ $config = [
|
||||
|
||||
// BUSINESS DATA
|
||||
'account_num' => '40702810...', // Nominal Account Number
|
||||
'refresh_token' => 'saved_refresh_token_db' // Your stored token
|
||||
'refresh_token' => 'saved_refresh_token_db', // Your stored token
|
||||
];
|
||||
|
||||
try {
|
||||
@@ -63,12 +63,12 @@ try {
|
||||
|
||||
// 4. Handle Result
|
||||
$list = $response->dto();
|
||||
echo "Found " . count($list->beneficiaries) . " beneficiaries.\n";
|
||||
echo 'Found ' . count($list->beneficiaries) . " beneficiaries.\n";
|
||||
|
||||
foreach ($list->beneficiaries as $b) {
|
||||
echo "- {$b->name} (ID: {$b->beneficiaryId})\n";
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo "Error: " . $e->getMessage() . "\n";
|
||||
echo 'Error: ' . $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
@@ -5,9 +5,9 @@ declare(strict_types=1);
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
use Apoloz\AlfaBank\AlfaBank;
|
||||
use Apoloz\AlfaBank\Enums\Environment;
|
||||
use Apoloz\AlfaBank\Requests\Auth\RefreshClientSecretRequest;
|
||||
use Apoloz\AlfaBank\Requests\NominalAccounts\Beneficiaries\GetBeneficiariesRequest;
|
||||
use Apoloz\AlfaBank\Enums\Environment;
|
||||
|
||||
/**
|
||||
* FULLY AUTOMATED WORKFLOW
|
||||
@@ -46,7 +46,7 @@ try {
|
||||
$secretResponse = $baas->send(new RefreshClientSecretRequest($clientId));
|
||||
$tempSecret = $secretResponse->dto()->clientSecret;
|
||||
|
||||
echo " Secret acquired: " . substr($tempSecret, 0, 5) . "...\n";
|
||||
echo ' Secret acquired: ' . substr($tempSecret, 0, 5) . "...\n";
|
||||
|
||||
// 3. AUTHENTICATE OAUTH2
|
||||
// Now we use the fresh secret to get an access token.
|
||||
@@ -66,7 +66,7 @@ try {
|
||||
$authenticator = $baasReady->refreshAccessToken($savedRefreshToken);
|
||||
$baasReady->authenticate($authenticator);
|
||||
|
||||
echo " Session active. Access Token expires at " . $authenticator->getExpiresAt()->format('H:i:s') . "\n";
|
||||
echo ' Session active. Access Token expires at ' . $authenticator->getExpiresAt()->format('H:i:s') . "\n";
|
||||
|
||||
// Update DB if refresh token rotated
|
||||
if ($authenticator->getRefreshToken()) {
|
||||
@@ -79,11 +79,11 @@ try {
|
||||
|
||||
$response = $baasReady->send(new GetBeneficiariesRequest($accNum, 'FL_RESIDENT'));
|
||||
|
||||
echo " Success! Found " . count($response->dto()->beneficiaries) . " records.\n";
|
||||
echo ' Success! Found ' . count($response->dto()->beneficiaries) . " records.\n";
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo "CRITICAL ERROR: " . $e->getMessage() . "\n";
|
||||
echo 'CRITICAL ERROR: ' . $e->getMessage() . "\n";
|
||||
if (method_exists($e, 'getResponse')) {
|
||||
echo "Body: " . $e->getResponse()->body() . "\n";
|
||||
echo 'Body: ' . $e->getResponse()->body() . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,11 +12,11 @@
|
||||
*/
|
||||
|
||||
use Apoloz\AlfaBank\Core\AlfaBankConnector;
|
||||
use Apoloz\AlfaBank\Requests\NominalAccounts\Beneficiaries\ScoreBeneficiaryRequest;
|
||||
use Apoloz\AlfaBank\Data\NominalAccounts\Beneficiaries\AddressData;
|
||||
use Apoloz\AlfaBank\Data\NominalAccounts\Beneficiaries\CreateBeneficiaryRequestData;
|
||||
use Apoloz\AlfaBank\Data\NominalAccounts\Beneficiaries\ScoreBeneficiaryRequestData;
|
||||
use Apoloz\AlfaBank\Requests\NominalAccounts\Beneficiaries\CreateBeneficiaryRequest;
|
||||
use Apoloz\AlfaBank\Data\NominalAccounts\Beneficiaries\CreateBeneficiaryRequestData;
|
||||
use Apoloz\AlfaBank\Data\NominalAccounts\Beneficiaries\AddressData;
|
||||
use Apoloz\AlfaBank\Requests\NominalAccounts\Beneficiaries\ScoreBeneficiaryRequest;
|
||||
|
||||
// 1. Get Configured Connector
|
||||
// Laravel automatically injects config from config/alfa-bank.php
|
||||
@@ -41,16 +41,18 @@ try {
|
||||
$scoreResponse = $baas->send(new ScoreBeneficiaryRequest($scoreData));
|
||||
$scoreResult = $scoreResponse->dto(); // ScoreBeneficiaryResponseData
|
||||
|
||||
echo "Scoring Result: " . $scoreResult->result . "\n";
|
||||
echo "Description: " . $scoreResult->description . "\n";
|
||||
echo 'Scoring Result: ' . $scoreResult->result . "\n";
|
||||
echo 'Description: ' . $scoreResult->description . "\n";
|
||||
|
||||
if ($scoreResult->result !== 'SUCCESS') {
|
||||
echo "Stopping: Scoring failed.\n";
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
echo "Scoring Error: " . $e->getMessage() . "\n";
|
||||
echo 'Scoring Error: ' . $e->getMessage() . "\n";
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -69,7 +71,7 @@ $createData = new CreateBeneficiaryRequestData(
|
||||
type: 'REGISTRATION_ADDRESS',
|
||||
address: '123456, г. Москва, ул. Тверская, д. 1',
|
||||
country: 'RU'
|
||||
)
|
||||
),
|
||||
])
|
||||
);
|
||||
|
||||
@@ -83,14 +85,13 @@ try {
|
||||
$beneficiary = $createResponse->dto(); // CreateBeneficiaryResponseData
|
||||
|
||||
echo "SUCCESS! Beneficiary Created.\n";
|
||||
echo "ID: " . $beneficiary->id . "\n";
|
||||
echo "Status: " . $beneficiary->status . "\n";
|
||||
echo "Request ID: " . $beneficiary->requestId . "\n";
|
||||
echo 'ID: ' . $beneficiary->id . "\n";
|
||||
echo 'Status: ' . $beneficiary->status . "\n";
|
||||
echo 'Request ID: ' . $beneficiary->requestId . "\n";
|
||||
|
||||
} catch (\Exception $e) {
|
||||
echo "Creation Error: " . $e->getMessage() . "\n";
|
||||
echo 'Creation Error: ' . $e->getMessage() . "\n";
|
||||
if (method_exists($e, 'getResponse')) {
|
||||
echo "Response Body: " . $e->getResponse()->body() . "\n";
|
||||
echo 'Response Body: ' . $e->getResponse()->body() . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,12 +13,12 @@
|
||||
*/
|
||||
|
||||
use Apoloz\AlfaBank\Core\AlfaBankConnector;
|
||||
use Apoloz\AlfaBank\Requests\NominalAccounts\Beneficiaries\Requisites\CreateRequisiteRequest;
|
||||
use Apoloz\AlfaBank\Data\NominalAccounts\Beneficiaries\Requisites\CreateRequisiteRequestData;
|
||||
use Apoloz\AlfaBank\Requests\NominalAccounts\Payouts\PayoffRequest;
|
||||
use Apoloz\AlfaBank\Data\NominalAccounts\Payouts\PayoffRequestData;
|
||||
use Apoloz\AlfaBank\Data\Common\RecipientData;
|
||||
use Apoloz\AlfaBank\Data\NominalAccounts\Beneficiaries\Requisites\CreateRequisiteRequestData;
|
||||
use Apoloz\AlfaBank\Data\NominalAccounts\Payouts\PayoffRequestData;
|
||||
use Apoloz\AlfaBank\Data\NominalAccounts\Payouts\PayoutRequisiteData;
|
||||
use Apoloz\AlfaBank\Requests\NominalAccounts\Beneficiaries\Requisites\CreateRequisiteRequest;
|
||||
use Apoloz\AlfaBank\Requests\NominalAccounts\Payouts\PayoffRequest;
|
||||
use Apoloz\AlfaBank\Services\PhpseclibCardEncryptor;
|
||||
|
||||
// --- CONFIGURATION ---
|
||||
@@ -34,8 +34,8 @@ $baas->login();
|
||||
// ==========================================
|
||||
// STEP 1: SECURE REGISTRATION (Tokenization)
|
||||
// ==========================================
|
||||
echo "--- Step 1: Registering Card Requisite ---
|
||||
";
|
||||
echo '--- Step 1: Registering Card Requisite ---
|
||||
';
|
||||
|
||||
// A. Encrypt PAN for transport
|
||||
$encryptor = new PhpseclibCardEncryptor(file_get_contents($cardPubKeyPath));
|
||||
@@ -55,20 +55,20 @@ try {
|
||||
$reqResponse = $baas->send(new CreateRequisiteRequest($reqData));
|
||||
$requisiteId = $reqResponse->dto()->id; // E.g. "REQ-998877"
|
||||
|
||||
echo "SUCCESS! Card Registered.
|
||||
";
|
||||
echo 'SUCCESS! Card Registered.
|
||||
';
|
||||
echo "Requisite ID: $requisiteId (SAVE THIS TO DATABASE)
|
||||
";
|
||||
echo "Mask: " . substr($rawPan, 0, 6) . "******" . substr($rawPan, -4) . "
|
||||
";
|
||||
echo 'Mask: ' . substr($rawPan, 0, 6) . '******' . substr($rawPan, -4) . '
|
||||
';
|
||||
|
||||
} catch (\Exception $e) {
|
||||
echo "Registration Failed: " . $e->getMessage() . "
|
||||
";
|
||||
echo 'Registration Failed: ' . $e->getMessage() . '
|
||||
';
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// ==========================================
|
||||
// STEP 2: PAYOUT (Using Requisite ID)
|
||||
// ==========================================
|
||||
@@ -96,12 +96,12 @@ try {
|
||||
$payResponse = $baas->send(new PayoffRequest($payoutData));
|
||||
$result = $payResponse->dto();
|
||||
|
||||
echo "Payout Sent!
|
||||
";
|
||||
echo "ID: " . ($result->id ?? 'N/A') . "
|
||||
";
|
||||
echo 'Payout Sent!
|
||||
';
|
||||
echo 'ID: ' . ($result->id ?? 'N/A') . '
|
||||
';
|
||||
|
||||
} catch (\Exception $e) {
|
||||
echo "Payout Failed: " . $e->getMessage() . "
|
||||
";
|
||||
echo 'Payout Failed: ' . $e->getMessage() . '
|
||||
';
|
||||
}
|
||||
|
||||
@@ -16,17 +16,17 @@ declare(strict_types=1);
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
use Apoloz\AlfaBank\AlfaBank;
|
||||
use Apoloz\AlfaBank\Enums\Environment;
|
||||
use Apoloz\AlfaBank\Sbp\Data\QrCodeRequestData;
|
||||
use Apoloz\AlfaBank\Sbp\Requests\GetQrCodeRequest;
|
||||
use Apoloz\AlfaBank\Core\AlfaConfig;
|
||||
use Apoloz\AlfaBank\Sbp\SbpConnector;
|
||||
use Apoloz\AlfaBank\Data\NominalAccounts\Identification\AmountDistributionData;
|
||||
use Apoloz\AlfaBank\Data\NominalAccounts\Identification\IdentifyRequestData;
|
||||
use Apoloz\AlfaBank\Data\NominalAccounts\Payouts\DigestSignatureData;
|
||||
use Apoloz\AlfaBank\Enums\Environment;
|
||||
use Apoloz\AlfaBank\Requests\NominalAccounts\Identification\GetIdentifyStatusRequest;
|
||||
use Apoloz\AlfaBank\Requests\NominalAccounts\Identification\GetUnidentifiedTransactionsRequest;
|
||||
use Apoloz\AlfaBank\Requests\NominalAccounts\Identification\IdentifyTransactionRequest;
|
||||
use Apoloz\AlfaBank\Requests\NominalAccounts\Identification\GetIdentifyStatusRequest;
|
||||
use Apoloz\AlfaBank\Data\NominalAccounts\Identification\IdentifyRequestData;
|
||||
use Apoloz\AlfaBank\Data\NominalAccounts\Identification\AmountDistributionData;
|
||||
use Apoloz\AlfaBank\Data\NominalAccounts\Payouts\DigestSignatureData;
|
||||
use Apoloz\AlfaBank\Sbp\Data\QrCodeRequestData;
|
||||
use Apoloz\AlfaBank\Sbp\Requests\GetQrCodeRequest;
|
||||
use Apoloz\AlfaBank\Sbp\SbpConnector;
|
||||
use Spatie\LaravelData\DataCollection;
|
||||
|
||||
echo "=== SBP QR → Номинальный счёт → Идентификация ===\n\n";
|
||||
@@ -148,7 +148,7 @@ try {
|
||||
$unidentifiedResponse = $baas->send($unidentifiedRequest);
|
||||
$unidentifiedCollection = $unidentifiedResponse->dto();
|
||||
|
||||
echo "Найдено неидентифицированных пополнений: " . count($unidentifiedCollection->items) . "\n\n";
|
||||
echo 'Найдено неидентифицированных пополнений: ' . count($unidentifiedCollection->items) . "\n\n";
|
||||
|
||||
if (count($unidentifiedCollection->items) === 0) {
|
||||
echo "⚠️ Нет неидентифицированных пополнений. Возможные причины:\n";
|
||||
@@ -175,7 +175,7 @@ try {
|
||||
}
|
||||
|
||||
if ($targetTransaction === null) {
|
||||
throw new \RuntimeException("Не найдена подходящая транзакция для идентификации");
|
||||
throw new \RuntimeException('Не найдена подходящая транзакция для идентификации');
|
||||
}
|
||||
|
||||
echo "✅ Выбрана транзакция для идентификации: {$targetTransaction->id}\n";
|
||||
@@ -194,7 +194,7 @@ try {
|
||||
new AmountDistributionData(
|
||||
beneficiaryId: $beneficiaryId,
|
||||
amount: $targetTransaction->amount
|
||||
)
|
||||
),
|
||||
], AmountDistributionData::class);
|
||||
|
||||
// Подготавливаем данные для идентификации
|
||||
@@ -207,7 +207,7 @@ try {
|
||||
new DigestSignatureData(
|
||||
base64Encoded: 'base64-encoded-signature-here', // Реальная подпись
|
||||
signatureType: 'rsa'
|
||||
)
|
||||
),
|
||||
], DigestSignatureData::class)
|
||||
);
|
||||
|
||||
|
||||
@@ -12,16 +12,15 @@ declare(strict_types=1);
|
||||
|
||||
use Apoloz\AlfaBank\Core\AlfaBankConnector;
|
||||
use Apoloz\AlfaBank\Core\AlfaConfig;
|
||||
use Apoloz\AlfaBank\Data\NominalAccounts\Identification\AmountDistributionData;
|
||||
use Apoloz\AlfaBank\Data\NominalAccounts\Identification\IdentifyRequestData;
|
||||
use Apoloz\AlfaBank\Enums\Environment;
|
||||
use Apoloz\AlfaBank\Sbp\SbpConnector;
|
||||
use Apoloz\AlfaBank\Sbp\Data\QrCodeRequestData;
|
||||
use Apoloz\AlfaBank\Sbp\Requests\GetQrCodeRequest;
|
||||
use Apoloz\AlfaBank\Requests\NominalAccounts\Identification\GetIdentifyStatusRequest;
|
||||
use Apoloz\AlfaBank\Requests\NominalAccounts\Identification\GetUnidentifiedTransactionsRequest;
|
||||
use Apoloz\AlfaBank\Requests\NominalAccounts\Identification\IdentifyTransactionRequest;
|
||||
use Apoloz\AlfaBank\Requests\NominalAccounts\Identification\GetIdentifyStatusRequest;
|
||||
use Apoloz\AlfaBank\Data\NominalAccounts\Identification\IdentifyRequestData;
|
||||
use Apoloz\AlfaBank\Data\NominalAccounts\Identification\AmountDistributionData;
|
||||
use Apoloz\AlfaBank\Data\NominalAccounts\Payouts\DigestSignatureData;
|
||||
use Apoloz\AlfaBank\Sbp\Data\QrCodeRequestData;
|
||||
use Apoloz\AlfaBank\Sbp\Requests\GetQrCodeRequest;
|
||||
use Apoloz\AlfaBank\Sbp\SbpConnector;
|
||||
use Spatie\LaravelData\DataCollection;
|
||||
|
||||
echo "=== SBP QR → Номинальный счёт → Идентификация (Tinker) ===\n\n";
|
||||
@@ -35,7 +34,7 @@ $beneficiaryId = 'your-beneficiary-id-here'; // ID бенефициара (по
|
||||
$amount = '15000'; // 150.00 RUB в копейках
|
||||
|
||||
echo "Номинальный счёт: $nominalAccountNumber\n";
|
||||
echo "Сумма: " . number_format($amount / 100, 2) . " RUB\n\n";
|
||||
echo 'Сумма: ' . number_format($amount / 100, 2) . " RUB\n\n";
|
||||
|
||||
// =============================================================================
|
||||
// ШАГ 1: Генерация SBP QR
|
||||
@@ -74,6 +73,7 @@ try {
|
||||
|
||||
if ($qrData->ErrorCode !== 0) {
|
||||
echo "❌ Ошибка генерации QR: {$qrData->message}\n";
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -97,10 +97,11 @@ try {
|
||||
);
|
||||
|
||||
$transactions = $unidentifiedResponse->dto()->items;
|
||||
echo "Найдено транзакций: " . count($transactions) . "\n\n";
|
||||
echo 'Найдено транзакций: ' . count($transactions) . "\n\n";
|
||||
|
||||
if (count($transactions) === 0) {
|
||||
echo "⚠️ Нет неидентифицированных пополнений\n";
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -126,6 +127,7 @@ try {
|
||||
echo "⚠️ Укажите правильный beneficiaryId!\n";
|
||||
echo " Получите список бенефициаров через:\n";
|
||||
echo " >>> \$baas->send(new GetBeneficiariesRequest())->dto()\n";
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -136,7 +138,7 @@ try {
|
||||
new AmountDistributionData(
|
||||
beneficiaryId: $beneficiaryId,
|
||||
amount: $transaction->amount
|
||||
)
|
||||
),
|
||||
], AmountDistributionData::class)
|
||||
);
|
||||
|
||||
@@ -171,7 +173,7 @@ try {
|
||||
|
||||
} catch (\Exception $e) {
|
||||
echo "\n❌ Ошибка: {$e->getMessage()}\n";
|
||||
echo "Класс: " . get_class($e) . "\n";
|
||||
echo 'Класс: ' . get_class($e) . "\n";
|
||||
}
|
||||
|
||||
echo "\n=== Готово ===\n";
|
||||
|
||||
@@ -9,9 +9,9 @@ namespace Apoloz\AlfaBank;
|
||||
use Apoloz\AlfaBank\Core\AlfaBankConnector;
|
||||
use Apoloz\AlfaBank\Core\AlfaConfig;
|
||||
use Apoloz\AlfaBank\Enums\Environment;
|
||||
use Apoloz\AlfaBank\Services\OpenSslCmsSigner;
|
||||
use Apoloz\AlfaBank\Sbp\SbpConnector;
|
||||
use Apoloz\AlfaBank\Requests\Accounts\GetAccountsRequest;
|
||||
use Apoloz\AlfaBank\Sbp\SbpConnector;
|
||||
use Apoloz\AlfaBank\Services\OpenSslCmsSigner;
|
||||
|
||||
class AlfaBank
|
||||
{
|
||||
@@ -29,7 +29,8 @@ class AlfaBank
|
||||
): bool {
|
||||
$baas = self::baas($certificatePath, $privateKeyPath, $environment, $caBundlePath);
|
||||
$baas->login($clientId, $clientSecret);
|
||||
$baas->send(new GetAccountsRequest());
|
||||
$baas->send(new GetAccountsRequest);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace Apoloz\AlfaBank\Core;
|
||||
// <SECTION name="module_imports" intent="Import necessary contracts, services, and base framework components for the connector's operation.">
|
||||
// <BELIEF_STATE "Saloon's plugin architecture requires importing traits for features like retries and timeouts. Local contracts (SignerInterface) are imported for dependency injection.">
|
||||
use Apoloz\AlfaBank\Contracts\SignerInterface;
|
||||
use Apoloz\AlfaBank\Enums\Environment;
|
||||
use Apoloz\AlfaBank\Http\Middleware\RequestIdMiddleware;
|
||||
use Apoloz\AlfaBank\Http\Pagination\AlfaOffsetPaginator;
|
||||
use Apoloz\AlfaBank\Traits\HasAlfaErrorHandling;
|
||||
@@ -15,19 +16,18 @@ use Saloon\Http\Connector;
|
||||
use Saloon\Http\Request;
|
||||
use Saloon\PaginationPlugin\Contracts\HasPagination;
|
||||
use Saloon\PaginationPlugin\OffsetPaginator;
|
||||
use Saloon\Traits\Plugins\AlwaysThrowOnErrors;
|
||||
use Saloon\Traits\RequestProperties\HasTries;
|
||||
use Saloon\Traits\Plugins\HasTimeout;
|
||||
use Saloon\Traits\OAuth2\AuthorizationCodeGrant;
|
||||
use Apoloz\AlfaBank\Enums\Environment;
|
||||
use Saloon\Traits\Plugins\AlwaysThrowOnErrors;
|
||||
use Saloon\Traits\Plugins\HasTimeout;
|
||||
use Saloon\Traits\RequestProperties\HasTries;
|
||||
|
||||
class AlfaBankConnector extends Connector implements HasPagination
|
||||
{
|
||||
use AlwaysThrowOnErrors;
|
||||
use AuthorizationCodeGrant;
|
||||
use HasAlfaErrorHandling;
|
||||
use HasTimeout;
|
||||
use HasTries;
|
||||
use AlwaysThrowOnErrors;
|
||||
use HasAlfaErrorHandling;
|
||||
use AuthorizationCodeGrant;
|
||||
|
||||
public function __construct(
|
||||
protected AlfaConfig $alfaConfig,
|
||||
@@ -42,6 +42,79 @@ class AlfaBankConnector extends Connector implements HasPagination
|
||||
return $this->alfaConfig->baseUrl;
|
||||
}
|
||||
|
||||
public function boot(\Saloon\Http\PendingRequest $pendingRequest): void
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function paginate(Request $request): OffsetPaginator
|
||||
{
|
||||
return new AlfaOffsetPaginator($this, $request);
|
||||
}
|
||||
|
||||
// login() kept for ClientCredentials compatibility (legacy/simple flow)
|
||||
public function login(?string $clientId = null, ?string $clientSecret = null, array $scopes = []): static
|
||||
{
|
||||
$oauthConfig = $this->oauthConfig();
|
||||
|
||||
// Allow overriding credentials via method arguments
|
||||
if ($clientId) {
|
||||
$oauthConfig->setClientId($clientId);
|
||||
}
|
||||
if ($clientSecret) {
|
||||
$oauthConfig->setClientSecret($clientSecret);
|
||||
}
|
||||
|
||||
if (empty($oauthConfig->getClientId()) || empty($oauthConfig->getClientSecret())) {
|
||||
throw new \RuntimeException('Client ID/Secret not configured.');
|
||||
}
|
||||
|
||||
$request = new \Saloon\Http\OAuth2\GetClientCredentialsTokenRequest($oauthConfig, $scopes);
|
||||
|
||||
$response = $this->send($request);
|
||||
|
||||
// Use the trait's helper to parse the token
|
||||
$authenticator = $this->createOAuthAuthenticatorFromResponse($response);
|
||||
|
||||
$this->authenticate($authenticator);
|
||||
|
||||
return $this;
|
||||
}
|
||||
// </SECTION>
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="signer_accessor" intent="Provide access to the configured signing service for requests that require a digital signature.">
|
||||
// <BELIEF_STATE "Requests should not instantiate their own signing logic. The connector acts as a service locator, providing the globally-configured Signer service. This ensures that all signatures are generated consistently.">
|
||||
public function getSigner(): SignerInterface
|
||||
{
|
||||
if (! $this->signer) {
|
||||
throw new \RuntimeException('No signer configured for this connector.');
|
||||
}
|
||||
|
||||
return $this->signer;
|
||||
}
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="logging_mutator" intent="Allow attaching a PSR-3 logger to the connector for debugging.">
|
||||
// <BELIEF_STATE "Logging should be an optional, opt-in feature. This method provides a fluent interface to attach a logging middleware, which will automatically sanitize sensitive data before output.">
|
||||
public function withLogging(\Psr\Log\LoggerInterface $logger): static
|
||||
{
|
||||
$this->middleware()->onRequest(new \Apoloz\AlfaBank\Http\Middleware\LoggingRequestMiddleware($logger));
|
||||
$this->middleware()->onResponse(new \Apoloz\AlfaBank\Http\Middleware\LoggingResponseMiddleware($logger));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable automated JWS response verification and decoding.
|
||||
*/
|
||||
public function withJwsVerification(string $publicKeyPem): static
|
||||
{
|
||||
$this->middleware()->onResponse(new \Apoloz\AlfaBank\Http\Middleware\VerifyJwsResponseMiddleware($publicKeyPem));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function defaultOauthConfig(): OAuthConfig
|
||||
{
|
||||
$idUrl = $this->alfaConfig->baseUrl === Environment::PRODUCTION->value
|
||||
@@ -83,80 +156,8 @@ class AlfaBankConnector extends Connector implements HasPagination
|
||||
protected function defaultMiddleware(): array
|
||||
{
|
||||
return [
|
||||
new RequestIdMiddleware(),
|
||||
new RequestIdMiddleware,
|
||||
];
|
||||
}
|
||||
|
||||
public function boot(\Saloon\Http\PendingRequest $pendingRequest): void
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function paginate(Request $request): OffsetPaginator
|
||||
{
|
||||
return new AlfaOffsetPaginator($this, $request);
|
||||
}
|
||||
|
||||
// login() kept for ClientCredentials compatibility (legacy/simple flow)
|
||||
public function login(?string $clientId = null, ?string $clientSecret = null, array $scopes = []): static
|
||||
{
|
||||
$oauthConfig = $this->oauthConfig();
|
||||
|
||||
// Allow overriding credentials via method arguments
|
||||
if ($clientId) {
|
||||
$oauthConfig->setClientId($clientId);
|
||||
}
|
||||
if ($clientSecret) {
|
||||
$oauthConfig->setClientSecret($clientSecret);
|
||||
}
|
||||
|
||||
if (empty($oauthConfig->getClientId()) || empty($oauthConfig->getClientSecret())) {
|
||||
throw new \RuntimeException("Client ID/Secret not configured.");
|
||||
}
|
||||
|
||||
$request = new \Saloon\Http\OAuth2\GetClientCredentialsTokenRequest($oauthConfig, $scopes);
|
||||
|
||||
$response = $this->send($request);
|
||||
|
||||
// Use the trait's helper to parse the token
|
||||
$authenticator = $this->createOAuthAuthenticatorFromResponse($response);
|
||||
|
||||
$this->authenticate($authenticator);
|
||||
|
||||
return $this;
|
||||
}
|
||||
// </SECTION>
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="signer_accessor" intent="Provide access to the configured signing service for requests that require a digital signature.">
|
||||
// <BELIEF_STATE "Requests should not instantiate their own signing logic. The connector acts as a service locator, providing the globally-configured Signer service. This ensures that all signatures are generated consistently.">
|
||||
public function getSigner(): SignerInterface
|
||||
{
|
||||
if (!$this->signer) {
|
||||
throw new \RuntimeException("No signer configured for this connector.");
|
||||
}
|
||||
return $this->signer;
|
||||
}
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="logging_mutator" intent="Allow attaching a PSR-3 logger to the connector for debugging.">
|
||||
// <BELIEF_STATE "Logging should be an optional, opt-in feature. This method provides a fluent interface to attach a logging middleware, which will automatically sanitize sensitive data before output.">
|
||||
public function withLogging(\Psr\Log\LoggerInterface $logger): static
|
||||
{
|
||||
$this->middleware()->onRequest(new \Apoloz\AlfaBank\Http\Middleware\LoggingRequestMiddleware($logger));
|
||||
$this->middleware()->onResponse(new \Apoloz\AlfaBank\Http\Middleware\LoggingResponseMiddleware($logger));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable automated JWS response verification and decoding.
|
||||
*/
|
||||
public function withJwsVerification(string $publicKeyPem): static
|
||||
{
|
||||
$this->middleware()->onResponse(new \Apoloz\AlfaBank\Http\Middleware\VerifyJwsResponseMiddleware($publicKeyPem));
|
||||
|
||||
return $this;
|
||||
}
|
||||
// </SECTION>
|
||||
}
|
||||
@@ -14,6 +14,7 @@ namespace Apoloz\AlfaBank\Data\Auth;
|
||||
// <SECTION name="module_imports" intent="Import the base Spatie Laravel Data class.">
|
||||
// <BELIEF_STATE "Extending `Spatie\LaravelData\Data` enables automatic casting from JSON and provides other DTO benefits.">
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for OAuth 2.0 token responses.">
|
||||
|
||||
@@ -17,6 +17,7 @@ use Apoloz\AlfaBank\Data\PaginationData;
|
||||
use Spatie\LaravelData\Attributes\DataCollectionOf;
|
||||
use Spatie\LaravelData\Data;
|
||||
use Spatie\LaravelData\DataCollection;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for a collection of client consents.">
|
||||
|
||||
@@ -14,9 +14,10 @@ namespace Apoloz\AlfaBank\Data\Auth\UserInfo;
|
||||
// <SECTION name="module_imports" intent="Import necessary DTOs and Spatie Laravel Data components.">
|
||||
// <BELIEF_STATE "This DTO represents a single consent entry. The `PaginationData` import here is likely due to prior usage or template, but not directly used within this single DTO.">
|
||||
use Apoloz\AlfaBank\Data\PaginationData; // This import is likely extraneous for a single DTO, but kept for context consistency.
|
||||
use Spatie\LaravelData\Attributes\DataCollectionOf; // This is also likely extraneous for a single DTO.
|
||||
// This is also likely extraneous for a single DTO.
|
||||
use Spatie\LaravelData\Data;
|
||||
use Spatie\LaravelData\DataCollection; // This is also likely extraneous for a single DTO.
|
||||
|
||||
// This is also likely extraneous for a single DTO.
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for a single client consent.">
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Apoloz\AlfaBank\Data\Auth\UserInfo;
|
||||
// <SECTION name="module_imports" intent="Import the base Spatie Laravel Data class.">
|
||||
// <BELIEF_STATE "Extending `Spatie\LaravelData\Data` enables automatic casting from JSON and provides other DTO benefits.">
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for OpenID Connect UserInfo claims.">
|
||||
|
||||
@@ -4,9 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace Apoloz\AlfaBank\Data\B2C;
|
||||
|
||||
use Spatie\LaravelData\Attributes\DataCollectionOf;
|
||||
use Spatie\LaravelData\Data;
|
||||
use Spatie\LaravelData\DataCollection;
|
||||
|
||||
class B2CPaymentResponseData extends Data
|
||||
{
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace Apoloz\AlfaBank\Data\FileExchange;
|
||||
use Spatie\LaravelData\Attributes\DataCollectionOf;
|
||||
use Spatie\LaravelData\Data;
|
||||
use Spatie\LaravelData\DataCollection;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for file download response data.">
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Apoloz\AlfaBank\Data\FileExchange;
|
||||
// <SECTION name="module_imports" intent="Import the base Spatie Laravel Data class.">
|
||||
// <BELIEF_STATE "Extending `Spatie\LaravelData\Data` enables automatic casting from JSON and provides other DTO benefits.">
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for file link details.">
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace Apoloz\AlfaBank\Data\FileExchange;
|
||||
use Spatie\LaravelData\Attributes\DataCollectionOf;
|
||||
use Spatie\LaravelData\Data;
|
||||
use Spatie\LaravelData\DataCollection;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for file upload response data.">
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts\Beneficiaries;
|
||||
// <SECTION name="module_imports" intent="Import the base Spatie Laravel Data class.">
|
||||
// <BELIEF_STATE "Extending `Spatie\LaravelData\Data` enables automatic casting from JSON and provides other DTO benefits.">
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for address details.">
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts\Beneficiaries;
|
||||
use Spatie\LaravelData\Attributes\DataCollectionOf;
|
||||
use Spatie\LaravelData\Data;
|
||||
use Spatie\LaravelData\DataCollection;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for a beneficiary's balance details.">
|
||||
|
||||
@@ -17,6 +17,7 @@ use Apoloz\AlfaBank\Data\PaginationData;
|
||||
use Spatie\LaravelData\Attributes\DataCollectionOf;
|
||||
use Spatie\LaravelData\Data;
|
||||
use Spatie\LaravelData\DataCollection;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define the paginated collection for beneficiary transactions.">
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts\Beneficiaries;
|
||||
// <SECTION name="module_imports" intent="Import the base Spatie\LaravelData class.">
|
||||
// <BELIEF_STATE "This class extends `Spatie\LaravelData\Data` to leverage its robust data mapping and type safety, ensuring consistent and predictable handling of individual transaction payloads.">
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define the beneficiary transaction data structure.">
|
||||
|
||||
@@ -20,6 +20,7 @@ use Spatie\LaravelData\Attributes\Validation\Email;
|
||||
use Spatie\LaravelData\Attributes\Validation\Numeric;
|
||||
use Spatie\LaravelData\Data;
|
||||
use Spatie\LaravelData\DataCollection;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for creating a new beneficiary.">
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts\Beneficiaries;
|
||||
// <SECTION name="module_imports" intent="Import the base Spatie Laravel Data class.">
|
||||
// <BELIEF_STATE "Extending `Spatie\LaravelData\Data` enables automatic casting from JSON and provides other DTO benefits.">
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for the response of creating a beneficiary.">
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts\Beneficiaries;
|
||||
// <SECTION name="module_imports" intent="Import the base Spatie Laravel Data class.">
|
||||
// <BELIEF_STATE "Extending `Spatie\LaravelData\Data` enables automatic casting from JSON and provides other DTO benefits.">
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for an identification document.">
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts\Beneficiaries;
|
||||
// <SECTION name="module_imports" intent="Import the base Spatie Laravel Data class.">
|
||||
// <BELIEF_STATE "Extending `Spatie\LaravelData\Data` enables automatic casting from JSON and provides other DTO benefits.">
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for personal identification details.">
|
||||
|
||||
@@ -18,6 +18,7 @@ use Apoloz\AlfaBank\Traits\SignableData;
|
||||
use Spatie\LaravelData\Attributes\DataCollectionOf;
|
||||
use Spatie\LaravelData\Data;
|
||||
use Spatie\LaravelData\DataCollection;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for creating a new requisite.">
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts\Beneficiaries\Requisites;
|
||||
// <SECTION name="module_imports" intent="Import the base Spatie Laravel Data class.">
|
||||
// <BELIEF_STATE "Extending `Spatie\LaravelData\Data` enables automatic casting from JSON and provides other DTO benefits.">
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for a single payment requisite.">
|
||||
|
||||
@@ -16,9 +16,9 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts\Beneficiaries\Requisites;
|
||||
use Apoloz\AlfaBank\Data\NominalAccounts\Payouts\DigestSignatureData;
|
||||
use Apoloz\AlfaBank\Traits\SignableData;
|
||||
use Spatie\LaravelData\Attributes\DataCollectionOf;
|
||||
use Spatie\LaravelData\Attributes\Validation\Numeric;
|
||||
use Spatie\LaravelData\Data;
|
||||
use Spatie\LaravelData\DataCollection;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for updating an existing requisite.">
|
||||
|
||||
@@ -20,6 +20,7 @@ use Spatie\LaravelData\Attributes\Validation\Email;
|
||||
use Spatie\LaravelData\Attributes\Validation\Numeric;
|
||||
use Spatie\LaravelData\Data;
|
||||
use Spatie\LaravelData\DataCollection;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for updating an existing beneficiary.">
|
||||
@@ -39,3 +40,23 @@ class UpdateBeneficiaryRequestData extends Data
|
||||
public ?DataCollection $addresses = null,
|
||||
public ?string $accountNumber = null,
|
||||
public ?bool $taxResidentUS = null,
|
||||
public ?bool $foreignTaxResident = null,
|
||||
public ?bool $financialActivities = null,
|
||||
public ?string $name = null,
|
||||
public ?string $registrationDate = null,
|
||||
#[Numeric]
|
||||
public ?string $inn = null,
|
||||
#[Numeric]
|
||||
public ?string $kpp = null,
|
||||
#[Numeric]
|
||||
public ?string $ogrn = null,
|
||||
public ?PersonalInformationData $personalInformation = null,
|
||||
public ?string $phoneNumber = null,
|
||||
#[Email]
|
||||
public ?string $email = null,
|
||||
#[DataCollectionOf(DocumentData::class)]
|
||||
public ?DataCollection $documents = null,
|
||||
) {}
|
||||
// </SECTION>
|
||||
}
|
||||
// </SECTION>
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts\Beneficiaries;
|
||||
// <SECTION name="module_imports" intent="Import the base Spatie Laravel Data class.">
|
||||
// <BELIEF_STATE "Extending `Spatie\LaravelData\Data` enables automatic casting from JSON and provides other DTO benefits.">
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for a specific wallet's balance.">
|
||||
|
||||
@@ -17,6 +17,7 @@ use Apoloz\AlfaBank\Data\PaginationData;
|
||||
use Spatie\LaravelData\Attributes\DataCollectionOf;
|
||||
use Spatie\LaravelData\Data;
|
||||
use Spatie\LaravelData\DataCollection;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for a collection of beneficiaries.">
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts;
|
||||
use Apoloz\AlfaBank\Data\PaginationData; // This import might be misleading for a single DTO, but kept for context consistency.
|
||||
use Spatie\LaravelData\Attributes\DataCollectionOf;
|
||||
use Spatie\LaravelData\Data;
|
||||
use Spatie\LaravelData\DataCollection;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for a single beneficiary's details.">
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts;
|
||||
// <SECTION name="module_imports" intent="Import the base Spatie Laravel Data class.">
|
||||
// <BELIEF_STATE "Extending `Spatie\LaravelData\Data` enables automatic casting from JSON and provides other DTO benefits.">
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for the status of a counterparty request.">
|
||||
|
||||
@@ -17,6 +17,7 @@ use Apoloz\AlfaBank\Data\PaginationData;
|
||||
use Spatie\LaravelData\Attributes\DataCollectionOf;
|
||||
use Spatie\LaravelData\Data;
|
||||
use Spatie\LaravelData\DataCollection;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for a collection of deals.">
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts\Deals;
|
||||
// <SECTION name="module_imports" intent="Import the base Spatie Laravel Data class.">
|
||||
// <BELIEF_STATE "Extending `Spatie\LaravelData\Data` enables automatic casting from JSON and provides other DTO benefits.">
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for a single deal's details.">
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts\Deals;
|
||||
// <SECTION name="module_imports" intent="Import the base Spatie Laravel Data class.">
|
||||
// <BELIEF_STATE "Extending `Spatie\LaravelData\Data` enables automatic casting from JSON and provides other DTO benefits.">
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for a payoff associated with a deal.">
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts\Deals;
|
||||
// <SECTION name="module_imports" intent="Import the base Spatie Laravel Data class.">
|
||||
// <BELIEF_STATE "Extending `Spatie\LaravelData\Data` enables automatic casting from JSON and provides other DTO benefits.">
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for the status of a deal request.">
|
||||
|
||||
@@ -18,6 +18,7 @@ use Apoloz\AlfaBank\Traits\SignableData;
|
||||
use Spatie\LaravelData\Attributes\DataCollectionOf;
|
||||
use Spatie\LaravelData\Data;
|
||||
use Spatie\LaravelData\DataCollection;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for performing an action on a deal contractor.">
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts\Deals\Steps;
|
||||
// <SECTION name="module_imports" intent="Import the base Spatie Laravel Data class.">
|
||||
// <BELIEF_STATE "Extending `Spatie\LaravelData\Data` enables automatic casting from JSON and provides other DTO benefits.">
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for an amount allocated to a contractor's wallet.">
|
||||
|
||||
@@ -18,6 +18,7 @@ use Apoloz\AlfaBank\Traits\SignableData;
|
||||
use Spatie\LaravelData\Attributes\DataCollectionOf;
|
||||
use Spatie\LaravelData\Data;
|
||||
use Spatie\LaravelData\DataCollection;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for performing an action on a deal step.">
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts\Deals\Steps;
|
||||
// <SECTION name="module_imports" intent="Import the base Spatie Laravel Data class.">
|
||||
// <BELIEF_STATE "Extending `Spatie\LaravelData\Data` enables automatic casting from JSON and provides other DTO benefits.">
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for the response of a step action request.">
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts\Deals\Steps;
|
||||
use Spatie\LaravelData\Attributes\DataCollectionOf;
|
||||
use Spatie\LaravelData\Data;
|
||||
use Spatie\LaravelData\DataCollection;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for a contractor in a deal step.">
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts\Deals\Steps;
|
||||
// <SECTION name="module_imports" intent="Import the base Spatie Laravel Data class.">
|
||||
// <BELIEF_STATE "Extending `Spatie\LaravelData\Data` enables automatic casting from JSON and provides other DTO benefits.">
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for a single deal step.">
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts\Deals;
|
||||
// <SECTION name="module_imports" intent="Import the base Spatie Laravel Data class.">
|
||||
// <BELIEF_STATE "Extending `Spatie\LaravelData\Data` enables automatic casting from JSON and provides other DTO benefits.">
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for the response of a deal validation.">
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts\Identification;
|
||||
// <SECTION name="module_imports" intent="Import the base Spatie Laravel Data class.">
|
||||
// <BELIEF_STATE "Extending `Spatie\LaravelData\Data` enables automatic casting from JSON and provides other DTO benefits.">
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for distributing amounts to beneficiaries.">
|
||||
|
||||
@@ -18,6 +18,7 @@ use Apoloz\AlfaBank\Traits\SignableData;
|
||||
use Spatie\LaravelData\Attributes\DataCollectionOf;
|
||||
use Spatie\LaravelData\Data;
|
||||
use Spatie\LaravelData\DataCollection;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for identifying a transaction.">
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts\Identification;
|
||||
// <SECTION name="module_imports" intent="Import the base Spatie Laravel Data class.">
|
||||
// <BELIEF_STATE "Extending `Spatie\LaravelData\Data` enables automatic casting from JSON and provides other DTO benefits.">
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for the response of an identification request.">
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts\Identification;
|
||||
// <SECTION name="module_imports" intent="Import the base Spatie Laravel Data class.">
|
||||
// <BELIEF_STATE "Extending `Spatie\LaravelData\Data` enables automatic casting from JSON and provides other DTO benefits.">
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for payer details.">
|
||||
|
||||
@@ -18,6 +18,7 @@ use Apoloz\AlfaBank\Traits\SignableData;
|
||||
use Spatie\LaravelData\Attributes\DataCollectionOf;
|
||||
use Spatie\LaravelData\Data;
|
||||
use Spatie\LaravelData\DataCollection;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for refunding an unidentified transaction.">
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts\Identification;
|
||||
// <SECTION name="module_imports" intent="Import the base Spatie Laravel Data class.">
|
||||
// <BELIEF_STATE "Extending `Spatie\LaravelData\Data` enables automatic casting from JSON and provides other DTO benefits.">
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for the response of a refund request.">
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts\Identification;
|
||||
use Spatie\LaravelData\Attributes\DataCollectionOf;
|
||||
use Spatie\LaravelData\Data;
|
||||
use Spatie\LaravelData\DataCollection;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for a collection of unidentified transactions.">
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts\Identification;
|
||||
// <SECTION name="module_imports" intent="Import the base Spatie Laravel Data class.">
|
||||
// <BELIEF_STATE "Extending `Spatie\LaravelData\Data` enables automatic casting from JSON and provides other DTO benefits.">
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for an unidentified transaction.">
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts;
|
||||
// <SECTION name="module_imports" intent="Import the base Spatie Laravel Data class.">
|
||||
// <BELIEF_STATE "Extending `Spatie\LaravelData\Data` enables automatic casting from JSON and provides other DTO benefits.">
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for a nominal account.">
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts\Payouts;
|
||||
use Apoloz\AlfaBank\Data\Shared\PayerInfoData;
|
||||
use Apoloz\AlfaBank\Data\Shared\RecipientInfoData;
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for detailed payoff records.">
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts\Payouts;
|
||||
// <SECTION name="module_imports" intent="Import the base Spatie Laravel Data class.">
|
||||
// <BELIEF_STATE "Extending `Spatie\LaravelData\Data` enables automatic casting from JSON and provides other DTO benefits.">
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for cryptographic digest signatures.">
|
||||
|
||||
@@ -21,6 +21,7 @@ use Spatie\LaravelData\Attributes\DataCollectionOf;
|
||||
use Spatie\LaravelData\Attributes\Validation\Numeric;
|
||||
use Spatie\LaravelData\Data;
|
||||
use Spatie\LaravelData\DataCollection;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for creating a new payoff request.">
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts\Payouts;
|
||||
// <SECTION name="module_imports" intent="Import the base Spatie Laravel Data class.">
|
||||
// <BELIEF_STATE "Extending `Spatie\LaravelData\Data` enables automatic casting from JSON and provides other DTO benefits.">
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for the response of a payoff request.">
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts\Payouts;
|
||||
// <SECTION name="module_imports" intent="Import the base Spatie Laravel Data class.">
|
||||
// <BELIEF_STATE "Extending `Spatie\LaravelData\Data` enables automatic casting from JSON and provides other DTO benefits.">
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for payout requisite details.">
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts\Payouts;
|
||||
// <SECTION name="module_imports" intent="Import the base Spatie Laravel Data class.">
|
||||
// <BELIEF_STATE "Extending `Spatie\LaravelData\Data` enables automatic casting from JSON and provides other DTO benefits.">
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for recipient details.">
|
||||
|
||||
@@ -14,10 +14,10 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts\Payouts;
|
||||
// <SECTION name="module_imports" intent="Import necessary classes for cryptographic signatures, data collection, and Laravel Data.">
|
||||
// <BELIEF_STATE "These imports are essential for constructing a secure and structured tax refund request. `DigestSignatureData` ensures the integrity and authenticity of the request, `DataCollectionOf` and `DataCollection` facilitate handling multiple signatures, and `Data` provides the foundational capabilities for data object mapping and validation.">
|
||||
use Apoloz\AlfaBank\Traits\SignableData;
|
||||
use Apoloz\AlfaBank\Data\NominalAccounts\Payouts\DigestSignatureData;
|
||||
use Spatie\LaravelData\Attributes\DataCollectionOf;
|
||||
use Spatie\LaravelData\Data;
|
||||
use Spatie\LaravelData\DataCollection;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define the tax refund request data structure.">
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts\Payouts;
|
||||
// <SECTION name="module_imports" intent="Import the base Spatie\LaravelData class.">
|
||||
// <BELIEF_STATE "This class extends `Spatie\LaravelData\Data` to leverage its robust data mapping and type safety, ensuring consistent and predictable handling of tax refund response payloads.">
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define the tax refund response data structure.">
|
||||
|
||||
@@ -16,9 +16,9 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts\UniversalRecipients;
|
||||
use Apoloz\AlfaBank\Data\NominalAccounts\Payouts\DigestSignatureData;
|
||||
use Apoloz\AlfaBank\Traits\SignableData;
|
||||
use Spatie\LaravelData\Attributes\DataCollectionOf;
|
||||
use Spatie\LaravelData\Attributes\Validation\Numeric;
|
||||
use Spatie\LaravelData\Data;
|
||||
use Spatie\LaravelData\DataCollection;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for creating a universal recipient.">
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts\UniversalRecipients;
|
||||
// <SECTION name="module_imports" intent="Import the base Spatie Laravel Data class.">
|
||||
// <BELIEF_STATE "Extending `Spatie\LaravelData\Data` enables automatic casting from JSON and provides other DTO benefits.">
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for a single universal recipient's details.">
|
||||
|
||||
@@ -14,7 +14,8 @@ namespace Apoloz\AlfaBank\Data\NominalAccounts\UniversalRecipients;
|
||||
// <SECTION name="module_imports" intent="Import the base response DTO.">
|
||||
// <BELIEF_STATE "This DTO reuses `CreateBeneficiaryResponseData` as its base, indicating that the response structure for creating universal recipients is identical to that for beneficiaries. This promotes consistency and reduces code duplication.">
|
||||
use Apoloz\AlfaBank\Data\NominalAccounts\Beneficiaries\CreateBeneficiaryResponseData;
|
||||
use Spatie\LaravelData\Data; // Included for clarity, though inherited from base DTO.
|
||||
|
||||
// Included for clarity, though inherited from base DTO.
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for the response of creating a universal recipient.">
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Apoloz\AlfaBank\Data;
|
||||
// <SECTION name="module_imports" intent="Import the base Spatie Laravel Data class.">
|
||||
// <BELIEF_STATE "Extending `Spatie\LaravelData\Data` enables automatic casting from JSON and provides other DTO benefits.">
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for pagination metadata.">
|
||||
|
||||
@@ -18,6 +18,7 @@ use Apoloz\AlfaBank\Traits\SignableData;
|
||||
use Spatie\LaravelData\Attributes\DataCollectionOf;
|
||||
use Spatie\LaravelData\Data;
|
||||
use Spatie\LaravelData\DataCollection;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for creating a sandbox RUB payment.">
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace Apoloz\AlfaBank\Data\Shared;
|
||||
use Spatie\LaravelData\Attributes\Validation\Numeric;
|
||||
use Spatie\LaravelData\Attributes\Validation\Size;
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for payer information.">
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Apoloz\AlfaBank\Data\Statement;
|
||||
// <SECTION name="module_imports" intent="Import the base Spatie Laravel Data class.">
|
||||
// <BELIEF_STATE "Extending `Spatie\LaravelData\Data` enables automatic casting from JSON and provides other DTO benefits.">
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for monetary amount data.">
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Apoloz\AlfaBank\Data\Statement;
|
||||
// <SECTION name="module_imports" intent="Import the base Spatie Laravel Data class.">
|
||||
// <BELIEF_STATE "Extending `Spatie\LaravelData\Data` enables automatic casting from JSON and provides other DTO benefits.">
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for Russian Ruble transfer details.">
|
||||
|
||||
@@ -17,6 +17,7 @@ use Apoloz\AlfaBank\Data\PaginationData;
|
||||
use Spatie\LaravelData\Attributes\DataCollectionOf;
|
||||
use Spatie\LaravelData\Data;
|
||||
use Spatie\LaravelData\DataCollection;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for a collection of account transactions.">
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Apoloz\AlfaBank\Data\Statement;
|
||||
// <SECTION name="module_imports" intent="Import necessary DTOs and Spatie Laravel Data components.">
|
||||
// <BELIEF_STATE "This DTO includes nested `AmountData` for monetary values and `RurTransferData` for detailed transfer information.">
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a DTO for a single account transaction.">
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
namespace Apoloz\AlfaBank\Data;
|
||||
|
||||
use Spatie\LaravelData\Data;
|
||||
use Spatie\LaravelData\Attributes\DataCollectionOf;
|
||||
use Spatie\LaravelData\Data;
|
||||
use Spatie\LaravelData\DataCollection;
|
||||
|
||||
class WebhookCollectionData extends Data
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Apoloz\AlfaBank\Exceptions;
|
||||
// <SECTION name="module_imports" intent="Import the base Saloon Response class.">
|
||||
// <BELIEF_STATE "The custom exception needs to hold the original Saloon `Response` object to give developers full access to the raw HTTP response for debugging purposes.">
|
||||
use Saloon\Http\Response;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a custom exception that extends PHP's base Exception class.">
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
// MODULE_CONTRACT: Provides a Saloon middleware to standardize error handling for Alfa Bank API responses.
|
||||
// RESPONSIBILITY: To intercept API responses, identify various error formats (BaaS, SBP, or generic HTTP), and throw a consistent `AlfaBankException`, thereby centralizing error reporting and simplifying error management in the SDK.
|
||||
@@ -13,6 +14,7 @@ namespace Apoloz\AlfaBank\Http\Middleware;
|
||||
// <BELIEF_STATE "These imports are crucial for the middleware's functionality. `AlfaBankException` provides a standardized way to signal API errors within the SDK, while `Response` from Saloon is the object that the middleware processes.">
|
||||
use Apoloz\AlfaBank\Exceptions\AlfaBankException;
|
||||
use Saloon\Http\Response;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define the Alfa Bank API response error handling middleware.">
|
||||
|
||||
@@ -45,6 +45,7 @@ class LoggingMiddleware implements RequestMiddleware, ResponseMiddleware
|
||||
if (isset($headers['Authorization'])) {
|
||||
$headers['Authorization'] = 'Bearer *****';
|
||||
}
|
||||
|
||||
return $headers;
|
||||
}
|
||||
// </SECTION>
|
||||
@@ -53,7 +54,9 @@ class LoggingMiddleware implements RequestMiddleware, ResponseMiddleware
|
||||
// <BELIEF_STATE "This protected recursive helper method inspects the request or response body for predefined sensitive keys (e.g., `pan`, `client_secret`). If a sensitive key is found, its value is replaced with a mask. The method recursively processes nested arrays, ensuring that sensitive data is masked even within complex JSON structures, thereby enhancing log security.">
|
||||
protected function maskBody(mixed $body): mixed
|
||||
{
|
||||
if (!is_array($body)) return $body;
|
||||
if (! is_array($body)) {
|
||||
return $body;
|
||||
}
|
||||
|
||||
$sensitiveKeys = ['pan', 'cvc', 'digestSignatures', 'client_secret', 'refresh_token', 'access_token'];
|
||||
|
||||
@@ -64,6 +67,7 @@ class LoggingMiddleware implements RequestMiddleware, ResponseMiddleware
|
||||
$body[$key] = $this->maskBody($value);
|
||||
}
|
||||
}
|
||||
|
||||
return $body;
|
||||
}
|
||||
// </SECTION>
|
||||
|
||||
@@ -25,12 +25,15 @@ class LoggingRequestMiddleware implements RequestMiddleware
|
||||
if (isset($headers['Authorization'])) {
|
||||
$headers['Authorization'] = 'Bearer *****';
|
||||
}
|
||||
|
||||
return $headers;
|
||||
}
|
||||
|
||||
protected function maskBody(mixed $body): mixed
|
||||
{
|
||||
if (!is_array($body)) return $body;
|
||||
if (! is_array($body)) {
|
||||
return $body;
|
||||
}
|
||||
|
||||
$sensitiveKeys = ['pan', 'cvc', 'digestSignatures', 'client_secret', 'refresh_token', 'access_token'];
|
||||
|
||||
@@ -41,6 +44,7 @@ class LoggingRequestMiddleware implements RequestMiddleware
|
||||
$body[$key] = $this->maskBody($value);
|
||||
}
|
||||
}
|
||||
|
||||
return $body;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,9 @@ class LoggingResponseMiddleware implements ResponseMiddleware
|
||||
|
||||
protected function maskBody(mixed $body): mixed
|
||||
{
|
||||
if (!is_array($body)) return $body;
|
||||
if (! is_array($body)) {
|
||||
return $body;
|
||||
}
|
||||
|
||||
$sensitiveKeys = ['pan', 'cvc', 'digestSignatures', 'client_secret', 'refresh_token', 'access_token'];
|
||||
|
||||
@@ -32,6 +34,7 @@ class LoggingResponseMiddleware implements ResponseMiddleware
|
||||
$body[$key] = $this->maskBody($value);
|
||||
}
|
||||
}
|
||||
|
||||
return $body;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ class AlfaOffsetPaginator extends OffsetPaginator
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
// Fallback to raw json if DTO fails
|
||||
echo "DTO Error: " . $e->getMessage() . "\n";
|
||||
echo 'DTO Error: ' . $e->getMessage() . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,12 +52,20 @@ class AlfaOffsetPaginator extends OffsetPaginator
|
||||
$json = $response->json();
|
||||
|
||||
// Common keys in Alfa API
|
||||
if (isset($json['transactions'])) return $json['transactions'];
|
||||
if (isset($json['payments'])) return $json['payments'];
|
||||
if (isset($json['accounts'])) return $json['accounts'];
|
||||
if (isset($json['transactions'])) {
|
||||
return $json['transactions'];
|
||||
}
|
||||
if (isset($json['payments'])) {
|
||||
return $json['payments'];
|
||||
}
|
||||
if (isset($json['accounts'])) {
|
||||
return $json['accounts'];
|
||||
}
|
||||
|
||||
// If it's a direct array (some endpoints)
|
||||
if (array_is_list($json)) return $json;
|
||||
if (array_is_list($json)) {
|
||||
return $json;
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -17,13 +17,14 @@ use Apoloz\AlfaBank\Contracts\SignerInterface;
|
||||
use Apoloz\AlfaBank\Core\AlfaBankConnector;
|
||||
use Apoloz\AlfaBank\Core\AlfaConfig;
|
||||
use Apoloz\AlfaBank\Enums\Environment;
|
||||
use Apoloz\AlfaBank\Laravel\Http\Controllers\AlfaWebhookController;
|
||||
use Apoloz\AlfaBank\Laravel\Middleware\VerifyAlfaWebhook;
|
||||
use Apoloz\AlfaBank\Sbp\SbpConnector;
|
||||
use Apoloz\AlfaBank\Services\OpenSslCmsSigner;
|
||||
use Apoloz\AlfaBank\Services\PhpseclibCardEncryptor;
|
||||
use Apoloz\AlfaBank\Sbp\SbpConnector;
|
||||
use Apoloz\AlfaBank\Laravel\Middleware\VerifyAlfaWebhook;
|
||||
use Apoloz\AlfaBank\Laravel\Http\Controllers\AlfaWebhookController;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
class AlfaBankServiceProvider extends ServiceProvider
|
||||
@@ -37,6 +38,7 @@ class AlfaBankServiceProvider extends ServiceProvider
|
||||
|
||||
$this->app->singleton('alfa.baas.config', function ($app) {
|
||||
$conf = $app['config']['alfa-bank.baas'];
|
||||
|
||||
return new AlfaConfig(
|
||||
baseUrl: $conf['environment'] === 'production' ? Environment::PRODUCTION->value : Environment::SANDBOX->value,
|
||||
certificatePath: $conf['certificate_path'],
|
||||
@@ -61,6 +63,7 @@ class AlfaBankServiceProvider extends ServiceProvider
|
||||
|
||||
$this->app->bind(EncryptorInterface::class, function ($app) {
|
||||
$key = $app['config']['alfa-bank.encryption.card_public_key'] ?? '';
|
||||
|
||||
return new PhpseclibCardEncryptor($key);
|
||||
});
|
||||
|
||||
@@ -74,6 +77,7 @@ class AlfaBankServiceProvider extends ServiceProvider
|
||||
|
||||
$this->app->singleton('alfa.sbp.config', function ($app) {
|
||||
$conf = $app['config']['alfa-bank.sbp'];
|
||||
|
||||
return new AlfaConfig(
|
||||
baseUrl: $conf['environment'] === 'production' ? Environment::SBP_PRODUCTION->value : Environment::SBP_SANDBOX->value,
|
||||
certificatePath: $conf['certificate_path'],
|
||||
@@ -86,6 +90,7 @@ class AlfaBankServiceProvider extends ServiceProvider
|
||||
|
||||
$this->app->singleton(SbpConnector::class, function ($app) {
|
||||
$config = $app['config']['alfa-bank.sbp'];
|
||||
|
||||
return new SbpConnector(
|
||||
alfaConfig: $app->make('alfa.sbp.config'),
|
||||
keyNameAlias: $config['key_name_alias'] ?? null
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace Apoloz\AlfaBank\Laravel\Commands;
|
||||
use Apoloz\AlfaBank\Core\AlfaBankConnector;
|
||||
use Apoloz\AlfaBank\Sbp\SbpConnector;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define the Alfa Bank SDK connection check Artisan command.">
|
||||
@@ -25,6 +26,7 @@ class CheckConnectionCommand extends Command
|
||||
// <SECTION name="command_signature_and_description" intent="Define the command's name and description.">
|
||||
// <BELIEF_STATE "The `$signature` property (`alfa:check`) makes the command executable via Artisan. The `$description` provides a clear summary of the command's purpose, aiding in user understanding when viewing `php artisan list`.">
|
||||
protected $signature = 'alfa:check';
|
||||
|
||||
protected $description = 'Verify Alfa Bank SDK configuration and mTLS certificates';
|
||||
// </SECTION>
|
||||
|
||||
@@ -52,16 +54,18 @@ class CheckConnectionCommand extends Command
|
||||
// 1. Check Files
|
||||
if (! file_exists($certPath)) {
|
||||
$this->error("❌ Certificate not found at: {$certPath}");
|
||||
|
||||
return;
|
||||
} else {
|
||||
$this->comment("✅ Certificate found");
|
||||
$this->comment('✅ Certificate found');
|
||||
}
|
||||
|
||||
if (! file_exists($keyPath)) {
|
||||
$this->error("❌ Private Key not found at: {$keyPath}");
|
||||
|
||||
return;
|
||||
} else {
|
||||
$this->comment("✅ Private Key found");
|
||||
$this->comment('✅ Private Key found');
|
||||
}
|
||||
|
||||
// 2. Validate Cert Expiry
|
||||
@@ -70,20 +74,20 @@ class CheckConnectionCommand extends Command
|
||||
|
||||
if ($certInfo && isset($certInfo['validTo_time_t'])) {
|
||||
$validTo = new \DateTimeImmutable('@' . $certInfo['validTo_time_t']);
|
||||
$now = new \DateTimeImmutable();
|
||||
$now = new \DateTimeImmutable;
|
||||
if ($validTo < $now) {
|
||||
$this->error("❌ Certificate EXPIRED on: " . $validTo->format('Y-m-d H:i:s'));
|
||||
$this->error('❌ Certificate EXPIRED on: ' . $validTo->format('Y-m-d H:i:s'));
|
||||
} else {
|
||||
$diff = $now->diff($validTo);
|
||||
$days = $diff->days;
|
||||
$this->comment("✅ Certificate valid until: " . $validTo->format('Y-m-d') . " ({$days} days remaining)");
|
||||
$this->comment('✅ Certificate valid until: ' . $validTo->format('Y-m-d') . " ({$days} days remaining)");
|
||||
}
|
||||
} else {
|
||||
$this->warn("⚠️ Could not parse certificate date.");
|
||||
$this->warn('⚠️ Could not parse certificate date.');
|
||||
}
|
||||
|
||||
// 3. Attempt Connection (Ping)
|
||||
$this->comment("Attempting TLS Handshake...");
|
||||
$this->comment('Attempting TLS Handshake...');
|
||||
|
||||
try {
|
||||
// We resolve the connector from container to use the config
|
||||
@@ -93,18 +97,23 @@ class CheckConnectionCommand extends Command
|
||||
|
||||
// Simple GET to the base URL (or a health endpoint) just to test SSL handshake
|
||||
// We don't need a valid token, we just want to see if we get a 401/403 instead of a connection error
|
||||
$connector->send(new class extends \Saloon\Http\Request {
|
||||
$connector->send(new class extends \Saloon\Http\Request
|
||||
{
|
||||
protected \Saloon\Enums\Method $method = \Saloon\Enums\Method::GET;
|
||||
public function resolveEndpoint(): string { return '/'; }
|
||||
|
||||
public function resolveEndpoint(): string
|
||||
{
|
||||
return '/';
|
||||
}
|
||||
});
|
||||
|
||||
// If we are here, SSL worked!
|
||||
$this->info("✅ Connection Successful! (Handshake completed)");
|
||||
$this->info('✅ Connection Successful! (Handshake completed)');
|
||||
|
||||
} catch (\Exception $e) {
|
||||
// Check if it's an SSL error
|
||||
if (str_contains($e->getMessage(), 'certificate') || str_contains($e->getMessage(), 'SSL')) {
|
||||
$this->error("❌ SSL/TLS Error: " . $e->getMessage());
|
||||
$this->error('❌ SSL/TLS Error: ' . $e->getMessage());
|
||||
} else {
|
||||
// Other errors (like 404/401) mean SSL worked but endpoint failed, which is GOOD for this check
|
||||
$this->info("✅ Connection Successful! (Server responded: {$e->getMessage()})");
|
||||
|
||||
@@ -4,7 +4,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace Apoloz\AlfaBank\Laravel\Facades;
|
||||
|
||||
use Apoloz\AlfaBank\Core\AlfaBankConnector;
|
||||
use Illuminate\Support\Facades\Facade;
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,7 +4,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace Apoloz\AlfaBank\Laravel\Facades;
|
||||
|
||||
use Apoloz\AlfaBank\Sbp\SbpConnector;
|
||||
use Illuminate\Support\Facades\Facade;
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,13 +31,13 @@ class GetAccountsRequest extends Request implements Paginatable
|
||||
return '/api/pp/v1/accounts';
|
||||
}
|
||||
|
||||
protected function defaultQuery(): array
|
||||
{
|
||||
return $this->getPaginationQuery();
|
||||
}
|
||||
|
||||
public function createDtoFromResponse(Response $response): DataCollection
|
||||
{
|
||||
return AccountData::collect($response->json('accounts'), DataCollection::class);
|
||||
}
|
||||
|
||||
protected function defaultQuery(): array
|
||||
{
|
||||
return $this->getPaginationQuery();
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,11 @@ class CheckComplianceRequest extends Request
|
||||
return '/api/aff/jp/v1/creditors/compliance';
|
||||
}
|
||||
|
||||
public function createDtoFromResponse(Response $response): AffResponseData
|
||||
{
|
||||
return AffResponseData::from($response->json());
|
||||
}
|
||||
|
||||
protected function defaultQuery(): array
|
||||
{
|
||||
return [
|
||||
@@ -30,9 +35,4 @@ class CheckComplianceRequest extends Request
|
||||
'name' => $this->name,
|
||||
];
|
||||
}
|
||||
|
||||
public function createDtoFromResponse(Response $response): AffResponseData
|
||||
{
|
||||
return AffResponseData::from($response->json());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,13 +27,13 @@ class CreateRegisterRequest extends Request implements HasBody
|
||||
return '/api/aff/jp/v1/registers';
|
||||
}
|
||||
|
||||
protected function defaultBody(): array
|
||||
{
|
||||
return $this->data->toArray();
|
||||
}
|
||||
|
||||
public function createDtoFromResponse(Response $response): AffResponseData
|
||||
{
|
||||
return AffResponseData::from($response->json());
|
||||
}
|
||||
|
||||
protected function defaultBody(): array
|
||||
{
|
||||
return $this->data->toArray();
|
||||
}
|
||||
}
|
||||
@@ -27,15 +27,15 @@ class SignRegisterRequest extends Request implements HasBody
|
||||
return '/api/aff/jp/v1/registers/sign';
|
||||
}
|
||||
|
||||
protected function defaultBody(): array
|
||||
{
|
||||
return $this->data->toArray();
|
||||
}
|
||||
|
||||
public function createDtoFromResponse(Response $response): GeneralStatusData
|
||||
{
|
||||
return GeneralStatusData::from([
|
||||
'success' => $response->successful(),
|
||||
]);
|
||||
}
|
||||
|
||||
protected function defaultBody(): array
|
||||
{
|
||||
return $this->data->toArray();
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ use Saloon\Enums\Method;
|
||||
use Saloon\Http\Request;
|
||||
use Saloon\Http\Response;
|
||||
use Saloon\Traits\Body\HasFormBody;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define a class for the OAuth 2.0 token endpoint request.">
|
||||
@@ -55,6 +56,14 @@ class GetTokenRequest extends Request implements HasBody
|
||||
}
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="response_dto_caster" intent="Transform the raw JSON response into a structured TokenData DTO.">
|
||||
// <BELIEF_STATE "Automatically casting the JSON token response into a `TokenData` DTO provides type safety and a clean, object-oriented way to access token properties like `access_token` and `expires_in`.">
|
||||
public function createDtoFromResponse(Response $response): TokenData
|
||||
{
|
||||
return TokenData::from($response->json());
|
||||
}
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="request_body_builder" intent="Construct the form-urlencoded body for the token request.">
|
||||
// <BELIEF_STATE "This method builds the request body array. It correctly maps the class properties to the `snake_case` parameter names expected by the OAuth 2.0 standard.">
|
||||
protected function defaultBody(): array
|
||||
@@ -77,12 +86,4 @@ class GetTokenRequest extends Request implements HasBody
|
||||
return $body;
|
||||
}
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="response_dto_caster" intent="Transform the raw JSON response into a structured TokenData DTO.">
|
||||
// <BELIEF_STATE "Automatically casting the JSON token response into a `TokenData` DTO provides type safety and a clean, object-oriented way to access token properties like `access_token` and `expires_in`.">
|
||||
public function createDtoFromResponse(Response $response): TokenData
|
||||
{
|
||||
return TokenData::from($response->json());
|
||||
}
|
||||
// </SECTION>
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user