PHPackages                             trungdv/zalo-otp - 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. [Mail &amp; Notifications](/categories/mail)
4. /
5. trungdv/zalo-otp

ActiveLibrary[Mail &amp; Notifications](/categories/mail)

trungdv/zalo-otp
================

Zalo OTP Package for Laravel - Send and verify OTP via Zalo API

v1.0.7(5mo ago)015MITPHPPHP ^8.1

Since Oct 22Pushed 5mo agoCompare

[ Source](https://github.com/trungdv-fabbi/zalo-otp)[ Packagist](https://packagist.org/packages/trungdv/zalo-otp)[ Docs](https://github.com/trungdv-fabbi/zalo-otp)[ RSS](/packages/trungdv-zalo-otp/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (4)Dependencies (5)Versions (9)Used By (0)

Zalo OTP Package for Laravel
============================

[](#zalo-otp-package-for-laravel)

A Laravel package for integrating with Zalo ZNS (Zalo Notification Service) API, enabling you to send OTP and transactional messages via Zalo platform.

Features
--------

[](#features)

- 🚀 Easy integration with Laravel applications
- 📱 Send OTP messages via Zalo ZNS
- 🔄 Access token refresh functionality
- 📊 Message delivery status tracking
- ⚡ Automatic error handling with custom exceptions
- 🛡️ Type-safe error codes
- 🔧 Configurable timeout and retry settings

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

[](#requirements)

- PHP &gt;= 8.1
- Laravel &gt;= 9.0
- GuzzleHttp &gt;= 7.0

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

[](#installation)

### 1. Install package

[](#1-install-package)

```
composer require trungdv/zalo-otp
```

### 2. Publish config file

[](#2-publish-config-file)

```
php artisan vendor:publish --tag=config
```

### 3. Configure in .env

[](#3-configure-in-env)

```
# Zalo OTP Configuration
ZALO_OTP_BASE_URL=https://oauth.zaloapp.com/v4/
ZALO_OTP_BUSINESS_BASE_URL=https://business.openapi.zalo.me/
ZALO_OTP_APP_ID=your_app_id
ZALO_OTP_APP_SECRET=your_app_secret
ZALO_OTP_TIMEOUT=30
ZALO_OTP_RETRY_ATTEMPTS=3
```

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

[](#configuration)

The config file is published at `config/zalo-otp.php`:

```
return [
    'base_url' => env('ZALO_OTP_BASE_URL', 'https://oauth.zaloapp.com/v4/'),
    'bussiness_base_url' => env('ZALO_OTP_BUSINESS_BASE_URL', 'https://business.openapi.zalo.me/'),
    'app_id' => env('ZALO_OTP_APP_ID'),
    'app_secret' => env('ZALO_OTP_APP_SECRET'),
    'timeout' => env('ZALO_OTP_TIMEOUT', 30),
    'retry_attempts' => env('ZALO_OTP_RETRY_ATTEMPTS', 3),
];
```

Usage
-----

[](#usage)

### Sending OTP

[](#sending-otp)

Send an OTP message to a phone number using a pre-configured Zalo ZNS template.

```
use TrungDV\ZaloOtp\Facades\ZaloOtp;
use TrungDV\ZaloOtp\Exceptions\ZaloException;

try {
    // Get instance
    $client = ZaloOtp::getInstance();

    // Send OTP
    $result = $client
        ->setAuthorization('your_access_token')
        ->sendOtp([
            'phone' => '0123456789',
            'template_id' => 'your_template_id',
            'template_data' => [
                'otp' => '123456',
                'expire_time' => '5 phút'
            ]
        ]);

    // Handle successful response
    echo "Message sent successfully!";
    echo "Message ID: " . $result['data']['msg_id'];

} catch (ZaloException $e) {
    // Handle Zalo API errors
    echo "Error Code: " . $e->getZaloErrorCode();
    echo "Error Message: " . $e->getMessage();
    echo "Error Detail: " . $e->getZaloErrorDetail();
}
```

#### Testing Mode

[](#testing-mode)

If you want to test sending messages without actually delivering them to users, you can add the `"mode": "development"` option in the params when calling `sendOtp()`.

**Important Note:** The development mode will only work when the recipient phone number has an admin role in your Zalo Official Account. Regular phone numbers will not receive messages in development mode.

```
try {
    $result = $client
        ->setAuthorization('your_access_token')
        ->sendOtp([
            'phone' => '0123456789', // Must be an admin phone number
            'mode' => 'development', // Testing mode
            'template_id' => 'your_template_id',
            'template_data' => [
                'otp' => '123456'
            ]
        ]);
} catch (ZaloException $e) {
    // Handle errors
}
```

### Refreshing Access Token

[](#refreshing-access-token)

Refresh your Zalo access token using a refresh token.

```
use TrungDV\ZaloOtp\Facades\ZaloOtp;
use TrungDV\ZaloOtp\Exceptions\ZaloException;

try {
    // Get instance
    $client = ZaloOtp::getInstance();

    // Set refresh token and refresh
    $result = $client
        ->setRefreshToken('your_refresh_token')
        ->refreshToken();

    // Get new access token
    $newAccessToken = $result['access_token'];
    $newRefreshToken = $result['refresh_token'];
    $expiresIn = $result['expires_in'];

    // Store tokens for future use
    // ...

} catch (ZaloException $e) {
    // Handle token refresh errors
    echo "Failed to refresh token: " . $e->getMessage();
}
```

### Checking Message Status

[](#checking-message-status)

Check the delivery status of a sent message.

```
use TrungDV\ZaloOtp\Facades\ZaloOtp;
use TrungDV\ZaloOtp\Exceptions\ZaloException;

try {
    // Get instance
    $client = ZaloOtp::getInstance();

    // Get message status
    $result = $client
        ->setAuthorization('your_access_token')
        ->getStatusMessage([
            'message_id' => '1234567890',
            'phone' => '0123456789'
        ]);

    // Check delivery status
    $status = $result['data']['status'];
    $sentTime = $result['data']['sent_time'];

    echo "Message Status: " . $status;

} catch (ZaloException $e) {
    // Handle errors
    echo "Failed to get message status: " . $e->getMessage();
}
```

Error Handling
--------------

[](#error-handling)

The package provides comprehensive error handling through the `ZaloException` class. All API methods automatically validate responses and throw exceptions when errors occur.

### Exception Methods

[](#exception-methods)

```
try {
    $result = $client->sendOtp([...]);
} catch (ZaloException $e) {
    // Get Zalo error code (integer)
    $errorCode = $e->getZaloErrorCode();

    // Get user-friendly error message (in Vietnamese)
    $message = $e->getMessage();

    // Get detailed error message from Zalo API
    $detail = $e->getZaloErrorDetail();

    // Get all error data as array
    $errorData = $e->toArray();
    /*
    [
        'zalo_error_code' => -108,
        'zalo_error_detail' => 'Phone number is invalid',
        'message' => 'Số điện thoại không hợp lệ'
    ]
    */
}
```

### Common Error Codes

[](#common-error-codes)

Error CodeDescription`0`Success`-100`Unknown error`-108`Invalid phone number`-115`Out of quota (insufficient balance)`-124`Invalid access token`-144`Daily ZNS quota exceededFor a complete list of error codes, check the `ZaloErrorCode` enum in `src/Consts/ZaloErrorCode.php`.

Response Format
---------------

[](#response-format)

All methods return an array containing the parsed JSON response from Zalo API:

### Successful Response Example

[](#successful-response-example)

```
[
    'error' => 0,
    'message' => 'Success',
    'data' => [
        'msg_id' => '1234567890',
        'sent_time' => '2024-01-01 12:00:00',
        // ... other data
    ]
]
```

Advanced Usage
--------------

[](#advanced-usage)

### Phone Number Formatting

[](#phone-number-formatting)

The package automatically formats Vietnamese phone numbers from `0xxx` format to `84xxx` format:

```
// Both formats are accepted
$client->sendOtp(['phone' => '0123456789', ...]); // Automatically converts to 84123456789
$client->sendOtp(['phone' => '84123456789', ...]); // Already in correct format
```

### Custom Headers

[](#custom-headers)

You can set custom headers for your requests:

```
$client->setHeaders([
    'Custom-Header' => 'value'
]);
```

### Debug Mode

[](#debug-mode)

For debugging purposes, you can generate a cURL command from your requests:

```
$curlCommand = $client->toCurlFromPendingRequest(
    $request,
    'POST',
    'https://api.zalo.me/endpoint',
    ['param' => 'value']
);
echo $curlCommand;
```

License
-------

[](#license)

MIT License. See [LICENSE](LICENSE) file for more details.

Contributing
------------

[](#contributing)

1. Fork repository
2. Create feature branch (`git checkout -b feature/amazing-feature`)
3. Commit changes (`git commit -m 'Add amazing feature'`)
4. Push to branch (`git push origin feature/amazing-feature`)
5. Create Pull Request

Support
-------

[](#support)

If you encounter any issues or have questions, please:

- Create an issue on [GitHub Issues](https://github.com/trungdv-fabbi/zalo-otp/issues)
- Contact:

Testing
-------

[](#testing)

Before using in production, test your integration in development mode:

```
// Send to admin phone numbers only
$result = $client->sendOtp([
    'phone' => 'admin_phone',
    'mode' => 'development',
    // ...
]);
```

Security
--------

[](#security)

- Never commit your `.env` file or expose your `ZALO_OTP_APP_SECRET`
- Store access tokens securely (database with encryption, cache with proper TTL)
- Implement rate limiting for OTP sending to prevent abuse
- Validate phone numbers before sending OTP

Changelog
---------

[](#changelog)

See [CHANGELOG.md](CHANGELOG.md) for detailed version history.

### Latest Changes

[](#latest-changes)

**v1.0.4**

- ✨ Added automatic error handling with `ZaloException`
- ✨ Integrated error handling directly into `ZaloClient`
- 🔥 Removed separate helpers file
- 📝 Improved documentation with comprehensive examples
- 🛡️ Type-safe error codes with `ZaloErrorCode` enum

**v1.0.0**

- 🎉 Initial release
- ✅ Send OTP via Zalo ZNS
- ✅ Refresh access token
- ✅ Get message delivery status
- ✅ Support for HTTP methods (GET, POST, PUT, PATCH)
- ✅ Facade support
- ✅ Service Container integration

###  Health Score

35

—

LowBetter than 79% of packages

Maintenance70

Regular maintenance activity

Popularity6

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 ~4 days

Total

8

Last Release

175d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/9fe575a5d11329025c64f2e33645eef88aad6dc512cb61bbf04eab50fb5dc5ab?d=identicon)[trungdv-fabbi](/maintainers/trungdv-fabbi)

---

Top Contributors

[![trungdv-fabbi](https://avatars.githubusercontent.com/u/54126491?v=4)](https://github.com/trungdv-fabbi "trungdv-fabbi (11 commits)")

---

Tags

apilaravelotpnotificationsmszalo

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/trungdv-zalo-otp/health.svg)

```
[![Health](https://phpackages.com/badges/trungdv-zalo-otp/health.svg)](https://phpackages.com/packages/trungdv-zalo-otp)
```

###  Alternatives

[laravel-notification-channels/telegram

Telegram Notifications Channel for Laravel

1.1k3.4M35](/packages/laravel-notification-channels-telegram)[gr8shivam/laravel-sms-api

A modern, flexible Laravel package for integrating any SMS gateway with REST API support

10138.4k](/packages/gr8shivam-laravel-sms-api)[laravel-notification-channels/twilio

Provides Twilio notification channel for Laravel

2587.7M12](/packages/laravel-notification-channels-twilio)[laravel-notification-channels/discord

Laravel notification driver for Discord.

2371.3M11](/packages/laravel-notification-channels-discord)[tzsk/sms

A robust and unified SMS gateway integration package for Laravel, supporting multiple providers.

320244.3k6](/packages/tzsk-sms)[ghanem/laravel-smsmisr

Send SMS and SMS Notification via SMS Misr for Laravel

194.8k](/packages/ghanem-laravel-smsmisr)

PHPackages © 2026

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