PHPackages                             imamnc/efihub-client - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. imamnc/efihub-client

ActiveLibrary[API Development](/categories/api)

imamnc/efihub-client
====================

Laravel client for EFIHUB Integration Service

v1.2.15(4w ago)01.2k—5.4%MITPHPPHP ^7.4|^8.0

Since Dec 29Pushed 4w agoCompare

[ Source](https://github.com/imamnc/efihub-client)[ Packagist](https://packagist.org/packages/imamnc/efihub-client)[ Docs](https://github.com/imamnc/efihub-client)[ RSS](/packages/imamnc-efihub-client/feed)WikiDiscussions main Synced yesterday

READMEChangelogDependencies (16)Versions (20)Used By (0)

 [ ![EFIHUB](https://camo.githubusercontent.com/7d92123d886b658872a288bd21dc293dfbccf23a459c59b2e8c47772340af8c0/68747470733a2f2f6566696875622e6d6f72656675726e69747572652e69642f696d672f6c6f676f2e706e67) ](https://efihub.morefurniture.id)

EFIHUB PHP/Laravel Client
=========================

[](#efihub-phplaravel-client)

 *A modern SDK to integrate with the EFIHUB platform using the OAuth 2.0 Client Credentials flow.*

 [![packagist version](https://camo.githubusercontent.com/3d2169ad37ba7d23c5d857ff5875f352a879d013519c756a8c93e38a6b103be0/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f696d616d6e632f6566696875622d636c69656e742e7376673f6c6f676f3d7061636b6167697374)](https://packagist.org/packages/imamnc/efihub-client) [![license](https://camo.githubusercontent.com/7013272bd27ece47364536a221edb554cd69683b68a46fc0ee96881174c4214c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d626c75652e737667)](https://camo.githubusercontent.com/7013272bd27ece47364536a221edb554cd69683b68a46fc0ee96881174c4214c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d626c75652e737667) [![author](https://camo.githubusercontent.com/0171bbba38f78ce95b3a8d4c270fb7ffb89ee608f528bd35710aceefa14b9cc0/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f617574686f722d496d616d2532304e632d6f72616e67652e737667)](https://imamnc.com)

Introduction
------------

[](#introduction)

EFIHUB client for Laravel/PHP that authenticates using OAuth 2.0 Client Credentials and exposes:

- A lightweight HTTP client (GET/POST/PUT/DELETE) with automatic token caching and retry on 401
- Storage module to upload files and get public URLs
- Websocket module to dispatch real-time events to channels
- WhatsApp module to manage agents (list, QR code, status, phone validation) and send messages (single/group) and file attachments
- SSO module to generate authorization URL and fetch user profile after callback

Designed for server-side apps only—do not expose your client secret to browsers.

---

Table of Contents
-----------------

[](#table-of-contents)

- [Getting Started](#getting-started)
    - [Installation](#installation)
    - [Framework Setup](#framework-setup)
    - [Environment Variables](#environment-variables)
    - [Authentication](#authentication)
- [HTTP Client](#http-client)
    - [Basic Usage](#basic-usage)
    - [Dependency Injection](#dependency-injection)
- [Modules](#modules)
    - [Storage](#storage-module)
    - [WebSocket](#websocket-module)
    - [SSO](#sso-module)
    - [WhatsApp](#whatsapp-module)
- [License &amp; Author](#license--author)

---

Getting Started
---------------

[](#getting-started)

### Installation

[](#installation)

Install the package via Composer:

```
composer require imamnc/efihub-client
```

### Framework Setup

[](#framework-setup)

#### Laravel

[](#laravel)

Auto-discovery is enabled. Optionally publish the config file:

```
php artisan vendor:publish --provider="Efihub\EfihubServiceProvider" --tag=config
```

#### Lumen 7 (Illuminate 7.30.4)

[](#lumen-7-illuminate-7304)

Register the service provider in `bootstrap/app.php`:

```
$app->register(Efihub\EfihubServiceProvider::class);
```

Enable and load the package config:

```
$app->configure('efihub');
```

Copy the config file manually to `config/efihub.php` (Lumen does not support `vendor:publish`).

To use the Facade, enable facades and add an alias:

```
$app->withFacades();

class_alias(Efihub\Facades\Efihub::class, 'Efihub');
```

### Environment Variables

[](#environment-variables)

Add the following to your `.env` file:

```
EFIHUB_CLIENT_ID=your_client_id
EFIHUB_CLIENT_SECRET=your_client_secret
EFIHUB_TOKEN_URL=https://efihub.morefurniture.id/oauth/token
EFIHUB_API_URL=https://efihub.morefurniture.id/api
```

These map to `config/efihub.php` keys: `client_id`, `client_secret`, `token_url`, `api_base_url`.

### Authentication

[](#authentication)

The client uses the **OAuth 2.0 Client Credentials** flow automatically:

- An access token is fetched from `EFIHUB_TOKEN_URL` using your client credentials.
- The token is cached for ~55 minutes; on a `401` response, the cache is cleared and the request is retried once.
- No manual token management is needed—simply use the Facade or inject the client.

---

HTTP Client
-----------

[](#http-client)

The base client handles authentication and exposes standard HTTP verbs. Use it directly for any EFIHUB API endpoint, or use the higher-level [Modules](#modules) for specific services.

### Basic Usage

[](#basic-usage)

```
use Efihub\Facades\Efihub;

// GET with query params
$res = Efihub::get('/user', ['page' => 1]);

// POST JSON
$res = Efihub::post('/orders', ['sku' => 'ABC', 'qty' => 2]);

// PUT
$res = Efihub::put('/orders/123', ['qty' => 3]);

// DELETE
$res = Efihub::delete('/orders/123');

if ($res->successful()) {
    $data = $res->json();
}

// Multipart upload (form-data + file attachment)
$uploadRes = Efihub::postMultipart('/documents', ['type' => 'invoice'], [
    'file' => storage_path('app/invoices/jan.pdf'),
]);
if ($uploadRes->failed()) {
    // handle failure
}
```

### Dependency Injection

[](#dependency-injection)

```
use Efihub\EfihubClient;

class UserService
{
    /** @var EfihubClient */
    private $efihub;

    public function __construct(EfihubClient $efihub)
    {
        $this->efihub = $efihub;
    }

    public function list(): array
    {
        $res = $this->efihub->get('/user');
        return $res->successful() ? $res->json() : [];
    }
}
```

---

Modules
-------

[](#modules)

All modules are accessed via the `Efihub` Facade (e.g. `Efihub::storage()`, `Efihub::whatsapp()`).

---

### Storage module

[](#storage-module)

Upload files and manage them on the EFIHUB storage service.

#### Methods

[](#methods)

`Efihub::storage()` returns `Efihub\Modules\StorageClient` with:

- `upload(mixed $file, string $path): string|false` – uploads a file; returns the public URL or `false` on failure.
- `exists(string $path): bool` – checks whether a file exists.
- `size(string $path): int|null` – returns file size in bytes, or `null` on failure.
- `delete(string $path): bool` – deletes a file; returns `true` on success.

`upload()` accepts a Laravel/Symfony `UploadedFile`, a string path, or raw file contents. End `$path` with `/` to let the server auto-generate the filename.

#### Usage

[](#usage)

```
use Illuminate\Http\Request;
use Efihub\Facades\Efihub;

class MediaController
{
    public function store(Request $request)
    {
        $request->validate([
            'file' => ['required', 'file', 'max:10240'], // 10 MB
        ]);

        $uploadedFile = $request->file('file'); // Illuminate\Http\UploadedFile

        // End path with '/' to auto-generate filename on the server
        $url = Efihub::storage()->upload($uploadedFile, 'uploads/'.date('Y/m/d').'/');

        if ($url === false) {
            return back()->withErrors('Upload failed');
        }

        return back()->with('url', $url);
    }
}
```

Other helpers:

```
Efihub::storage()->exists('uploads/photo.jpg'); // bool
Efihub::storage()->size('uploads/photo.jpg');   // int|null (bytes)
Efihub::storage()->delete('uploads/photo.jpg'); // bool
```

#### Endpoints

[](#endpoints)

- `POST /storage/upload`
- `GET /storage/url`
- `GET /storage/size`
- `GET /storage/exists`
- `DELETE /storage/delete`

---

### WebSocket module

[](#websocket-module)

Dispatch real-time events to channels from a server-side listener or job.

#### Methods

[](#methods-1)

`Efihub::socket()` returns `Efihub\Modules\WebsocketClient` with:

- `dispatch(string $channel, string $event, array $data): bool` – broadcasts an event; returns `true` on success.

#### Usage

[](#usage-1)

```
use Efihub\Facades\Efihub;

$ok = Efihub::socket()->dispatch(
    'orders:updates',
    'OrderUpdated',
    ['order_id' => 123, 'status' => 'updated']
);

if (!$ok) {
    // handle failure (log, retry, etc.)
}
```

#### Endpoint

[](#endpoint)

- `POST /websocket/dispatch` — payload: `{ channel, event, data }`

---

### SSO module

[](#sso-module)

Centralized login flow: generate an authorization URL, redirect the user, then exchange the `redirect_token` for user data.

#### Methods

[](#methods-2)

`Efihub::sso()` returns `Efihub\Modules\SSOClient` with:

- `login(): string|false` – returns the authorization URL or `false` on failure.
- `userData(string $redirectToken): array|false` – exchanges the token for user info; returns an array or `false` on failure.

#### Usage

[](#usage-2)

**Step 1 — Redirect the user to EFIHUB login:**

```
use Efihub\Facades\Efihub;

$authUrl = Efihub::sso()->login();
if ($authUrl === false) {
    // log error and abort
}

return redirect()->away($authUrl);
```

**Step 2 — Handle the callback and fetch user data:**

```
$token = request('redirect_token');
$user = Efihub::sso()->userData($token);

if ($user === false) {
    // invalid token or request failed
} else {
    // $user['email'], $user['name'], ...
}
```

#### Endpoints

[](#endpoints-1)

- `POST /sso/authorize`
- `GET /sso/user`

> Security enhancements like `state` / `nonce` can be layered externally; ensure you bind the session before redirecting.

---

### WhatsApp module

[](#whatsapp-module)

Manage WhatsApp agents and send messages (text or with attachments) to individual recipients or groups.

#### Methods

[](#methods-3)

`Efihub::whatsapp()` returns `Efihub\Modules\WhatsappClient` with:

**Agent management**

MethodReturnsDescription`agents()``array`List all registered agents/sessions. Empty array on failure.`agentQR(string $agentCode)``string|null`QR code as `image/png;base64`, or `null` on failure.`agentStatus(string $agentCode)``string|null``'connected'` or `'disconnected'`, or `null` on failure.`agentStart(string $agentCode)``bool`Start a WhatsApp agent session. Returns `true` on success.`agentRestart(string $agentCode)``bool`Restart a WhatsApp agent session. Returns `true` on success.`agentTerminate(string $agentCode)``bool`Terminate a WhatsApp agent session. Returns `true` on success.`checkPhoneNumber(string $agentCode, string $number)``bool``true` if the number is a valid WhatsApp user.**Messaging**

MethodReturnsDescription`sendMessage(string $sender, string $to, string $message, ?string $ref_id, ?string $ref_url, ?bool $delay = true)``bool`Send a text message to a single recipient.`sendGroupMessage(string $sender, string $to, string $message, ?string $ref_id, ?string $ref_url, ?bool $delay = true)``bool`Send a text message to a group.`sendAttachment(string $sender, string $to, string $message, mixed $attachment, ?string $ref_id, ?string $ref_url, ?bool $delay = true)``bool`Send a message with a file attachment to a single recipient.`sendGroupAttachment(string $sender, string $to, string $message, mixed $attachment, ?string $ref_id, ?string $ref_url, ?bool $delay = true)``bool`Send a message with a file attachment to a group.`getMessages(string $agentCode, string $phone, int $limit = 10)``array`Retrieve recent messages for an agent and phone number.`downloadMedia(string $agentCode, string $phone, string $messageId)``object|null`Download media attachment from a specific message.All message methods return `true` on HTTP success (2xx), `false` otherwise. The `getMessages()` method returns an array of messages or empty array on failure.

The WhatsApp client also normalizes phone numbers for phone-based methods such as `checkPhoneNumber()`, `getMessages()`, and `downloadMedia()`.

#### Agent management

[](#agent-management)

```
use Efihub\Facades\Efihub;

// List all registered agents
$agents = Efihub::whatsapp()->agents();
// returns: [ ['code' => 'AGENT1', ...], ... ]

// Get QR code image (base64 PNG) to display for scanning
$qr = Efihub::whatsapp()->agentQR('AGENT1');
// returns: 'data:image/png;base64,...' or null

// Check connection status
$status = Efihub::whatsapp()->agentStatus('AGENT1');
// returns: 'connected' | 'disconnected' | null

// Start a WhatsApp agent session
$started = Efihub::whatsapp()->agentStart('AGENT1');
if ($started) {
    // session started successfully
}

// Restart a WhatsApp agent session
$restarted = Efihub::whatsapp()->agentRestart('AGENT1');
if ($restarted) {
    // session restarted successfully
}

// Terminate a WhatsApp agent session
$terminated = Efihub::whatsapp()->agentTerminate('AGENT1');
if ($terminated) {
    // session terminated successfully
}

// Validate a phone number before sending
$valid = Efihub::whatsapp()->checkPhoneNumber('AGENT1', '628109998877');
if (!$valid) {
    // number is not on WhatsApp
}
```

#### Sending messages

[](#sending-messages)

```
use Efihub\Facades\Efihub;

// Send to a single recipient
$ok = Efihub::whatsapp()->sendMessage(
    sender: 'AGENT1',
    to: '+628109998877',
    message: 'Halo! Tes WhatsApp.'
);

// Send to a group
$ok = Efihub::whatsapp()->sendGroupMessage(
    sender: 'AGENT1',
    to: 'group-abc123', // group identifier
    message: 'Hello World!'
);

if (!$ok) {
    // log or retry
}
```

#### Attachments

[](#attachments)

```
// Single file by path
$ok = Efihub::whatsapp()->sendAttachment(
    sender: 'AGENT1',
    to: '+628109998877',
    message: 'Berikut invoice kamu',
    attachment: storage_path('app/invoices/jan.pdf'),
);

// Raw contents with custom filename & MIME type
$ok = Efihub::whatsapp()->sendAttachment(
    sender: 'AGENT1',
    to: '+628109998877',
    message: 'Report CSV',
    attachment: [
        'contents' => file_get_contents(storage_path('app/tmp/report.csv')),
        'filename' => 'report.csv',
        'headers'  => ['Content-Type' => 'text/csv'],
    ],
);

// Multiple files to a group
$ok = Efihub::whatsapp()->sendGroupAttachment(
    sender: 'AGENT1',
    to: 'group-abc123',
    message: 'Semua dokumen',
    attachment: [
        storage_path('app/docs/a.pdf'),
        storage_path('app/docs/b.pdf'),
    ],
);
```

**Supported file spec formats:**

FormatExamplePath string`'/path/to/file.pdf'`Path array with custom name`['path' => '/path/to/file.pdf', 'filename' => 'custom.pdf', 'headers' => [...]]`Raw contents`['contents' => $binary, 'filename' => 'name.ext', 'headers' => [...]]`Multiple files (array of specs)`['/path/a.jpg', '/path/b.jpg']`#### Reference metadata

[](#reference-metadata)

All four send methods accept optional `$ref_id` and `$ref_url` parameters to correlate outbound messages with internal entities (orders, tickets, etc.):

```
// Text message
Efihub::whatsapp()->sendMessage(
    sender: 'AGENT1',
    to: '+628109998877',
    message: 'Your order has been shipped.',
    ref_id: 'order-9988',
    ref_url: 'https://yourapp.com/orders/9988',
);

// Text message to a group
Efihub::whatsapp()->sendGroupMessage(
    sender: 'AGENT1',
    to: 'group-abc123',
    message: 'Bulk shipment processed.',
    ref_id: 'batch-42',
    ref_url: 'https://yourapp.com/batches/42',
);

// Attachment to a single recipient
Efihub::whatsapp()->sendAttachment(
    sender: 'AGENT1',
    to: '+628109998877',
    message: 'Berikut invoice kamu.',
    attachment: storage_path('app/invoices/jan.pdf'),
    ref_id: 'invoice-101',
    ref_url: 'https://yourapp.com/invoices/101',
);

// Attachment to a group
Efihub::whatsapp()->sendGroupAttachment(
    sender: 'AGENT1',
    to: 'group-abc123',
    message: 'Laporan bulanan.',
    attachment: storage_path('app/reports/jan.pdf'),
    ref_id: 'report-jan',
    ref_url: 'https://yourapp.com/reports/jan',
);
```

#### Retrieving messages

[](#retrieving-messages)

```
use Efihub\Facades\Efihub;

// Retrieve recent messages for an agent and phone number
$messages = Efihub::whatsapp()->getMessages(
    agentCode: 'AGENT1',
    phone: '+628109998877',
    limit: 10  // optional, defaults to 10
);

if (!empty($messages)) {
    foreach ($messages as $msg) {
        echo "From: {$msg['from']}, Message: {$msg['message']}";
    }
} else {
    // No messages or request failed
}

// Download media attachment from a specific message
$media = Efihub::whatsapp()->downloadMedia(
    agentCode: 'AGENT1',
    phone: '+628109998877',
    messageId: 'msg_abc123'
);

if ($media) {
    // $media contains media URL and metadata
    echo "Media URL: {$media->url}";
} else {
    // Media download failed
}
```

#### Error inspection

[](#error-inspection)

The helpers only return `bool`. For full error details, use the base HTTP client directly:

```
$client = app(\Efihub\EfihubClient::class);
$response = $client->post('/whatsapp/message', [ /* payload */ ]);
if ($response->failed()) {
    logger()->error('WA send failed', [
        'status' => $response->status(),
        'body'   => $response->json(),
    ]);
}
```

#### Phone number normalization

[](#phone-number-normalization)

All phone-based methods (`checkPhoneNumber`, `sendMessage`, `sendGroupMessage`, `sendAttachment`, `sendGroupAttachment`, `getMessages`, `downloadMedia`) automatically normalize phone numbers to the international format (`62xxxxxxxxxx` for Indonesia). You may pass numbers in any common format:

- `+628109998877` → `628109998877`
- `08109998877` → `628109998877`
- `628109998877` → `628109998877` (unchanged)

#### Endpoints

[](#endpoints-2)

MethodEndpoint`agents()``GET /whatsapp/sessions``agentQR()``GET /whatsapp/session/qrcode/{agentCode}``agentStatus()``GET /whatsapp/session/status/{agentCode}``agentStart()``POST /whatsapp/session/start/{agentCode}``agentRestart()``POST /whatsapp/session/restart/{agentCode}``agentTerminate()``POST /whatsapp/session/terminate/{agentCode}``checkPhoneNumber()``GET /whatsapp/user/exists/{agentCode}/{number}``sendMessage()``POST /whatsapp/message``sendGroupMessage()``POST /whatsapp/message/group``sendAttachment()``POST /whatsapp/message/attachment``sendGroupAttachment()``POST /whatsapp/message/group/attachment``getMessages()``GET /whatsapp/messages/{agentCode}/{phone}/{limit}``downloadMedia()``GET /whatsapp/message/download/{agentCode}/{phone}/{messageId}`> Adjust paths if your EFIHUB deployment customizes routing.

---

License &amp; Author
--------------------

[](#license--author)

MIT © Imam Nurcholis. See [LICENSE](LICENSE).

- Author:
- EFIHUB:

###  Health Score

45

—

FairBetter than 91% of packages

Maintenance94

Actively maintained with recent releases

Popularity19

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity49

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~19 days

Recently: every ~12 days

Total

19

Last Release

29d ago

PHP version history (2 changes)v1.0.0PHP ^8.0

v1.2.4PHP ^7.4|^8.0

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/44648298?v=4)[Imam Nurcholis](/maintainers/imamnc)[@imamnc](https://github.com/imamnc)

---

Top Contributors

[![imamnc](https://avatars.githubusercontent.com/u/44648298?v=4)](https://github.com/imamnc "imamnc (29 commits)")

---

Tags

apiclientlaraveloauth2efihub

### Embed Badge

![Health badge](/badges/imamnc-efihub-client/health.svg)

```
[![Health](https://phpackages.com/badges/imamnc-efihub-client/health.svg)](https://phpackages.com/packages/imamnc-efihub-client)
```

###  Alternatives

[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9762.4M130](/packages/roots-acorn)[psalm/plugin-laravel

Psalm plugin for Laravel

3355.3M346](/packages/psalm-plugin-laravel)[simplestats-io/laravel-client

Server-side analytics for Laravel that follows the full funnel from visit to registration to payment, attributed to the channel that drove it. Revenue, MRR, churn and ad-spend profit (ROAS/CAC) per channel. GDPR compliant, ad-blocker proof.

5021.9k](/packages/simplestats-io-laravel-client)[defstudio/telegraph

A laravel facade to interact with Telegram Bots

816333.3k3](/packages/defstudio-telegraph)[spatie/laravel-export

Create a static site bundle from a Laravel app

674146.0k6](/packages/spatie-laravel-export)[resend/resend-laravel

Resend for Laravel

1222.7M9](/packages/resend-resend-laravel)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
