laravel-asanimza maintained by sarkhanrasimoghlu
Description
Laravel package for Asan İmza mobile authentication and digital signing via JSON-RPC 2.0 proxy API
Author
Last update
2026/03/16 10:37
(dev-master)
License
Downloads
1
Tags
Laravel Asan İmza
Laravel package for Asan İmza — Azerbaijan's mobile authentication and digital signing system. Communicates with the Asan İmza proxy server via JSON-RPC 2.0 protocol.
Requirements
- PHP ^8.3
- Laravel ^12.0
- Asan İmza proxy server running (default:
http://localhost:8090)
Installation
composer require sarkhanrasimoghlu/laravel-asanimza
Publish the configuration file:
php artisan vendor:publish --tag=asanimza-config
Configuration
Add the following to your .env file:
ASANIMZA_BASE_URL=http://localhost:8090
ASANIMZA_SERVICE_NAME=AsanDoc
ASANIMZA_LANGUAGE=aze
ASANIMZA_TIMEOUT=30
ASANIMZA_LOG_ENABLED=true
ASANIMZA_LOG_CHANNEL=stack
| Variable | Default | Description |
|---|---|---|
ASANIMZA_BASE_URL |
http://localhost:8090 |
Asan İmza proxy server URL |
ASANIMZA_SERVICE_NAME |
AsanDoc |
Registered service name |
ASANIMZA_LANGUAGE |
aze |
Default language (aze, rus, eng) |
ASANIMZA_TIMEOUT |
30 |
HTTP request timeout (seconds) |
ASANIMZA_LOG_ENABLED |
true |
Enable/disable request logging |
ASANIMZA_LOG_CHANNEL |
stack |
Laravel log channel |
Usage
Inject AsanImzaInterface via constructor or method injection:
use Sarkhanrasimoghlu\AsanImza\Contracts\AsanImzaInterface;
Authentication
Step 1: Start authentication
public function login(AsanImzaInterface $asanImza)
{
$result = $asanImza->authenticate('+994501234567', 'userId123');
// Show verification code to the user
// $result->verificationCode — user must confirm this on their phone
// $result->transactionId — needed for status check
// $result->certificate — needed for status check
// $result->challenge — needed for status check
return response()->json([
'transactionId' => $result->transactionId,
'verificationCode' => $result->verificationCode,
'certificate' => $result->certificate,
'challenge' => $result->challenge,
]);
}
Step 2: Check authentication status (polling)
public function checkAuth(AsanImzaInterface $asanImza, Request $request)
{
$status = $asanImza->getAuthStatus(
transactionId: $request->input('transactionId'),
certificate: $request->input('certificate'),
challenge: $request->input('challenge'),
);
if ($status->status === \Sarkhanrasimoghlu\AsanImza\Enums\AuthStatus::USER_AUTHENTICATED) {
// Authentication successful
// $status->signature contains the base64-encoded signature
}
return response()->json([
'status' => $status->status->value,
]);
}
Get Certificate Data
Extract user information from a certificate:
$certData = $asanImza->getCertificateData($certificate);
$certData->firstName; // "John"
$certData->surname; // "Doe"
$certData->personalCode; // "1234567"
$certData->organizationName; // nullable
$certData->certType; // CertType enum (AUTHENTICATION, CITIZEN_SIGNING, etc.)
Digital Signing
Step 1: Get signing certificates
$certs = $asanImza->getSigningCertificates('+994501234567', 'userId123');
// Returns: ['certId1' => 'base64cert1', 'certId2' => 'base64cert2']
Step 2: Sign files
use Sarkhanrasimoghlu\AsanImza\DTOs\DataFile;
$dataFiles = [
new DataFile(
content: base64_encode(file_get_contents('/path/to/document.pdf')),
fileName: 'document.pdf',
mimeType: 'application/pdf',
),
];
$result = $asanImza->signFiles(
dataFiles: $dataFiles,
phoneNumber: '+994501234567',
userId: 'userId123',
certIdentifier: 'certId1',
certificate: $certs['certId1'],
);
// $result->transactionId
// $result->verificationCode — show to user
// $result->hash — needed for status check
// $result->container — needed for status check
Step 3: Check signing status (polling)
$status = $asanImza->getSignFileStatus(
transactionId: $result->transactionId,
hash: $result->hash,
container: $result->container,
certificate: $certs['certId1'],
);
if ($status->status === \Sarkhanrasimoghlu\AsanImza\Enums\SignStatus::SIGNATURE_CREATED) {
// $status->container — signed container (base64)
$signedContent = base64_decode($status->container);
}
Error Handling
All exceptions extend AsanImzaException:
use Sarkhanrasimoghlu\AsanImza\Exceptions\AsanImzaException;
use Sarkhanrasimoghlu\AsanImza\Exceptions\JsonRpcException;
try {
$result = $asanImza->authenticate('+994501234567', 'userId123');
} catch (JsonRpcException $e) {
// JSON-RPC error from Asan İmza proxy
$e->getErrorCode(); // e.g., 2004
$e->getErrorMessage(); // e.g., "Unknown phone number"
$e->getContext(); // ['error_code' => 2004, 'error_message' => '...']
} catch (AsanImzaException $e) {
// HTTP or parsing error
$e->getMessage();
$e->getContext();
}
Common Error Codes
| Code | Description |
|---|---|
| 1002 | Service overloaded |
| 2004 | Unknown phone number |
| 2013 | No authentication certificate |
| 2017 | Phone number and user ID are not related |
| 2018 | Authentication certificate is not valid |
| 2020 | No signing certificate |
| 2021 | Signing certificate is not valid |
| 2022 | Forbidden service name |
| -32700 | JSON-RPC parse error |
| -32600 | Invalid request |
| -32601 | Method not found |
Enums
AuthStatus
| Value | Description |
|---|---|
USER_AUTHENTICATED |
Authentication successful |
OUTSTANDING_TRANSACTION |
Waiting for user confirmation |
NOT_VALID |
Transaction not valid |
EXPIRED_TRANSACTION |
Transaction expired |
USER_CANCEL |
User cancelled on phone |
MID_NOT_READY |
Mobile ID not ready |
SENDING_ERROR |
Error sending to phone |
SIM_ERROR |
SIM card error |
INTERNAL_ERROR |
Internal system error |
SignStatus
Same values as AuthStatus, except USER_AUTHENTICATED is replaced by SIGNATURE_CREATED.
CertType
| Value | Description |
|---|---|
| 0 | Authentication |
| 1 | Citizen signing |
| 2 | Business signing |
| 3 | Governmental signing |
| 4 | Youth personal |
| 5 | Digital stamp |
License
MIT