diff --git a/README.md b/README.md index 2ac499d..6b68ed0 100644 --- a/README.md +++ b/README.md @@ -8,210 +8,163 @@ ## Требования - PHP 8.2+ -- Расширение OpenSSL - [Saloon](https://docs.saloon.dev) v3.0+ - [Spatie Laravel Data](https://spatie.be/docs/laravel-data) -## Установка +## Подключение и Безопасность -```bash -composer require apoloz/alfa-bank-sdk +SDK поддерживает две разные модели безопасности, используемые в API Альфа-Банка. + +### 1. Подключение к СБП (Pay-in) + +**Шаги для получения доступа:** +1. Генерируете пару ключей: `openssl req -x509 -newkey rsa:2048 -keyout client.key -out client.crt -nodes -days 3650`. +2. Отправляете `client.crt` менеджеру банка (acquiring@alfabank.ru). +3. Получаете от банка `alias` (key-name) и `TermNo`. + +**Поток данных и подпись:** +* **Transport**: Обязательный **MTLS**. Вы должны передать `client.crt` и `client.key` в конфигурацию Guzzle/Saloon. +* **Payload**: Тело запроса канонизируется по алгоритму **JCS**. +* **Signature**: SHA256withRSA подпись JCS-строки помещается в заголовок `Authorization`. + +**SDK делает это автоматически**: +```php +// В config/alfa-bank.php +'sbp' => [ + 'alias' => 'my-company-alias', + 'private_key' => storage_path('certs/client.key'), + 'cert' => storage_path('certs/client.crt'), +], ``` --- -## Архитектура и потоки данных +### 2. Подключение к BaaS (Номинальные счета) -Библиотека обеспечивает строгую типизацию на всех этапах. Вы работаете только с объектами (DTO), а SDK берет на себя всю сложность протоколов банка. +**Шаги для получения доступа:** +1. Регистрация в личном кабинете партнера. +2. Получение `client_id` и `client_secret` для OAuth2. +3. Регистрация публичного ключа для проверки подписей выплат. -### 1. Жизненный цикл запроса (BaaS) +**Поток данных и подпись:** +* **Auth**: Стандартный OAuth2 Bearer Token. +* **Payload Signature**: Для критических операций (выплаты, идентификация) требуется `digestSignatures`. Это массив CMS-подписей (PKCS7) в формате Base64, которыми подписываются финансовые поля. + +**Пример формирования CMS в SDK:** +```php +use Apoloz\AlfaBank\Utils\CmsSigner; + +$payload = json_encode($dataToSign); +$signature = CmsSigner::sign($payload, $privateKey, $certificate); + +// $signature помещается в массив digestSignatures +``` + +--- + +## Архитектура и Потоки данных + +### Гибридный поток: СБП -> Номинальный счет ```mermaid sequenceDiagram - participant App as Приложение - participant DTO as Request DTO - participant SDK as Connector - participant API as Alfa Bank + participant Client as Покупатель + participant SBP as SDK (SBP Connector) + participant API as Alfa Bank API + participant BaaS as SDK (BaaS Connector) - App->>DTO: 1. Создание данных - App->>SDK: 2. send(Request) - SDK->>SDK: 3. Маппинг полей (PascalCase) - SDK->>SDK: 4. Подпись/Шифрование - SDK->>API: 5. HTTPS + mTLS - API-->>SDK: 6. JSON Ответ - SDK->>SDK: 7. Валидация ошибок - SDK->>App: 8. Возврат Response DTO -``` + Note over SBP, API: MTLS + JCS Signature + SBP->>API: 1. GetQrCodeRequest(NominalAcc) + API-->>SBP: 2. QR Payload (URL) + Client->>API: 3. Оплата в приложении (СБП) -### 2. Безопасность СБП (Body Signing) -Для СБП реализована автоматическая каноникализация JSON (JCS) с рекурсивной сортировкой ключей перед подписью RSA-SHA256. - ---- - -## Настройка и Безопасность - -Альфа-Банк требует **два набора ключей**: -1. **Транспортные (mTLS):** Для установки защищенного соединения. -2. **Прикладные (Signing):** Для цифровой подписи реестров и платежей. - -### Быстрый старт (Laravel) - -1. Опубликуйте конфиг: -```bash -php artisan vendor:publish --tag=alfa-bank-config -``` - -2. Настройте `.env`: -```env -ALFA_BAAS_CERT_PATH=/path/to/transport.crt -ALFA_BAAS_KEY_PATH=/path/to/transport.key -ALFA_BAAS_CLIENT_ID=your_id -ALFA_BAAS_CLIENT_SECRET=your_secret -``` - -3. Проверьте соединение: -```bash -php artisan alfa:check + Note over API, BaaS: Webhook with Signature + API->>BaaS: 4. Webhook (Входящий платеж) + + Note over BaaS, API: OAuth2 + CMS Signature + BaaS->>API: 5. IdentifyTransactionRequest(beneficiaryId) + API-->>BaaS: 6. 200 OK (Зачислено) ``` --- ## Примеры использования -### 1. Авторизация и получение счетов -```php -use Apoloz\AlfaBank\Laravel\Facades\AlfaBank; -use Apoloz\AlfaBank\Requests\Accounts\GetAccountsRequest; - -// SDK сам получит токен и применит его -$accounts = AlfaBank::send(new GetAccountsRequest()); - -foreach ($accounts as $account) { - echo $account->number . ": " . $account->openDate; -} -``` - -### 2. Стандартный платеж (BaaS) -```php -use Apoloz\AlfaBank\Requests\Payments\CreatePaymentRequest; -use Apoloz\AlfaBank\Data\Payments\PaymentData; - -$data = new PaymentData( - amount: 1500.00, - date: date('Y-m-d'), - externalId: 'INV-2026-001', - operationCode: '01', - payeeAccount: '40702...', - payeeBankBic: '044525593', - payeeName: 'ООО Партнер', - payerAccount: '40702...', - payerBankBic: '044525593', - payerBankCorrAccount: '30101...', - payerInn: '7700000000', - payerName: 'Моя Компания', - priority: '5', - purpose: 'Оплата по счету №1' -); - -$response = AlfaBank::send(new CreatePaymentRequest($data)); -echo "Платеж создан: " . $response->id; -``` - -### 3. СБП: Генерация QR-кода +### 1. СБП: Прием платежа на номинальный счет ```php use Apoloz\AlfaBank\Laravel\Facades\Sbp; use Apoloz\AlfaBank\Sbp\Requests\GetQrCodeRequest; use Apoloz\AlfaBank\Sbp\Data\QrCodeRequestData; -$payload = new QrCodeRequestData( - termNo: '90080567', - amount: '10000', // 100.00 руб - paymentPurpose: 'Заказ №5' -); - -$response = Sbp::send(new GetQrCodeRequest($payload)); -echo "Отсканируйте код: " . $response->payload; -``` - -### 4. Работа с выписками (Пагинация) -```php -use Apoloz\AlfaBank\Requests\Statement\GetTransactionsRequest; - -// Автоматическая итерация через все страницы -$paginator = AlfaBank::paginate(new GetTransactionsRequest( - accountNumber: '40702...', - executeDateFrom: '2026-01-01', - executeDateTo: '2026-01-18' +$response = Sbp::send(new GetQrCodeRequest( + new QrCodeRequestData( + termNo: '90080567', + amount: '10000', // 100.00 RUB + paymentPurpose: 'Пополнение кошелька #123' + ) )); -foreach ($paginator->items() as $transaction) { - echo "Транзакция {" . $transaction->uuid . ": " . $transaction->amount['amount'] . " RUB\n"; -} +echo "QR URL: " . $response->dto()->payload; ``` -### 5. Самозанятые (Справочники и выплаты) +### 2. Идентификация платежа (BaaS) +Когда платеж пришел на номинальный счет, его нужно привязать к бенефициару: + ```php -use Apoloz\AlfaBank\Requests\SelfEmployed\GetActivitiesRequest; +use Apoloz\AlfaBank\Requests\NominalAccounts\Identification\IdentifyTransactionRequest; +use Apoloz\AlfaBank\Data\NominalAccounts\Identification\IdentifyRequestData; +use Apoloz\AlfaBank\Data\NominalAccounts\Identification\AmountDistributionData; -// Получение списка разрешенных видов деятельности -$activities = AlfaBank::send(new GetActivitiesRequest()); +$data = new IdentifyRequestData( + transactionId: '1220112MOCO#DS4001415', + accountNumber: '40702810...', + amountDistribution: AmountDistributionData::collect([ + ['beneficiaryId' => 'BEN-001', 'amount' => '100.00'] + ], DataCollection::class), + digestSignatures: ... // CMS подпись +); -foreach ($activities as $activity) { - echo "{$activity->code}: {$activity->name}\n"; -} +AlfaBank::send(new IdentifyTransactionRequest($data)); ``` -### 6. Номинальные счета (Полный цикл) -Сценарий создания бенефициара и выплаты с подписью: - +### 3. Работа с номинальными счетами (Бенефициары) ```php use Apoloz\AlfaBank\Requests\NominalAccounts\Beneficiaries\CreateBeneficiaryRequest; -use Apoloz\AlfaBank\Requests\NominalAccounts\Payouts\CreatePayoffRequest; -// 1. Создание бенефициара с CMS подписью -$response = $baas->send(new CreateBeneficiaryRequest($beneficiaryData)); +// Регистрация нового бенефициара (Физлицо/Юрлицо) +$response = AlfaBank::send(new CreateBeneficiaryRequest($beneficiaryData)); +$id = $response->dto()->requestId; -// 2. Инициирование выплаты -$payoff = $baas->send(new CreatePayoffRequest($payoffData)); -echo "Статус выплаты: " . $payoff->dto()->status; +// Запуск скоринга (верификации) +AlfaBank::send(new ScoreBeneficiaryRequest($id)); ``` --- ## Продвинутые возможности -### Диагностика без Laravel +### Автоматическая пагинация ```php -use Apoloz\AlfaBank\AlfaBank; +$paginator = AlfaBank::paginate(new GetTransactionsRequest(...)); -$ok = AlfaBank::check( - certificatePath: 'cert.pem', - privateKeyPath: 'key.pem', - clientId: '...', - clientSecret: '...' -); -``` - -### Логирование с маскировкой данных -SDK автоматически скрывает номера карт, токены и подписи в логах. -```php -$connector = AlfaBank::getFacadeRoot(); -$connector->withLogging(Log::channel('daily')->getLogger()); -``` - -### Обработка Webhooks (Laravel) -```php -// routes/api.php -Route::alfaWebhooks('/webhooks/alfa'); - -// Listener -public function handle(AlfaWebhookReceived $event) { - $data = $event->webhook->data; - // $data будет объектом TransactionWebhookData или SbpPaymentWebhookData +foreach ($paginator->items() as $transaction) { + // Каждая итерация автоматически подгружает следующую страницу при необходимости } ``` ---- +### Webhook Handling (Laravel) +```php +// Регистрация роута +Route::alfaWebhooks('/api/alfa/webhooks'); + +// Обработка в Listener +public function handle(AlfaWebhookReceived $event) { + if ($event->webhook->object === 'ul_transaction_default') { + $tx = $event->webhook->data; // TransactionWebhookData + Log::info("Пришел платеж на сумму: " . $tx->amount['amount']); + } +} +``` ## Лицензия -MIT. Автор: Anatoliy Poloz. \ No newline at end of file +MIT. Автор: Anatoliy Poloz.