tanemrahman/zkteco-biotime

ZKTeco BioTime (ZKBioTime) REST sync for Laravel — pull punches from BioTime into zkteco_transactions.

Maintainers

Package info

github.com/tanemrahman/zkteco-biotime

pkg:composer/tanemrahman/zkteco-biotime

Transparency log

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

dev-main 2026-08-10 17:12 UTC

This package is auto-updated.

Last update: 2026-08-12 13:48:38 UTC


README

Laravel package to pull attendance punches from a ZKTeco BioTime / ZKBioTime server into your app.

BioTime keeps talking to the devices; this package periodically syncs transactions via the BioTime REST API into zkteco_transactions.

Requirements

  • PHP ^8.2
  • Laravel 11 / 12 / 13
  • A reachable ZKBioTime / BioTime instance (HTTP or HTTPS)
  • BioTime API user (username + password)

Installation (Composer)

Option A — from GitHub (current)

composer.json

{
  "repositories": [
    {
      "type": "vcs",
      "url": "https://github.com/tanemrahman/zkteco-biotime.git"
    }
  ],
  "require": {
    "tanemrahman/zkteco-biotime": "dev-main"
  }
}
composer update tanemrahman/zkteco-biotime
php artisan migrate
php artisan vendor:publish --tag=zkteco-biotime-config

Or:

composer config repositories.zkteco-biotime vcs https://github.com/tanemrahman/zkteco-biotime.git
composer require tanemrahman/zkteco-biotime:dev-main
php artisan migrate
php artisan vendor:publish --tag=zkteco-biotime-config

Option B — path / local copy

your-laravel-app/
  packages/tanemrahman/zkteco-biotime/
{
  "repositories": [
    {
      "type": "path",
      "url": "packages/tanemrahman/zkteco-biotime",
      "options": { "symlink": true }
    }
  ],
  "require": {
    "tanemrahman/zkteco-biotime": "*"
  }
}
composer update tanemrahman/zkteco-biotime
php artisan migrate

Laravel auto-discovers TanemRahman\ZktecoBiotime\ZktecoBiotimeServiceProvider.

What this package gives you

Piece Purpose
zkteco_biotime_settings Store BioTime URL + credentials
zkteco_transactions Shared punch table (source = biotime)
BioTimeClient Auth + paginated transactions API
zkteco-biotime:sync Artisan sync command
Schedule Auto sync during office hours
Event TransactionsSynced Hook into your HRM

No admin UI is included.
Build your own settings form + punch list in Blade / Inertia / Filament / Livewire.

Database tables

Table Purpose
zkteco_biotime_settings Connection profiles (can have many)
zkteco_transactions Punches (source = biotime)

If you also install tanemrahman/zkteco-adms, both packages share zkteco_transactions safely (migration uses Schema::hasTable).

zkteco_biotime_settings columns

Column Meaning
enabled Sync only when true
name Label (e.g. Head Office)
api_url BioTime base URL
username / password API login (password encrypted)
last_sync_at Incremental cursor
last_sync_status Last OK / error message

zkteco_transactions (BioTime rows)

Column Meaning
device_id 0 (no local ADMS device row)
user_id BioTime emp_code (PIN)
timestamp punch_time
status punch_state
verify verify_type
source biotime
terminal_sn BioTime terminal_sn

Configure a BioTime connection

Via Tinker / seeder

use TanemRahman\ZktecoBiotime\Models\ZktecoBiotimeSetting;

ZktecoBiotimeSetting::create([
    'enabled'  => true,
    'name'     => 'Head Office',
    'api_url'  => 'http://192.168.1.50',   // no trailing slash needed
    'username' => 'admin',
    'password' => 'your-password',
]);

Via your own settings UI (recommended)

Build a simple form that writes to ZktecoBiotimeSetting:

use TanemRahman\ZktecoBiotime\Models\ZktecoBiotimeSetting;

public function store(Request $request)
{
    $data = $request->validate([
        'name'     => 'nullable|string|max:120',
        'api_url'  => 'required|url',
        'username' => 'required|string',
        'password' => 'required|string',
        'enabled'  => 'boolean',
    ]);

    ZktecoBiotimeSetting::create($data);

    return back()->with('success', 'BioTime connection saved.');
}

Show sync health on the same page:

@foreach (\TanemRahman\ZktecoBiotime\Models\ZktecoBiotimeSetting::all() as $s)
  <div>
    {{ $s->name }}{{ $s->enabled ? 'ON' : 'OFF' }}
    Last sync: {{ $s->last_sync_at }}
    Status: {{ $s->last_sync_status }}
  </div>
@endforeach

