EFL
Guides

Full process walkthrough

End-to-end example of a full EFL Leasing process, from cart to session restoration.

Overview

This guide walks through a full leasing flow in a backend application:

  1. Obtain an authentication token and start a process.
  2. Calculate offers for a basket and accept a selected variant.
  3. Submit customer data and additional statements.
  4. Initialise identity verification and handle pay-by-link.
  5. Track process changes and final status.
  6. Restore customer session after signing.

The code samples are intentionally focused on the core SDK calls.

1. From cart to process start

use GuzzleHttp\Client as GuzzleClient;
use Imoli\EflLeasingSdk\Config;
use Imoli\EflLeasingSdk\EflClient;
use Imoli\EflLeasingSdk\Http\Adapter\GuzzleHttpAdapter;

// Configuration (sandbox)
$config = Config::sandbox(
    apiKey: getenv('EFL_API_KEY'),
    baseUrl: 'https://leasingonlineapi-sandbox.efl.com.pl'
);

$guzzle = new GuzzleClient([
    'timeout' => 30,
    'connect_timeout' => 10,
]);

$httpClient = new GuzzleHttpAdapter($guzzle);
$client = new EflClient($config, $httpClient);

// 1) Obtain Bearer token used in subsequent calls
$partnerId = getenv('EFL_PARTNER_ID');
$token = $client->getAuthToken($partnerId);

// 2) Start the leasing process for the current order
$process = $client->startProcess(
    positiveReturnUrl: 'https://example.com/efl/success',
    negativeReturnUrl: 'https://example.com/efl/failure',
    bearerToken: $token
);

// Persist the transaction identifier from $process for later use
$processTransactionId = /* extract transactionId from $process */;

2. Offer selection and acceptance

use Imoli\EflLeasingSdk\Model\Calculation\AssetToCalculation;
use Imoli\EflLeasingSdk\Model\Calculation\OfferItem;
use Imoli\EflLeasingSdk\Model\Calculation\ItemDetail;

// Build basket from your cart
$itemDetail = new ItemDetail(
    guid: 'item-guid-1',
    description: 'Example asset'
    // ... additional fields as required by the model
);

$offerItem = OfferItem::builder('offer-item-guid-1')
    ->withItemDetail($itemDetail)
    // configure other financial parameters as needed
    ->build();

$basket = AssetToCalculation::builder('basket-guid-1')
    ->addOfferItem($offerItem)
    ->build();

// Calculate basic offer
$offerResponse = $client->calculateBasicOffer($basket, $token);

// Present variants to the customer and let them choose one
$selectedCalculationId = /* chosen calculation id */;
$selectedVariantId = /* chosen variant id */;

// Accept the chosen variant
$client->acceptCalculation(
    transactionId: $processTransactionId,
    calculationId: $selectedCalculationId,
    calculationVariantId: $selectedVariantId,
    basketCalculation: null,
    bearerToken: $token
);

3. Customer data and statements

use Imoli\EflLeasingSdk\Model\Customer\Address;
use Imoli\EflLeasingSdk\Model\Customer\Company;
use Imoli\EflLeasingSdk\Model\Customer\CustomerData;
use Imoli\EflLeasingSdk\Model\Customer\CustomerDataStatement;
use Imoli\EflLeasingSdk\Model\Customer\EmailAddress;
use Imoli\EflLeasingSdk\Model\Customer\Phone;

// Build customer payload from your own domain models / forms
$company = Company::builder('company-guid', '1234567890')
    ->addEmail(new EmailAddress('email-guid', 'contact@example.com', 'work'))
    ->addPhone(new Phone('phone-guid', '+48', '123456789', 'mobile', 'mobile'))
    ->addAddress(new Address(
        'addr-guid',
        'Headquarters',
        'registered_office',
        'Warsaw',
        'Main St',
        '1',
        '00-001',
        'PL'
    ))
    ->addStatement(new CustomerDataStatement('stmt-guid', true, 'gdpr'))
    ->build();

$customerData = CustomerData::builder($processTransactionId, 42)
    ->withCompany($company)
    ->build();

// Submit main customer data
$client->submitCustomerData($customerData, $token);

// Optionally submit additional statements
$additionalStatements = [
    new CustomerDataStatement('stmt-marketing', true, 'marketing'),
];

$client->submitCustomerStatements(
    transactionId: $processTransactionId,
    statements: $additionalStatements,
    bearerToken: $token
);
use Imoli\EflLeasingSdk\Model\Verification\VerificationInitializationParams;

// Build verification parameters according to EFL documentation
$params = VerificationInitializationParams::builder('order-uuid')
    // configure as required by EFL verification rules
    ->build();

// Initialise identity verification
$verificationResult = $client->initializeIdentityVerification(
    $processTransactionId,
    $params,
    $token
);

$redirectUrl = $verificationResult->getRedirectUrl();

// Redirect the customer to $redirectUrl to perform identity verification

// Optionally initiate pay-by-link payment at the appropriate point in your flow
$client->initiatePayByLinkPayment($processTransactionId, $token);

5. Process tracking and finalisation

// Poll process changes in a background job or on demand
$statusBpmFilters = null; // or an array of specific BPM status codes

$state = $client->getProcessChanges(
    transactionId: $processTransactionId,
    statusBpm: $statusBpmFilters,
    bearerToken: $token
);

// Alternatively, only read the last status
$lastStatus = $client->getLastProcessStatus($processTransactionId, $token);

// Use $state or $lastStatus to update your own order/contract records

6. Session restoration after signing

After the contract is signed, you may need to restore the customer session using data returned by EFL (for example, a pay-by-link order identifier or transaction id).

use Imoli\EflLeasingSdk\Model\Restoration\AuthenticationRestorationResult;

// Restore session by pay-by-link order id
$restorationResult = $client->restoreCustomerSessionByOrderId($payByLinkOrderId);

// Or restore session directly by transaction id after signing
$restorationResultAfterSigning = $client->restoreSessionAfterSigning($processTransactionId);

// Decide how to continue based on the restoration action
$action = $restorationResult->getReauthenticationAction(); // ReauthenticationAction enum

switch ($action) {
    case 'None':
        // Session can be restored without additional user action
        break;
    case 'Reauthenticate':
        // Ask the user to re-authenticate before continuing
        break;
    // handle other enum values as defined by the model
}

This completes the full end-to-end walkthrough. In a real application you should combine this flow with proper error handling, logging and retries as described in the dedicated error handling guide.