PHP code example of letbar / loketqris-sdk

1. Go to this page and download the library: Download letbar/loketqris-sdk library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

letbar / loketqris-sdk example snippets


// config/loketqris-sdk.php

return [
    // LoketQRIS API base URL
    'base_url' => env('LOKETQRIS_BASE_URL'),

    // Default credentials (optional for multi-tenant apps)
    'credentials' => [
        'kode_loket' => env('LOKETQRIS_KODE_LOKET'),
        'api_key' => env('LOKETQRIS_API_KEY'),
        'client_secret' => env('LOKETQRIS_CLIENT_SECRET'),
    ],

    // Webhook routes configuration
    'routes' => [
        'enabled' => true,           // Set false to handle routes yourself
        'prefix' => '',              // Route prefix
        'token_path' => '/b2b/token',
        'notify_path' => '/qris/notify',
        'middleware' => ['api'],
    ],

    // Access token TTL in seconds
    'token_ttl' => env('LOKETQRIS_TOKEN_TTL', 300),

    // Response codes mapping
    'response_codes' => [
        'success' => ['2004700', '2005100'],
        'pending' => ['2005101'],
    ],
];

use Letbar\LoketQrisSdk\Facades\LoketQris;
use Letbar\LoketQrisSdk\DTOs\GenerateQrisRequest;

// Using config credentials
$request = GenerateQrisRequest::make(
    partnerReferenceNo: 'INV-2026-001',
    amount: 50000,
    validTime: 900  // seconds (optional, default: 900)
);

$response = LoketQris::generate($request);

if ($response->isSuccessful()) {
    $qrContent = $response->getQrContent();
    $referenceNo = $response->getPartnerReferenceNo();
}

// Access raw response
$rawData = $response->toArray();
$customField = $response->get('customField', 'default');

use Letbar\LoketQrisSdk\Facades\LoketQris;
use Letbar\LoketQrisSdk\DTOs\QueryQrisRequest;

$request = QueryQrisRequest::make('INV-2026-001');

$response = LoketQris::query($request);

if ($response->isSuccessful()) {
    if ($response->isPaid()) {
        $paidTime = $response->getPaidTime();
        $amount = $response->getAmountValue();
        $currency = $response->getAmountCurrency();

        // Additional info
        $issuerId = $response->getAdditionalInfoValue('issuerID');
        $paymentRef = $response->getAdditionalInfoValue('paymentReferenceNo');
    }

    if ($response->isPending()) {
        // Transaction still pending
    }
}

use Letbar\LoketQrisSdk\DTOs\CredentialData;
use Letbar\LoketQrisSdk\DTOs\GenerateQrisRequest;
use Letbar\LoketQrisSdk\Facades\LoketQris;

// Get tenant credentials from your database
$tenant = Credential::find($tenantId);

$credential = CredentialData::make(
    kodeLoket: $tenant->kode_loket,
    apiKey: $tenant->api_key,
    clientSecret: $tenant->client_secret
);

// Or from array
$credential = CredentialData::fromArray([
    'kode_loket' => $tenant->kode_loket,
    'api_key' => $tenant->api_key,
    'client_secret' => $tenant->client_secret,
]);

$request = GenerateQrisRequest::make('INV-001', 50000);

// Pass credential as second argument
$response = LoketQris::generate($request, $credential);

use Letbar\LoketQrisSdk\LoketQrisClient;

$client = app(LoketQrisClient::class);

$response = $client->generate($request, $credential);

// app/Providers/EventServiceProvider.php
use Letbar\LoketQrisSdk\Events\QrisGenerated;
use Letbar\LoketQrisSdk\Events\NotificationReceived;

protected $listen = [
    QrisGenerated::class => [
        LogQrisGenerated::class,
    ],
    NotificationReceived::class => [
        ProcessPaymentNotification::class,
    ],
];

// app/Listeners/LogQrisGenerated.php
namespace App\Listeners;

use Illuminate\Support\Facades\Log;
use Letbar\LoketQrisSdk\Events\QrisGenerated;

class LogQrisGenerated
{
    public function handle(QrisGenerated $event): void
    {
        Log::info('QRIS generated', [
            'reference' => $event->request->partnerReferenceNo,
            'amount' => $event->request->amount,
            'qr_content' => $event->response->getQrContent(),
            'kode_loket' => $event->credential->kodeLoket,
        ]);
    }
}

// app/Listeners/ProcessPaymentNotification.php
namespace App\Listeners;

use App\Models\Transaction;
use Letbar\LoketQrisSdk\Events\NotificationReceived;

class ProcessPaymentNotification
{
    public function handle(NotificationReceived $event): void
    {
        $payload = $event->payload;

        if (!$payload->isSuccessful()) {
            return;
        }

        $transaction = Transaction::where(
            'reference_no',
            $payload->getOriginalPartnerReferenceNo()
        )->first();

        if ($transaction) {
            $transaction->update([
                'status' => 'paid',
                'paid_at' => $payload->getPaymentDate(),
                'payment_reference' => $payload->getPaymentReferenceNo(),
            ]);
        }
    }
}

// config/loketqris-sdk.php
'routes' => [
    'enabled' => true,
    'prefix' => 'api/v1',           // Routes: /api/v1/b2b/token
    'token_path' => '/auth/token',   // Custom path
    'notify_path' => '/webhooks/qris',
    'middleware' => ['api', 'throttle:60,1'],
],

// config/loketqris-sdk.php
'routes' => [
    'enabled' => false,
],