Sync punches

# Incremental (uses last_sync_at, or last 7 days on first run)
php artisan zkteco-biotime:sync

# Force last N days
php artisan zkteco-biotime:sync --days=3

# One settings row only
php artisan zkteco-biotime:sync --setting=1

Scheduler (built-in)

When zkteco-biotime.schedule.enabled=true (default):

  • Every 10 minutes during office hours (08:0021:00, timezone configurable)
  • Daily catch-up at 21:30 for last 3 days

Ensure Laravel’s scheduler is running:

* * * * * cd /path/to/your-app && php artisan schedule:run >> /dev/null 2>&1

Config (.env)

php artisan vendor:publish --tag=zkteco-biotime-config
ZKTECO_BIOTIME_TOKEN_SCHEME=Token
# Some BioTime builds need: JWT

ZKTECO_BIOTIME_PAGE_SIZE=200
ZKTECO_BIOTIME_LOOKBACK_DAYS=7
ZKTECO_BIOTIME_SCHEDULE=true
ZKTECO_BIOTIME_TIMEZONE=Asia/Dhaka

Token scheme:

  • Most installs → Token
  • Some ZKBioTime builds → JWT

How to design your app around this package

This package is a sync engine, not a full HRM module.

Suggested screens (you build)

  1. BioTime settings — CRUD on ZktecoBiotimeSetting (URL, user, pass, enable toggle, “Sync now” button)
  2. Transactions — list/filter zkteco_transactions where source = biotime
  3. Employee mapping — map user_id (emp_code) → your employee table
  4. Attendance builder — convert punches into daily attendance / late / OT in your domain

Example: Sync now button

use Illuminate\Support\Facades\Artisan;

public function syncNow(int $id)
{
    Artisan::call('zkteco-biotime:sync', ['--setting' => $id]);

    return back()->with('status', Artisan::output());
}

Example: Show today’s BioTime punches

use TanemRahman\ZktecoBiotime\Models\ZktecoTransaction;

$punches = ZktecoTransaction::query()
    ->where('source', 'biotime')
    ->whereDate('timestamp', today())
    ->orderByDesc('timestamp')
    ->paginate(50);

Example: React after sync

use TanemRahman\ZktecoBiotime\Events\TransactionsSynced;

Event::listen(TransactionsSynced::class, function (TransactionsSynced $e) {
    // $e->settingId
    // $e->fetched
    // $e->saved
    // $e->pins     — emp_codes touched
    // $e->source   — "biotime"

    // Roll up into your attendances table, notify, etc.
});

Example: Map emp_code → employee

use App\Models\Employee;
use TanemRahman\ZktecoBiotime\Models\ZktecoTransaction;

foreach (ZktecoTransaction::where('source', 'biotime')->whereDate('timestamp', today())->cursor() as $txn) {
    $employee = Employee::where('biometric_emp_id', $txn->user_id)->first();
    if (!$employee) {
        continue;
    }
    // upsert attendance for $employee on $txn->timestamp…
}

Optional: use BioTimeClient directly

use TanemRahman\ZktecoBiotime\Models\ZktecoBiotimeSetting;
use TanemRahman\ZktecoBiotime\Services\BioTimeClient;

$setting = ZktecoBiotimeSetting::where('enabled', true)->firstOrFail();
$client  = BioTimeClient::fromSetting($setting);

foreach ($client->transactions('2026-08-01 00:00:00', '2026-08-10 23:59:59') as $page) {
    // $page = array of BioTime transaction rows
}

$employees = $client->employees();

Using with ADMS package

Install both if some offices use ADMS push and others use BioTime:

Package When
zkteco-adms Device pushes directly to Laravel
zkteco-biotime BioTime server already exists

Shared table: zkteco_transactions
Separate with source = adms|biotime.

{
  "repositories": [
    { "type": "vcs", "url": "https://github.com/tanemrahman/zkteco-adms.git" },
    { "type": "vcs", "url": "https://github.com/tanemrahman/zkteco-biotime.git" }
  ],
  "require": {
    "tanemrahman/zkteco-adms": "dev-main",
    "tanemrahman/zkteco-biotime": "dev-main"
  }
}

How BioTime API works (reference)

Step Endpoint
Auth POST {base}/api-token-auth/{ token }
Punches GET {base}/iclock/api/transactions/?page=&start_time=&end_time=
Employees GET {base}/personnel/api/employees/

Header: Authorization: Token <token> (or JWT <token> via config).

Publishable tags

php artisan vendor:publish --tag=zkteco-biotime-config
php artisan vendor:publish --tag=zkteco-biotime-migrations

License

MIT