14 KiB
Alfa Bank SDK (Unofficial)
This is an unofficial PHP SDK for the Alfa Bank API, built using Saloon and Spatie Laravel Data.
Requirements
- PHP 8.2+
- OpenSSL (for certificate generation/handling)
- Saloon v3.0+
- Spatie Laravel Data
- phpseclib (for Card Encryption)
Installation
composer require apoloz/alfa-bank-sdk
Security & Setup (Crucial)
Alfa Bank uses a comprehensive security model requiring two distinct sets of keys:
- Transport (mTLS): To establish the SSL connection.
- Signing (JWS/CMS): To digitally sign the request body.
Where to get keys?
- Sandbox: Provided by the bank support or downloaded from the Developer Portal (usually as
.pfxor.zip). - Production:
- Transport (mTLS): Generate a private key and CSR using OpenSSL (
openssl genrsa,openssl req). Send the CSR toalfa_api@alfabank.ru. The bank will reply with your Certificate. - Signing: Generated by you (the client). The public certificate must be registered in "Alfa Business Online" or sent to your onboarding manager.
- Transport (mTLS): Generate a private key and CSR using OpenSSL (
1. Converting PFX to PEM
If the bank provided a .pfx file for signing, you must convert it to PEM format:
# Extract Private Key
openssl pkcs12 -in signing.pfx -nocerts -out signing_key.pem -nodes
# Extract Public Certificate
openssl pkcs12 -in signing.pfx -clcerts -nokeys -out signing_cert.pem
2. Initialization
You can now initialize the SDK with both key pairs:
use Apoloz\AlfaBank\AlfaBank;
use Apoloz\AlfaBank\Enums\Environment;
$baas = AlfaBank::baas(
// Transport Keys (mTLS)
certificatePath: '/path/to/transport_cert.pem',
privateKeyPath: '/path/to/transport_key.pem',
// Signing Keys (Business Logic) - Optional, defaults to transport keys if not set
signingCertificatePath: '/path/to/signing_cert.pem',
signingPrivateKeyPath: '/path/to/signing_key.pem',
environment: Environment::SANDBOX,
caBundlePath: '/path/to/root_ca_bundle.crt'
);
Core Usage
Authentication (BaaS)
Use the login method to perform OAuth Client Credentials flow:
$baas->login(
clientId: 'your-client-id',
clientSecret: 'your-client-secret'
);
Making Requests
SBP: Generate QR Code
use Apoloz\AlfaBank\Sbp\Requests\GetQrCodeRequest;
use Apoloz\AlfaBank\Sbp\Data\QrCodeRequestData;
$sbp = AlfaBank::sbp(
certificatePath: '...',
privateKeyPath: '...',
keyNameAlias: '9728109955', // Terminal ID
signingPrivateKeyPath: '/path/to/signing_key.pem' // Specific signing key for SBP body
);
$response = $sbp->send(new GetQrCodeRequest(
new QrCodeRequestData(TermNo: '...', amount: '100')
));
$link = $response->dto()->payload;
Nominal Accounts
$response = $baas->send(new CreateBeneficiaryRequest($payload));
Self-Employed (Payouts & Status)
The SDK supports managing self-employed beneficiaries, checking their FTS status, and processing payouts.
Check Taxpayer Status
use Apoloz\AlfaBank\Requests\SelfEmployed\GetTaxpayerStatusRequest;
use Apoloz\AlfaBank\Data\SelfEmployed\TaxpayerStatusRequestData;
$payload = new TaxpayerStatusRequestData(
externalId: 'unique-id',
selfemployedVatinList: ['123456789012']
);
$response = $baas->send(new GetTaxpayerStatusRequest($payload));
$status = $response->dto()->taxpayerStatusList[0];
Process Payout
use Apoloz\AlfaBank\Requests\SelfEmployed\CreatePayoutRequest;
use Apoloz\AlfaBank\Data\SelfEmployed\PayoutRequestData;
$payload = new PayoutRequestData(
externalId: 'ext-id-456',
company: ['vatin' => '7700000000'],
requisite: [
['amount' => 1000, 'vatin' => '112233445566']
]
);
$response = $baas->send(new CreatePayoutRequest($payload));
File Exchange
Upload and download files securely.
use Apoloz\AlfaBank\Requests\FileExchange\UploadFileRequest;
use Apoloz\AlfaBank\Requests\FileExchange\DownloadFileRequest;
// Upload
$stream = fopen('path/to/file', 'r');
$baas->send(new UploadFileRequest($uploadUrl, $stream, $fileSize));
// Download
$response = $baas->send(new DownloadFileRequest($downloadUrl));
$content = $response->body();
Payments (RUR Payment Orders)
Create standard payment orders and check their status.
use Apoloz\AlfaBank\Requests\Payments\CreatePaymentRequest;
use Apoloz\AlfaBank\Data\Payments\PaymentData;
$payload = new PaymentData(
amount: 100.50,
date: '2023-10-25',
externalId: 'order-12345',
operationCode: '01',
payeeAccount: '40702...',
payeeBankBic: '044525225',
payeeName: 'Partner LLC',
payerAccount: '40702...',
payerBankBic: '044525593',
payerBankCorrAccount: '30101...',
payerInn: '7700000000',
payerName: 'My Company',
priority: '5',
purpose: 'Payment for services'
);
// Create Payment
$baas->send(new CreatePaymentRequest($payload));
// Check State
use Apoloz\AlfaBank\Requests\Payments\GetPaymentStateRequest;
$state = $baas->send(new GetPaymentStateRequest('order-12345'))->dto();
echo $state->bankStatus; // e.g. ACCEPTED
Cards
Retrieve a list of client cards.
use Apoloz\AlfaBank\Requests\Cards\GetCardsRequest;
$response = $baas->send(new GetCardsRequest());
foreach ($response->dto() as $card) {
echo $card->maskedNumber . ' - ' . $card->status;
}
B2C Payouts (SBP via Phone)
Send money to individuals using their phone number through SBP.
use Apoloz\AlfaBank\Requests\B2C\CreateB2CPaymentRequest;
use Apoloz\AlfaBank\Data\B2C\B2CPaymentRequestData;
use Apoloz\AlfaBank\Data\B2C\B2CClientData;
use Apoloz\AlfaBank\Data\B2C\B2CPaymentRecipientData;
$payload = new B2CPaymentRequestData(
client: new B2CClientData(b2cClientId: '...', partnerId: 123),
inn: '7700000000',
account: '40702...',
total: 100.53,
signedBody: '...base64_signature...',
payments: B2CPaymentRecipientData::collect([
[
'phone' => '79001112233',
'amount' => 100.53,
'nspkBankId' => '100000000001',
'sequence' => 'unique-seq-1',
'name' => ['first' => 'Ivan', 'last' => 'Ivanov']
]
], DataCollection::class)
);
$baas->send(new CreateB2CPaymentRequest($payload));
Payment Registries (Batch Ruble Payments)
Create a registry for multiple ruble payments and sign it.
use Apoloz\AlfaBank\Requests\Registries\CreateRegistryRequest;
use Apoloz\AlfaBank\Data\Registries\RegistryRequestData;
use Apoloz\AlfaBank\Data\Registries\RegistryPaymentData;
$payload = new RegistryRequestData(
payments: RegistryPaymentData::collect([
[
'amount' => 1000.0,
'date' => '2023-11-01',
'payeeAccount' => '40702...',
'payeeBankBic' => '044525225',
'payeeInn' => '7700000000',
'payeeName' => 'Vendor LLC',
'payerAccount' => '40702...',
'purpose' => 'Batch payment part 1'
]
], DataCollection::class),
description: 'Weekly payroll'
);
$response = $baas->send(new CreateRegistryRequest($payload));
$registryId = $response->json('id');
// Sign Registry
use Apoloz\AlfaBank\Requests\Registries\SignRegistryRequest;
use Apoloz\AlfaBank\Data\Registries\RegistrySignatureData;
use Spatie\LaravelData\DataCollection;
$signatures = RegistrySignatureData::collect([
[
'base64Encoded' => '...', // Base64 signature
'signatureType' => 'RSA',
'certificateUuid' => '...'
]
], DataCollection::class);
$baas->send(new SignRegistryRequest($registryId, $signatures));
Customer Info
Get organization profile.
use Apoloz\AlfaBank\Requests\CustomerInfo\GetCustomerInfoRequest;
$info = $baas->send(new GetCustomerInfoRequest())->dto();
echo $info->fullName;
Limits
Get client's operation limits.
use Apoloz\AlfaBank\Requests\Limits\GetGeneralLimitsRequest;
$response = $baas->send(new GetGeneralLimitsRequest());
$limits = $response->json();
Debit Cards
Apply for a new debit card.
use Apoloz\AlfaBank\Requests\DebitCards\CreateDebitCardApplicationRequest;
use Apoloz\AlfaBank\Data\DebitCards\DebitCardApplicationData;
$payload = new DebitCardApplicationData(
embossingName: 'IVAN IVANOV',
firstName: 'Иван',
lastName: 'Иванов',
middleName: 'Иванович',
mobilePhone: '79001112233',
passportBirthDate: '1990-01-01',
sex: 'm',
sopdConfirmed: true
);
$baas->send(new CreateDebitCardApplicationRequest($payload));
User Compliance
Check user compliance for loans.
use Apoloz\AlfaBank\Requests\Compliance\GetUserComplianceRequest;
$baas->send(new GetUserComplianceRequest());
DFA (Digital Financial Assets)
List initial placements.
use Apoloz\AlfaBank\Requests\DFA\GetDfaInitialPlacementListRequest;
$baas->send(new GetDfaInitialPlacementListRequest(limit: 5));
Currency Rates
Get currency rates by office.
use Apoloz\AlfaBank\Requests\Rates\GetOfficeRatesRequest;
$baas->send(new GetOfficeRatesRequest());
Escrow Accounts
Manage construction projects and escrow orders.
use Apoloz\AlfaBank\Requests\Escrow\GetBuildProjectsRequest;
$projects = $baas->send(new GetBuildProjectsRequest())->json();
Power of Attorney (Poa)
Request and check status of digital POAs.
use Apoloz\AlfaBank\Requests\Poa\CreatePoaRequest;
$response = $baas->send(new CreatePoaRequest('poa-123', '7700000000'));
$uuid = $response->json('requestUuid');
Loyalty
Access bonus accounts and transaction history.
use Apoloz\AlfaBank\Requests\Loyalty\GetLoyaltyAccountsRequest;
$accounts = $baas->send(new GetLoyaltyAccountsRequest())->json();
Reports
Order certificates and reports.
use Apoloz\AlfaBank\Requests\Reports\CreateAccountBalanceReportRequest;
$baas->send(new CreateAccountBalanceReportRequest(['40702...'], 'eng'));
Crypto Service
Manage encryption and signing certificates.
use Apoloz\AlfaBank\Requests\Crypto\GetCertificatesRequest;
$certificates = $baas->send(new GetCertificatesRequest())->json();
Partner (MMB)
Access partner program data and applications.
use Apoloz\AlfaBank\Requests\Partner\GetPartnerApplicationsRequest;
$apps = $baas->send(new GetPartnerApplicationsRequest())->json();
Miscellaneous
- Bonus Numbers:
$baas->send(new GetBonusNumbersRequest()); - Credit Offers:
$baas->send(new GetCreditOffersRequest()); - Self-encashment:
$baas->send(new CreateSelfEncashmentRegistryRequest($data)); - Business Lounge:
$baas->send(new GetLoungeBalanceRequest()); - Scoring:
$baas->send(new GetComplianceScoreRequest('7700000000')); - Security:
$baas->send(new GetSubscriptionsRequest()); - Logistics:
$baas->send(new GetDeliveriesRequest('...')); - Webhooks:
$baas->send(new GetWebhooksRequest()); - 1C Integration:
$baas->send(new CheckMerchantRequest('MF123', 'Basic ...')); - Claims:
$baas->send(new ResolveClaimRequest('ID', $data)); - Orders (Travel/Afisha):
$baas->send(new CreateTravelOrderRequest($data)); - Salary Project:
$baas->send(new CreatePayrollApplicationRequest($payload)); - Cloud Signature:
$baas->send(new SubmitSigningRequest('REQ-ID')); - Aff Integration:
$baas->send(new CheckComplianceRequest('INN', 'Name')); - Digital Ruble:
$sbp->send(new CreateUniQrRequest($uniQrData));
Signing Data (CMS)
For requests requiring a digital signature (e.g., Payments), you must canonicalize and sign the data manually.
use Apoloz\AlfaBank\Utils\CmsSigner;
use Apoloz\AlfaBank\Data\NominalAccounts\Payouts\DigestSignatureData;
use Spatie\LaravelData\DataCollection;
// 1. Prepare data
$fields = [
'amount' => 100.50,
// ... other fields
];
// 2. Canonicalize & Sign
$json = CmsSigner::canonicalize($fields);
$cert = file_get_contents('/path/to/signing_cert.pem');
$key = file_get_contents('/path/to/signing_key.pem');
$signature = CmsSigner::sign($json, $cert, $key);
// 3. Attach to DTO
$paymentData->digestSignatures = DigestSignatureData::collect([
[
'base64Encoded' => $signature,
'signatureType' => 'CMS'
]
], DataCollection::class);
Advanced Features
Pagination
The SDK supports automatic pagination for list endpoints:
use Apoloz\AlfaBank\Requests\Accounts\GetAccountsRequest;
$paginator = $baas->paginate(new GetAccountsRequest());
foreach ($paginator as $account) {
// Each item is processed automatically
}
Laravel Integration
The package supports auto-discovery. Publish the config file:
php artisan vendor:publish --tag=alfa-bank-config
Configure your .env:
ALFA_BAAS_CERT_PATH=/path/to/transport_cert.pem
# ... other settings
ALFA_WEBHOOK_USER=your_webhook_user
ALFA_WEBHOOK_PASSWORD=your_webhook_password
Webhook Handling (Laravel)
The SDK provides a built-in controller and route macro to handle incoming webhooks and dispatch Laravel events.
- Register the route in
routes/api.php:
Route::alfaWebhooks('/webhooks/alfa');
- Listen for the event in
app/Providers/EventServiceProvider.php:
use Apoloz\AlfaBank\Laravel\Events\AlfaWebhookReceived;
protected $listen = [
AlfaWebhookReceived::class => [
\App\Listeners\HandleAlfaWebhook::class,
],
];
- Handle the DTO in your listener:
public function handle(AlfaWebhookReceived $event)
{
$webhook = $event->webhook; // BaseWebhookData DTO
if ($webhook->object === 'ul_transaction_default') {
$transaction = $webhook->data;
// ...
}
}
Error Handling
The SDK throws Apoloz\AlfaBank\Exceptions\AlfaBankException when the API returns an error.
try {
$baas->send($request);
} catch (\Apoloz\AlfaBank\Exceptions\AlfaBankException $e) {
echo $e->getErrorCode(); // e.g. "invalid_token" or "RQ05014"
echo $e->getMessage();
}
Utilities
- Card PAN Encryption:
CardEncryptor::encrypt($pan, $pubKey) - CMS Signing:
CmsSigner::sign($data, $cert, $key) - JWS/JWE:
JwsSignerandJweEncryptorfor transport security.
Diagnostics
Health Check (Laravel)
Run the built-in Artisan command to verify your mTLS certificates and connection:
php artisan alfa:check
Logging
Attach a PSR-3 logger to debug requests (sensitive data redacted):
$baas->withLogging(Log::getLogger());
License
MIT