// routes/api.php
use Letbar\LoketQrisSdk\Http\Controllers\TokenController;
use Letbar\LoketQrisSdk\Http\Controllers\NotificationController;
use Letbar\LoketQrisSdk\Http\Middleware\VerifyLoketQrisSignature;
use Letbar\LoketQrisSdk\Http\Middleware\VerifyBearerToken;

Route::post('/custom/token', [TokenController::class, 'store'])
    ->middleware(VerifyLoketQrisSignature::class);

Route::post('/custom/notify', [NotificationController::class, 'store'])
    ->middleware(VerifyBearerToken::class);

// app/Services/TenantCredentialResolver.php
namespace App\Services;

use App\Models\Credential;
use Letbar\LoketQrisSdk\Contracts\CredentialResolver;

class TenantCredentialResolver implements CredentialResolver
{
    public function resolveClientSecret(string $kodeLoket, string $apiKey): ?string
    {
        $credential = Credential::query()
            ->where('kode_loket', $kodeLoket)
            ->where('api_key', $apiKey)
            ->first();

        return $credential?->client_secret;
    }
}

// app/Providers/AppServiceProvider.php
use App\Services\TenantCredentialResolver;
use Letbar\LoketQrisSdk\Contracts\CredentialResolver;

public function register(): void
{
    $this->app->bind(CredentialResolver::class, TenantCredentialResolver::class);
}

use Letbar\LoketQrisSdk\Exceptions\ApiRequestException;
use Letbar\LoketQrisSdk\Exceptions\ConfigurationException;
use Letbar\LoketQrisSdk\Exceptions\InvalidCredentialException;
use Letbar\LoketQrisSdk\Exceptions\InvalidSignatureException;

try {
    $response = LoketQris::generate($request);
} catch (ConfigurationException $e) {
    // Missing base_url or credentials
} catch (InvalidCredentialException $e) {
    // Empty or invalid credential fields
} catch (ApiRequestException $e) {
    // API returned an error
    $httpStatus = $e->getHttpStatusCode();
    $responseCode = $e->getResponseCode();
    $responseBody = $e->getResponseBody();
}

use Carbon\Carbon;
use Letbar\LoketQrisSdk\SignatureGenerator;
use Letbar\LoketQrisSdk\DTOs\CredentialData;

// Generate signature
$result = SignatureGenerator::generate(
    kodeLoket: 'LK000001',
    clientSecret: 'your-secret',
    timestamp: Carbon::now()  // optional
);

$timestamp = $result['timestamp'];   // ISO 8601 format
$signature = $result['signature'];   // Base64 encoded

// Or from credential
$credential = CredentialData::make('LK000001', 'api-key', 'secret');
$result = SignatureGenerator::fromCredential($credential);

// Verify signature
$isValid = SignatureGenerator::verify(
    kodeLoket: 'LK000001',
    clientSecret: 'your-secret',
    timestamp: '2026-01-28T12:00:00+07:00',
    signature: 'base64-signature'
);

CredentialData::make(string $kodeLoket, string $apiKey, string $clientSecret)
CredentialData::fromArray(array $data)
CredentialData::fromConfig()

$credential->kodeLoket;
$credential->apiKey;
$credential->clientSecret;
$credential->toArray();
$credential->validate();  // throws InvalidCredentialException

GenerateQrisRequest::make(
    string $partnerReferenceNo,
    string|float|int $amount,
    string|int $validTime = '900'
)

$request->partnerReferenceNo;
$request->amount;          // Formatted as "10000.00"
$request->validTime;
$request->toArray();

$response->isSuccessful(): bool
$response->getResponseCode(): ?string
$response->getResponseMessage(): ?string
$response->getPartnerReferenceNo(): ?string
$response->getQrContent(): ?string
$response->toArray(): array
$response->get(string $key, mixed $default = null): mixed

QueryQrisRequest::make(string $originalPartnerReferenceNo)

$request->originalPartnerReferenceNo;
$request->toArray();

$response->isSuccessful(): bool
$response->isPending(): bool
$response->isPaid(): bool
$response->getResponseCode(): ?string
$response->getResponseMessage(): ?string
$response->getOriginalPartnerReferenceNo(): ?string
$response->getServiceCode(): ?string
$response->getTransactionStatusDesc(): ?string
$response->getLatestTransactionStatus(): ?string
$response->getPaidTime(): ?string
$response->getAmountValue(): ?string
$response->getAmountCurrency(): ?string
$response->getAdditionalInfo(): array
$response->getAdditionalInfoValue(string $key, mixed $default = null): mixed
$response->toArray(): array
$response->get(string $key, mixed $default = null): mixed

NotificationPayload::fromArray(array $data)

$payload->isSuccessful(): bool
$payload->getOriginalReferenceNo(): ?string
$payload->getOriginalPartnerReferenceNo(): ?string
$payload->getLatestTransactionStatus(): ?string
$payload->getTransactionStatusDesc(): ?string
$payload->getAmountValue(): ?string
$payload->getAmountCurrency(): ?string
$payload->getExternalStoreId(): ?string
$payload->getAdditionalInfo(): array
$payload->getCallbackUrl(): ?string
$payload->getIssuerId(): ?string
$payload->getMerchantId(): ?string
$payload->getPaymentDate(): ?string
$payload->getRetrievalReferenceNo(): ?string
$payload->getPaymentReferenceNo(): ?string
$payload->toArray(): array
$payload->get(string $key, mixed $default = null): mixed
bash
php artisan vendor:publish --tag=loketqris-sdk-config