PHPackages                             ghanem/dtone - 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. ghanem/dtone

ActiveLaravel-package[API Development](/categories/api)

ghanem/dtone
============

A package that provides an interface between Laravel and DT One DVS API

v3.1.0(2mo ago)0581MITPHPPHP ^7.2.5|^8.0

Since Oct 1Pushed 2mo ago1 watchersCompare

[ Source](https://github.com/AbdullahGhanem/laravel-dtone)[ Packagist](https://packagist.org/packages/ghanem/dtone)[ RSS](/packages/ghanem-dtone/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (5)Dependencies (7)Versions (7)Used By (0)

Laravel Dtone
=============

[](#laravel-dtone)

[![Latest Stable Version](https://camo.githubusercontent.com/3b1f486b4d92aa3e7fa8db57dd2afb073876514a025037c45396be3eb465e0ee/68747470733a2f2f706f7365722e707567782e6f72672f6768616e656d2f64746f6e652f762f737461626c652e737667)](https://packagist.org/packages/ghanem/dtone) [![License](https://camo.githubusercontent.com/0688fc4088ccc05313e8e27d8e61bb7973eac3185fa5ef8091d4ddda29af8bfe/68747470733a2f2f706f7365722e707567782e6f72672f6768616e656d2f64746f6e652f6c6963656e73652e737667)](https://packagist.org/packages/ghanem/dtone) [![Total Downloads](https://camo.githubusercontent.com/fd64def888dd6844ce5b705c9c5b0928979fc76c1ccf8887bef25928c231a8ca/68747470733a2f2f706f7365722e707567782e6f72672f6768616e656d2f64746f6e652f646f776e6c6f6164732e737667)](https://packagist.org/packages/ghanem/dtone)

A package that provides an interface between [Laravel](https://laravel.com) and [DT One DVS API](https://dvs-api-doc.dtone.com/#section/Overview).

Requirements
------------

[](#requirements)

- PHP ^7.2.5 | ^8.0
- Laravel ^7.0 | ^8.0 | ^9.0 | ^10.0 | ^11.0 | ^12.0

Installation
------------

[](#installation)

- [Dtone on Packagist](https://packagist.org/packages/ghanem/dtone)
- [Dtone on GitHub](https://github.com/abdullahghanem/dtone)

You can install the package via composer:

```
composer require ghanem/dtone
```

Publish the config file:

```
php artisan vendor:publish --provider="Ghanem\Dtone\DtoneServiceProvider" --tag="config"
```

Configuration
-------------

[](#configuration)

Add the following to your `.env` file:

```
DTONE_KEY=your-production-api-key
DTONE_SECRET=your-production-api-secret
DTONE_TEST_KEY=your-sandbox-api-key
DTONE_TEST_SECRET=your-sandbox-api-secret
DTONE_IS_PRODUCTION=false
DTONE_RETRIES=0
DTONE_RETRY_DELAY=100
```

Set `DTONE_IS_PRODUCTION=true` when you are ready to use the production API.

### Retry Configuration

[](#retry-configuration)

You can enable automatic retries for failed requests:

```
DTONE_RETRIES=3
DTONE_RETRY_DELAY=100
```

This will retry failed requests up to 3 times with a 100ms delay between attempts.

Usage
-----

[](#usage)

You can use the `Dtone` facade or resolve it from the container.

```
use Ghanem\Dtone\Facades\Dtone;
```

### Services

[](#services)

```
// List all services (returns PaginatedResponse of Service DTOs)
$services = Dtone::services($page, $per_page);

$services->getData();           // array of Service DTOs
$services->getMeta()->getTotal(); // total count

// Get a service by ID
$service = Dtone::serviceById(1);
$service->getId();
$service->getName();
```

### Countries

[](#countries)

```
// List all countries
$countries = Dtone::countries($page, $per_page);

// Get a country by ISO code
$country = Dtone::countryByIsoCode('US');
$country->getIsoCode();    // 'US'
$country->getName();       // 'United States'
$country->getRegions();    // array
```

### Operators

[](#operators)

```
// List all operators (optionally filter by country)
$operators = Dtone::operators('US', $page, $per_page);

// Get an operator by ID
$operator = Dtone::operatorById(5);
$operator->getId();
$operator->getName();
$operator->getCountry();            // Country DTO
$operator->getCountry()->getName(); // nested access

// Lookup operators by mobile number
$result = Dtone::lookupOperatorsByMobileNumber('+1234567890');
```

### Products

[](#products)

```
// List products with filters
$products = Dtone::products(
    $type,              // e.g. 'FIXED_VALUE_RECHARGE'
    $service_id,        // e.g. 1
    $country_iso_code,  // e.g. 'US'
    $benefit_types,     // e.g. ['Airtime']
    $page,
    $per_page
);

// Get a product by ID
$product = Dtone::productById(99);
$product->getId();
$product->getType();
$product->getService();              // Service DTO
$product->getOperator();             // Operator DTO
$product->getAttribute('prices');    // raw array for nested fields
```

### Campaigns

[](#campaigns)

```
// List active campaigns
$campaigns = Dtone::campaigns($page, $per_page);

// Get a campaign by ID
$campaign = Dtone::campaignById(7);
$campaign->getId();
$campaign->getName();
```

### Promotions

[](#promotions)

```
// List promotions
$promotions = Dtone::promotions($page, $per_page);

// Get a promotion by ID
$promotion = Dtone::promotionById(3);
$promotion->getOperator(); // Operator DTO or null
```

### Benefit Types

[](#benefit-types)

```
// List all benefit types
$benefitTypes = Dtone::benefitTypes($page, $per_page);
```

### Balances

[](#balances)

```
$balances = Dtone::balances(); // array of Balance DTOs

foreach ($balances as $balance) {
    $balance->getAmount();    // 150.50
    $balance->getCurrency();  // 'USD'
}
```

### Transactions

[](#transactions)

```
// List transactions
$transactions = Dtone::transactions($page, $per_page);

// Get a transaction by ID
$transaction = Dtone::transactionById(456);
$transaction->getId();
$transaction->getStatus();
$transaction->getExternalId();
$transaction->getAttribute('product');  // raw array

// Create a transaction (async)
$transaction = Dtone::createTransaction(
    'external-id-123',                      // external_id
    99,                                     // product_id
    ['mobile_number' => '+1234567890'],     // credit_party_identifier
    false                                   // auto_confirm (default: false)
);

// Create a transaction (sync - waits for completion)
$transaction = Dtone::createTransactionSync(
    'external-id-123',
    99,
    ['mobile_number' => '+1234567890'],
    true                                    // auto_confirm
);

// Confirm a transaction (async)
$confirmed = Dtone::confirmTransaction($transaction_id);

// Confirm a transaction (sync - waits for completion)
$confirmed = Dtone::confirmTransactionSync($transaction_id);

// Cancel a transaction
$cancelled = Dtone::cancelTransaction($transaction_id);
```

### Lookups

[](#lookups)

```
// Lookup operators by mobile number
$operators = Dtone::lookupOperatorsByMobileNumber('+1234567890');

// Statement inquiry
$statement = Dtone::statementInquiry(
    99,                                     // product_id
    ['account_number' => '123456']          // credit_party_identifier
);

// Get remaining benefits for a credit party
$benefits = Dtone::creditPartyBenefits(
    99,                                     // product_id
    ['mobile_number' => '+1234567890']      // credit_party_identifier
);

// Get status for a credit party
$status = Dtone::creditPartyStatus(
    99,                                     // product_id
    ['mobile_number' => '+1234567890']      // credit_party_identifier
);
```

### Response DTOs

[](#response-dtos)

All API responses are returned as typed DTO objects. Every DTO has a `toArray()` method for backward compatibility:

```
$service = Dtone::serviceById(1);
$service->toArray();  // ['id' => 1, 'name' => 'Mobile']

$response = Dtone::services();
$response->toArray(); // ['data' => [...], 'meta' => [...]]
```

Available DTOs: `Service`, `Country`, `Operator`, `Product`, `Balance`, `Transaction`, `Campaign`, `Promotion`, `BenefitType`, `PaginatedResponse`, `Meta`.

### Paginated Responses

[](#paginated-responses)

List endpoints return a `PaginatedResponse` DTO:

```
$response = Dtone::services(1, 10);

$response->getData();                  // array of DTOs
$response->getMeta()->getTotal();      // total items
$response->getMeta()->getTotalPages(); // total pages
$response->getMeta()->getPage();       // current page
$response->getMeta()->getPerPage();    // items per page
$response->getMeta()->getNextPage();   // next page number
$response->getMeta()->getPrevPage();   // previous page number
```

Webhooks
--------

[](#webhooks)

The package automatically registers a webhook endpoint to receive DT One transaction callbacks.

### Configuration

[](#configuration-1)

```
DTONE_WEBHOOK_PATH=dtone/webhook
DTONE_WEBHOOK_SECRET=your-webhook-secret
DTONE_WEBHOOK_LOGGING=false
```

You can also configure middleware in `config/dtone.php`:

```
'webhook_middleware' => ['api'],
```

Set `webhook_path` to `null` to disable the webhook route.

### Events

[](#events)

The webhook controller dispatches the following events:

EventDispatched when`TransactionStatusChanged`Every webhook (always dispatched)`TransactionCompleted`Status is `COMPLETED``TransactionFailed`Status is `FAILED` or `DECLINED``TransactionConfirmed`Status is `CONFIRMED``TransactionCancelled`Status is `CANCELLED`Listen to events in your `EventServiceProvider`:

```
use Ghanem\Dtone\Events\TransactionCompleted;

protected $listen = [
    TransactionCompleted::class => [
        YourTransactionCompletedListener::class,
    ],
];
```

Each event has `$payload`, `$status`, and `$transactionId` properties:

```
public function handle(TransactionCompleted $event)
{
    $event->transactionId; // 123
    $event->status;        // 'COMPLETED'
    $event->payload;       // full webhook payload array
}
```

### Signature Verification

[](#signature-verification)

If `DTONE_WEBHOOK_SECRET` is set, the `VerifyWebhookSignature` middleware is available:

```
// config/dtone.php
'webhook_middleware' => [
    \Ghanem\Dtone\Http\Middleware\VerifyWebhookSignature::class,
],
```

This verifies the `X-Dtone-Signature` header using HMAC-SHA256.

Laravel Notifications Channel
-----------------------------

[](#laravel-notifications-channel)

Send top-ups as Laravel notifications using the `DtoneChannel`:

```
use Ghanem\Dtone\Notifications\DtoneChannel;
use Ghanem\Dtone\Notifications\DtoneMessage;
use Illuminate\Notifications\Notification;

class SendAirtimeNotification extends Notification
{
    public function via($notifiable)
    {
        return [DtoneChannel::class];
    }

    public function toDtone($notifiable)
    {
        return DtoneMessage::create(99)          // product_id
            ->externalId('order-123')             // optional external ID
            ->toMobileNumber('+1234567890')       // recipient
            ->autoConfirm();                      // auto-confirm the transaction
    }
}
```

### DtoneMessage API

[](#dtonemessage-api)

```
DtoneMessage::create($productId)         // create with product ID
    ->externalId('ext-123')               // set external ID (auto-generated if not set)
    ->toMobileNumber('+1234567890')       // set mobile number recipient
    ->to(['account_number' => '123456'])  // or set custom identifier
    ->autoConfirm()                       // enable auto-confirm
    ->sync();                             // use synchronous API (default: async)
```

### On-Demand Notifications

[](#on-demand-notifications)

```
use Illuminate\Support\Facades\Notification;

Notification::route(DtoneChannel::class, null)
    ->notify(new SendAirtimeNotification());
```

Caching
-------

[](#caching)

Discovery endpoints (services, countries, operators, products, campaigns, promotions, benefit-types) can be cached to reduce API calls:

```
DTONE_CACHE_TTL=3600
```

Override TTL per endpoint:

```
DTONE_CACHE_TTL_SERVICES=7200
DTONE_CACHE_TTL_COUNTRIES=86400
DTONE_CACHE_TTL_OPERATORS=3600
DTONE_CACHE_TTL_PRODUCTS=1800
```

Set `DTONE_CACHE_TTL=0` (default) to disable caching. Transactions, balances, and lookups are never cached.

Clear cache programmatically:

```
use Ghanem\Dtone\Request;

Request::clearCache();              // clear all DT One cache
Request::clearCache('services');    // clear specific endpoint cache
```

Artisan Commands
----------------

[](#artisan-commands)

CommandDescription`dtone:balance`Display account balances`dtone:products`List products (supports `--country`, `--type`, `--service`, `--page`, `--per-page`)`dtone:transaction {id?}`List transactions or get details by ID`dtone:cache-clear {endpoint?}`Clear DT One cache (all or specific endpoint)`dtone:health`Check API connectivity, balances, and service availabilityExamples:

```
php artisan dtone:balance
php artisan dtone:products --country=US --type=FIXED_VALUE_RECHARGE
php artisan dtone:transaction 456
php artisan dtone:cache-clear services
php artisan dtone:health
```

Done
----

[](#done)

- Services (list, get by ID)
- Countries (list, get by ISO code)
- Operators (list, get by ID)
- Products (list with filters, get by ID)
- Campaigns (list, get by ID)
- Promotions (list, get by ID)
- Benefit types (list)
- Balances
- Transactions (list, get by ID, create async/sync, confirm async/sync, cancel)
- Lookup operators by mobile number
- Statement inquiry lookup
- Credit party lookup (remaining benefits, status)
- Pagination support with meta data
- Production / Sandbox environment switching
- Retry mechanism for failed requests
- Response DTOs (typed objects with toArray() compatibility)
- Webhook / Callback support with event dispatching
- Signature verification middleware
- Laravel notifications channel integration
- Caching layer for discovery endpoints
- Configurable cache TTL per endpoint
- Rate limiting awareness (respects `X-RateLimit` headers)
- Artisan commands (`dtone:balance`, `dtone:products`, `dtone:transaction`, `dtone:cache-clear`, `dtone:health`)
- Health check command
- Test suite (110 tests, 248 assertions)
- Support for Laravel 7 - 12

Roadmap
-------

[](#roadmap)

- Batch transactions support
- Auto-paginate helper (fetch all pages automatically)
- Webhook queue integration (dispatch events to queue)

Testing
-------

[](#testing)

```
composer test
```

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE) for more information.

###  Health Score

45

—

FairBetter than 93% of packages

Maintenance86

Actively maintained with recent releases

Popularity12

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity60

Established project with proven stability

 Bus Factor1

Top contributor holds 85.7% 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 ~324 days

Recently: every ~315 days

Total

6

Last Release

68d ago

Major Versions

v1.2 → v2.02026-03-09

v2.0 → v3.02026-03-09

### Community

Maintainers

![](https://www.gravatar.com/avatar/fafeedb68c6ad2ddbb249caed67289c8c74073d25fcfb210534a9769d393dda4?d=identicon)[ghanem](/maintainers/ghanem)

---

Top Contributors

[![AbdullahGhanem](https://avatars.githubusercontent.com/u/5055892?v=4)](https://github.com/AbdullahGhanem "AbdullahGhanem (12 commits)")[![mohamedhamdy5](https://avatars.githubusercontent.com/u/10795780?v=4)](https://github.com/mohamedhamdy5 "mohamedhamdy5 (2 commits)")

---

Tags

airtimeairtime-paymentdtonelaravelphpphpapilaraveldtoneDT OneDVS

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/ghanem-dtone/health.svg)

```
[![Health](https://phpackages.com/badges/ghanem-dtone/health.svg)](https://phpackages.com/packages/ghanem-dtone)
```

###  Alternatives

[resend/resend-laravel

Resend for Laravel

1191.4M6](/packages/resend-resend-laravel)[dariusiii/tmdb-laravel

Laravel Package for TMDB ( The Movie Database ) API. Provides easy access to the wtfzdotnet/php-tmdb-api library.

1821.1k](/packages/dariusiii-tmdb-laravel)[gufy/whmcs

WHMCS API for Laravel 5

201.7k](/packages/gufy-whmcs)

PHPackages © 2026

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