forked from apoloz/alfa-bank-sdk
Update documentation and examples, add new nominal accounts features and authentication methods
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
@@ -6,24 +6,30 @@ use Apoloz\AlfaBank\AlfaBank;
|
||||
use Apoloz\AlfaBank\Enums\Environment;
|
||||
|
||||
// 1. Initialize
|
||||
// Ensure you have valid certificates for the Sandbox
|
||||
// CERTIFICATES:
|
||||
// - Sandbox: Provided by bank via email or portal (often a .pfx or zip).
|
||||
// - Production: Generated by YOU (openssl), public part sent to bank for activation.
|
||||
$baas = AlfaBank::baas(
|
||||
certificatePath: __DIR__ . '/certs/client.cer',
|
||||
privateKeyPath: __DIR__ . '/certs/private.key',
|
||||
environment: Environment::SANDBOX,
|
||||
caBundlePath: __DIR__ . '/certs/russian_trusted_sub_ca.crt' // Mincifry
|
||||
caBundlePath: __DIR__ . '/certs/russian_trusted_sub_ca.crt' // Optional: for trusted chain validation
|
||||
);
|
||||
|
||||
try {
|
||||
echo "Authenticating...\n";
|
||||
|
||||
// AUTHENTICATION:
|
||||
// client_id: From Developer Portal (App Settings)
|
||||
// client_secret: From Developer Portal (App Settings -> Key Icon) OR generated via SDK (examples/14_generate_client_secret.php)
|
||||
|
||||
// METHOD A: Standard Client Credentials (for simple services)
|
||||
// $baas->login(
|
||||
// clientId: 'your-client-id',
|
||||
// clientSecret: 'your-client-secret'
|
||||
// clientId: 'your-client-id-uuid',
|
||||
// clientSecret: 'your-client-secret-string'
|
||||
// );
|
||||
|
||||
// METHOD B: Authorization Code Flow (H2H) (for Nominal Accounts)
|
||||
// METHOD B: Authorization Code Flow (H2H) (REQUIRED for Nominal Accounts)
|
||||
// See examples/13_h2h_auth_service.php for the full setup
|
||||
$auth = \Apoloz\AlfaBank\AlfaBank::auth(
|
||||
clientId: 'your-client-id',
|
||||
|
||||
@@ -44,7 +44,11 @@ $payload = new CreateBeneficiaryRequestData(
|
||||
|
||||
// 2. Login and send request
|
||||
// For Nominal Accounts, use H2H Auth (Refresh Token)
|
||||
// See examples/13_h2h_auth_service.php
|
||||
// See examples/13_h2h_auth_service.php for setting this up.
|
||||
|
||||
// CREDENTIALS SOURCE:
|
||||
// - client-id: Developer Portal -> App -> Overview
|
||||
// - client-secret: Developer Portal -> App -> Keys (Click Eye Icon) OR SDK Generator
|
||||
$auth = AlfaBank::auth(
|
||||
'client-id', 'client-secret', 'https://callback',
|
||||
'path/to/cert.pem', 'path/to/key.pem', Environment::SANDBOX
|
||||
|
||||
@@ -23,6 +23,8 @@ use Spatie\LaravelData\DataCollection;
|
||||
*/
|
||||
|
||||
// 1. Инициализация SDK
|
||||
// Сертификаты (Transport Certs):
|
||||
// Получены от банка (Sandbox) или сгенерированы вами и активированы банком (Production).
|
||||
$baas = AlfaBank::baas(
|
||||
certificatePath: 'transport.crt',
|
||||
privateKeyPath: 'transport.key'
|
||||
@@ -34,6 +36,8 @@ $signKey = file_get_contents('signing.key');
|
||||
|
||||
try {
|
||||
// Auth: Nominal Accounts require H2H Flow
|
||||
// client_id: Из Портала разработчика
|
||||
// client_secret: Из Портала разработчика (глаз) или сгенерирован через SDK (examples/14_generate_client_secret.php)
|
||||
$auth = AlfaBank::auth(
|
||||
'client_id', 'client_secret', 'https://callback',
|
||||
'transport.crt', 'transport.key'
|
||||
|
||||
@@ -16,11 +16,24 @@ use Apoloz\AlfaBank\Requests\NominalAccounts\Beneficiaries\GetBeneficiariesReque
|
||||
|
||||
// 1. Конфигурация
|
||||
$config = [
|
||||
// CERTIFICATES:
|
||||
// Production: You generated `private.key` and sent CSR to bank. Bank sent back `client.cer`.
|
||||
// Sandbox: Bank sent you these via email/portal.
|
||||
'cert' => __DIR__ . '/certs/client.cer',
|
||||
'key' => __DIR__ . '/certs/private.key',
|
||||
|
||||
// APP CREDENTIALS (OAUTH2):
|
||||
// From: Developer Portal -> Your App -> Settings/Keys
|
||||
// Note: If you don't have client_secret, generate it using `14_generate_client_secret.php`
|
||||
'client_id' => getenv('ALFA_BAAS_CLIENT_ID'),
|
||||
'client_secret' => getenv('ALFA_BAAS_CLIENT_SECRET'),
|
||||
'redirect_uri' => 'https://your-app.com/callback', // Тот же, что указывали при получении кода
|
||||
|
||||
// REDIRECT URI:
|
||||
// Must match exactly what you entered in Developer Portal for this App.
|
||||
'redirect_uri' => 'https://your-app.com/callback',
|
||||
|
||||
// BUSINESS DATA:
|
||||
// From your Contract or Internet Bank. Not related to Auth directly.
|
||||
'account_number' => '40702810...'
|
||||
];
|
||||
|
||||
|
||||
@@ -12,25 +12,26 @@ use Apoloz\AlfaBank\Enums\Environment;
|
||||
*/
|
||||
|
||||
// 1. Конфигурация
|
||||
$clientId = getenv('ALFA_BAAS_CLIENT_ID');
|
||||
$clientSecret = getenv('ALFA_BAAS_CLIENT_SECRET');
|
||||
$redirectUri = 'https://your-domain.com/callback';
|
||||
$cert = __DIR__ . '/certs/client.cer';
|
||||
$key = __DIR__ . '/certs/private.key';
|
||||
// Все эти данные вы получаете на Портале Разработчика и в Интернет-банке.
|
||||
$clientId = getenv('ALFA_BAAS_CLIENT_ID'); // ID приложения (Portal)
|
||||
$clientSecret = getenv('ALFA_BAAS_CLIENT_SECRET'); // Secret Key (Portal OR Generated via SDK)
|
||||
$redirectUri = 'https://your-domain.com/callback'; // Callback URL (Portal)
|
||||
$cert = __DIR__ . '/certs/client.cer'; // Public Cert (From Bank)
|
||||
$key = __DIR__ . '/certs/private.key'; // Private Key (Generated by You)
|
||||
|
||||
// 2. Инициализация сервиса авторизации
|
||||
$authService = AlfaBank::auth(
|
||||
$clientId,
|
||||
$clientSecret,
|
||||
$redirectUri,
|
||||
$cert,
|
||||
$key,
|
||||
Environment::SANDBOX
|
||||
// 2. Инициализация SDK (сразу с кредами)
|
||||
$baas = AlfaBank::baas(
|
||||
certificatePath: $cert,
|
||||
privateKeyPath: $key,
|
||||
environment: Environment::SANDBOX,
|
||||
clientId: $clientId,
|
||||
clientSecret: $clientSecret,
|
||||
redirectUri: $redirectUri
|
||||
);
|
||||
|
||||
// --- СЦЕНАРИЙ 1: Генерация ссылки на вход ---
|
||||
// Выведите эту ссылку в админке или логах
|
||||
$link = $authService->getAuthUrl(scopes: ['beneficiaries', 'payment']);
|
||||
// Используем нативный метод Saloon
|
||||
$link = $baas->getAuthorizationUrl(scopes: ['beneficiaries', 'payment']);
|
||||
echo "1. Перейдите по ссылке для авторизации:\n$link\n\n";
|
||||
|
||||
|
||||
@@ -41,17 +42,17 @@ $codeFromUrl = '...код из браузера...';
|
||||
if ($codeFromUrl !== '...код из браузера...') {
|
||||
try {
|
||||
echo "2. Обмен кода на токены...\n";
|
||||
$tokenData = $authService->exchangeCode($codeFromUrl);
|
||||
|
||||
echo "Access Token: " . substr($tokenData->access_token, 0, 20) . "...\n";
|
||||
echo "Refresh Token: " . $tokenData->refresh_token . "\n";
|
||||
echo "Expires In: " . $tokenData->expires_in . " sec\n";
|
||||
// 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";
|
||||
|
||||
// TODO: Сохраните refresh_token в базу данных!
|
||||
// DB::table('settings')->updateOrInsert(['key' => 'alfa_refresh_token'], ['value' => $tokenData->refresh_token]);
|
||||
|
||||
} catch (
|
||||
Exception $e) {
|
||||
} catch (\Exception $e) {
|
||||
echo "Ошибка обмена кода: " . $e->getMessage() . "\n";
|
||||
}
|
||||
}
|
||||
@@ -62,17 +63,21 @@ $savedRefreshToken = '...saved_refresh_token...';
|
||||
if ($savedRefreshToken !== '...saved_refresh_token...') {
|
||||
try {
|
||||
echo "3. Обновление токена...\n";
|
||||
$newTokenData = $authService->refreshToken($savedRefreshToken);
|
||||
|
||||
// Обновляем токен
|
||||
$newAuthenticator = $baas->refreshAccessToken($savedRefreshToken);
|
||||
|
||||
// Автоматически применяем к коннектору (для текущего скрипта)
|
||||
$baas->authenticate($newAuthenticator);
|
||||
|
||||
echo "Токен обновлен!\n";
|
||||
|
||||
// Если пришел новый refresh_token — обновляем его
|
||||
if ($newTokenData->refresh_token) {
|
||||
if ($newAuthenticator->getRefreshToken()) {
|
||||
// DB::update(...)
|
||||
echo "Новый Refresh Token получен.\n";
|
||||
}
|
||||
} catch (
|
||||
Exception $e) {
|
||||
} catch (\Exception $e) {
|
||||
echo "Ошибка обновления токена: " . $e->getMessage() . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,8 +14,10 @@ use Apoloz\AlfaBank\Enums\Environment;
|
||||
* Run this ONCE when setting up the project or if you lose your secret.
|
||||
*
|
||||
* Requirements:
|
||||
* 1. You have the `client_id` (from the bank/portal).
|
||||
* 1. You have the `client_id` (Found in Developer Portal -> App Settings URL or Overview).
|
||||
* 2. You have the TLS certificates (.pem/.key) authorized by the bank.
|
||||
* - Prod: You sent CSR to bank, they enabled integration and sent .cer back.
|
||||
* - Sandbox: You downloaded them from the email/portal.
|
||||
*/
|
||||
|
||||
// 1. Configuration
|
||||
|
||||
70
examples/15_nominal_accounts_list.php
Normal file
70
examples/15_nominal_accounts_list.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
use Apoloz\AlfaBank\AlfaBank;
|
||||
use Apoloz\AlfaBank\Enums\Environment;
|
||||
use Apoloz\AlfaBank\Requests\NominalAccounts\Beneficiaries\GetBeneficiariesRequest;
|
||||
|
||||
/**
|
||||
* FINAL GOAL EXAMPLE: Get List of Nominal Account Beneficiaries
|
||||
*
|
||||
* This script assumes you have already:
|
||||
* 1. Generated/Received Certificates.
|
||||
* 2. Obtained Client ID & Secret (via Portal or Script 14).
|
||||
* 3. Passed H2H Auth via Browser and obtained a Refresh Token (via Script 13).
|
||||
*/
|
||||
|
||||
// --- CONFIGURATION (From .env) ---
|
||||
$config = [
|
||||
'client_id' => getenv('ALFA_BAAS_CLIENT_ID'),
|
||||
'client_secret' => getenv('ALFA_BAAS_CLIENT_SECRET'),
|
||||
'redirect_uri' => 'https://your-app.com/callback',
|
||||
'cert_path' => __DIR__ . '/certs/client.cer',
|
||||
'key_path' => __DIR__ . '/certs/private.key',
|
||||
|
||||
// BUSINESS DATA
|
||||
'account_num' => '40702810...', // Nominal Account Number
|
||||
'refresh_token' => 'saved_refresh_token_db' // Your stored token
|
||||
];
|
||||
|
||||
try {
|
||||
// 1. Initialize Connector with Auth Config
|
||||
$baas = AlfaBank::baas(
|
||||
certificatePath: $config['cert_path'],
|
||||
privateKeyPath: $config['key_path'],
|
||||
environment: Environment::SANDBOX,
|
||||
clientId: $config['client_id'],
|
||||
clientSecret: $config['client_secret'],
|
||||
redirectUri: $config['redirect_uri']
|
||||
);
|
||||
|
||||
// 2. Refresh Token (Get valid Access Token for this session)
|
||||
echo "Refreshing session...\n";
|
||||
$authenticator = $baas->refreshAccessToken($config['refresh_token']);
|
||||
|
||||
// Apply authentication to the connector
|
||||
$baas->authenticate($authenticator);
|
||||
|
||||
// 3. Perform Business Request
|
||||
echo "Requesting beneficiaries list...\n";
|
||||
$request = new GetBeneficiariesRequest(
|
||||
accountNumber: $config['account_num'],
|
||||
type: 'FL_RESIDENT'
|
||||
);
|
||||
|
||||
$response = $baas->send($request);
|
||||
|
||||
// 4. Handle Result
|
||||
$list = $response->dto();
|
||||
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";
|
||||
}
|
||||
89
examples/16_automated_startup.php
Normal file
89
examples/16_automated_startup.php
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
use Apoloz\AlfaBank\AlfaBank;
|
||||
use Apoloz\AlfaBank\Requests\Auth\RefreshClientSecretRequest;
|
||||
use Apoloz\AlfaBank\Requests\NominalAccounts\Beneficiaries\GetBeneficiariesRequest;
|
||||
use Apoloz\AlfaBank\Enums\Environment;
|
||||
|
||||
/**
|
||||
* FULLY AUTOMATED WORKFLOW
|
||||
*
|
||||
* Scenario: You don't want to store `client_secret` persistently.
|
||||
* Instead, you use your Certificates to fetch a fresh secret on startup (or when needed),
|
||||
* and then immediately use it to refresh your OAuth tokens.
|
||||
*
|
||||
* CAUTION: Requesting a new secret invalidates the old one.
|
||||
* If you have multiple app instances, implement a shared cache (Redis/DB) for the secret!
|
||||
*/
|
||||
|
||||
// --- CONFIGURATION ---
|
||||
// You only need immutable identifiers and certificates.
|
||||
$clientId = getenv('ALFA_BAAS_CLIENT_ID');
|
||||
$redirectUri = 'https://your-app.com/callback';
|
||||
$certPath = __DIR__ . '/certs/client.cer';
|
||||
$keyPath = __DIR__ . '/certs/private.key';
|
||||
$accNum = '40702810...';
|
||||
|
||||
// This assumes you have already passed the browser flow once and saved the refresh token.
|
||||
$savedRefreshToken = 'your_saved_refresh_token_from_db';
|
||||
|
||||
// 1. Initialize Bare Connector (mTLS only)
|
||||
$baas = AlfaBank::baas($certPath, $keyPath, Environment::SANDBOX);
|
||||
|
||||
try {
|
||||
// 2. FETCH CLIENT SECRET DYNAMICALLY
|
||||
// We prove our identity via mTLS certificates.
|
||||
echo "1. Requesting dynamic client_secret via API...\n";
|
||||
|
||||
// In a real app: CHECK CACHE FIRST!
|
||||
// $cachedSecret = Cache::get('alfa_client_secret');
|
||||
// if ($cachedSecret) { $tempSecret = $cachedSecret; } else { ... }
|
||||
|
||||
$secretResponse = $baas->send(new RefreshClientSecretRequest($clientId));
|
||||
$tempSecret = $secretResponse->dto()->clientSecret;
|
||||
|
||||
echo " Secret acquired: " . substr($tempSecret, 0, 5) . "...\n";
|
||||
|
||||
// 3. AUTHENTICATE OAUTH2
|
||||
// Now we use the fresh secret to get an access token.
|
||||
echo "2. Refreshing OAuth2 session...\n";
|
||||
|
||||
// Re-initialize connector with the new secret
|
||||
$baasReady = AlfaBank::baas(
|
||||
certificatePath: $certPath,
|
||||
privateKeyPath: $keyPath,
|
||||
environment: Environment::SANDBOX,
|
||||
clientId: $clientId,
|
||||
clientSecret: $tempSecret,
|
||||
redirectUri: $redirectUri
|
||||
);
|
||||
|
||||
// Refresh token using native method
|
||||
$authenticator = $baasReady->refreshAccessToken($savedRefreshToken);
|
||||
$baasReady->authenticate($authenticator);
|
||||
|
||||
echo " Session active. Access Token expires at " . $authenticator->getExpiresAt()->format('H:i:s') . "\n";
|
||||
|
||||
// Update DB if refresh token rotated
|
||||
if ($authenticator->getRefreshToken()) {
|
||||
// saveNewRefreshToken($authenticator->getRefreshToken());
|
||||
echo " New Refresh Token saved.\n";
|
||||
}
|
||||
|
||||
// 4. BUSINESS LOGIC
|
||||
echo "3. Fetching beneficiaries...\n";
|
||||
|
||||
$response = $baasReady->send(new GetBeneficiariesRequest($accNum, 'FL_RESIDENT'));
|
||||
|
||||
echo " Success! Found " . count($response->dto()->beneficiaries) . " records.\n";
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo "CRITICAL ERROR: " . $e->getMessage() . "\n";
|
||||
if (method_exists($e, 'getResponse')) {
|
||||
echo "Body: " . $e->getResponse()->body() . "\n";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user