171 lines
6.5 KiB
Markdown
171 lines
6.5 KiB
Markdown
# Alfa Bank SDK (Unofficial)
|
||
|
||
[](https://github.com/apoloz/alfa-bank-sdk/actions)
|
||
[](https://phpstan.org/)
|
||
|
||
Профессиональная PHP-библиотека для интеграции с API Альфа-Банка (BaaS и СБП). Построена на базе [Saloon v3](https://docs.saloon.dev) и [Spatie Laravel Data](https://spatie.be/docs/laravel-data).
|
||
|
||
## Требования
|
||
|
||
- PHP 8.2+
|
||
- [Saloon](https://docs.saloon.dev) v3.0+
|
||
- [Spatie Laravel Data](https://spatie.be/docs/laravel-data)
|
||
|
||
## Подключение и Безопасность
|
||
|
||
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 (Номинальные счета)
|
||
|
||
**Шаги для получения доступа:**
|
||
1. Регистрация в личном кабинете партнера.
|
||
2. Получение `client_id` и `client_secret` для OAuth2.
|
||
3. Регистрация публичного ключа для проверки подписей выплат.
|
||
|
||
**Поток данных и подпись:**
|
||
* **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 Client as Покупатель
|
||
participant SBP as SDK (SBP Connector)
|
||
participant API as Alfa Bank API
|
||
participant BaaS as SDK (BaaS Connector)
|
||
|
||
Note over SBP, API: MTLS + JCS Signature
|
||
SBP->>API: 1. GetQrCodeRequest(NominalAcc)
|
||
API-->>SBP: 2. QR Payload (URL)
|
||
Client->>API: 3. Оплата в приложении (СБП)
|
||
|
||
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\Sbp;
|
||
use Apoloz\AlfaBank\Sbp\Requests\GetQrCodeRequest;
|
||
use Apoloz\AlfaBank\Sbp\Data\QrCodeRequestData;
|
||
|
||
$response = Sbp::send(new GetQrCodeRequest(
|
||
new QrCodeRequestData(
|
||
termNo: '90080567',
|
||
amount: '10000', // 100.00 RUB
|
||
paymentPurpose: 'Пополнение кошелька #123'
|
||
)
|
||
));
|
||
|
||
echo "QR URL: " . $response->dto()->payload;
|
||
```
|
||
|
||
### 2. Идентификация платежа (BaaS)
|
||
Когда платеж пришел на номинальный счет, его нужно привязать к бенефициару:
|
||
|
||
```php
|
||
use Apoloz\AlfaBank\Requests\NominalAccounts\Identification\IdentifyTransactionRequest;
|
||
use Apoloz\AlfaBank\Data\NominalAccounts\Identification\IdentifyRequestData;
|
||
use Apoloz\AlfaBank\Data\NominalAccounts\Identification\AmountDistributionData;
|
||
|
||
$data = new IdentifyRequestData(
|
||
transactionId: '1220112MOCO#DS4001415',
|
||
accountNumber: '40702810...',
|
||
amountDistribution: AmountDistributionData::collect([
|
||
['beneficiaryId' => 'BEN-001', 'amount' => '100.00']
|
||
], DataCollection::class),
|
||
digestSignatures: ... // CMS подпись
|
||
);
|
||
|
||
AlfaBank::send(new IdentifyTransactionRequest($data));
|
||
```
|
||
|
||
### 3. Работа с номинальными счетами (Бенефициары)
|
||
```php
|
||
use Apoloz\AlfaBank\Requests\NominalAccounts\Beneficiaries\CreateBeneficiaryRequest;
|
||
|
||
// Регистрация нового бенефициара (Физлицо/Юрлицо)
|
||
$response = AlfaBank::send(new CreateBeneficiaryRequest($beneficiaryData));
|
||
$id = $response->dto()->requestId;
|
||
|
||
// Запуск скоринга (верификации)
|
||
AlfaBank::send(new ScoreBeneficiaryRequest($id));
|
||
```
|
||
|
||
---
|
||
|
||
## Продвинутые возможности
|
||
|
||
### Автоматическая пагинация
|
||
```php
|
||
$paginator = AlfaBank::paginate(new GetTransactionsRequest(...));
|
||
|
||
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.
|