定制 sashalenz/viber-bot-api 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

sashalenz/viber-bot-api

Composer 安装命令:

composer require sashalenz/viber-bot-api

包简介

Viber Bot REST API SDK for Laravel — client, typed DTOs, webhook signature verification and a nutgram-style handler engine.

README 文档

README

Viber Bot REST API SDK for Laravel — a typed HTTP client, webhook signature verification, and a nutgram-style inbound handler engine.

It is the reusable Viber engine (think nutgram/nutgram + its Laravel bridge): the package owns the protocol, while app-specific glue (persistence, CRM binding, notification channels) lives in your application.

Features

  • Outbound clientAccount, Messages, Users over a typed transport with timeout/retry and per-call token override (multi-account).
  • Message builders — text, picture, video, file, contact, location, url, sticker, and rich-media (carousel), each self-validating its Viber constraints.
  • Keyboards — fluent Button / Keyboard builders and a SharePhoneButton onboarding primitive.
  • Webhook securityX-Viber-Content-Signature HMAC-SHA256 verification as route middleware.
  • Typed inbound events — every callback hydrated into a spatie/laravel-data DTO (MessageEvent, SubscribedEvent, ConversationStartedEvent, …).
  • Handler engine — register onMessage / onText / onContact / … handlers with a short-circuitable middleware pipeline; dispatched automatically from the webhook controller.
  • Artisan commands — manage the webhook lifecycle from the CLI.

Requirements

  • PHP 8.2 – 8.5
  • Laravel 11, 12, or 13

Installation

The package is distributed via a private Composer registry. Add the repository, then require it:

// composer.json
"repositories": [
    { "type": "composer", "url": "https://repo.xitedev.com" }
]
composer require sashalenz/viber-bot-api

Publish the config:

php artisan vendor:publish --tag="viber-bot-api-config"

Set at least the token and sender name in your .env:

VIBER_BOT_TOKEN=your-public-account-token
VIBER_BOT_SENDER_NAME=A20

Configuration

All options live in config/viber-bot-api.php and are env-driven:

Env var Default Purpose
VIBER_BOT_TOKEN Public-account auth token (X-Viber-Auth-Token).
VIBER_BOT_API_URL https://chatapi.viber.com/pa/ API base URL.
VIBER_BOT_SENDER_NAME Bot Sender name (Viber caps it at 28 chars).
VIBER_BOT_SENDER_AVATAR Sender avatar URL.
VIBER_BOT_WEBHOOK_ROUTES_ENABLED true Register the webhook route.
VIBER_BOT_WEBHOOK_PREFIX viber-bot-api Route path prefix.
VIBER_BOT_WEBHOOK_KEY webhook Route path segment.
VIBER_BOT_WEBHOOK_DOMAIN Optional route domain.
VIBER_BOT_WEBHOOK_MIDDLEWARE Extra middleware (comma-separated).
VIBER_BOT_VERIFY_SIGNATURE true Enforce the HMAC signature check.

event_types (the events requested on set_webhook) is an array in the config file and defaults to all of message, subscribed, unsubscribed, conversation_started, delivered, seen, failed.

Outbound

use Sashalenz\ViberBotApi\ViberBotApi;
use Sashalenz\ViberBotApi\Messages\TextMessage;

ViberBotApi::messages()->send($viberUserId, new TextMessage('Привіт 👋'));

// per-call token override (multi-account: e.g. dev vs prod bot)
ViberBotApi::messages()->token($prodToken)->send($id, new TextMessage(''));

// broadcast to up to 300 receivers per call
ViberBotApi::messages()->broadcast([$id1, $id2], new TextMessage(''));

send() / broadcast() return a typed SendMessageResponse (->status, ->message_token, …). A non-zero Viber status throws ViberBotApiException.

Message builders

Every builder implements MessageContract and validates its own Viber constraints in the constructor (throwing ViberBotApiException). Media is URL-based — pass a public https:// URL, not a binary upload.

use Sashalenz\ViberBotApi\Messages\{
    TextMessage, PictureMessage, VideoMessage, FileMessage, ContactMessage,
    LocationMessage, UrlMessage, StickerMessage, RichMediaMessage,
};
use Sashalenz\ViberBotApi\Keyboards\Button;

new TextMessage('Hello');                                   // ≤ 7000 chars
new PictureMessage('https://cdn/p.jpg', text: 'caption');   // caption ≤ 768
new VideoMessage('https://cdn/v.mp4', size: 1_200_000);     // ≤ 26 MB
new FileMessage('https://cdn/d.pdf', size: 50_000, fileName: 'invoice.pdf'); // ≤ 50 MB
new ContactMessage('Itamar', '+972511123123');
new LocationMessage(50.4501, 30.5234);
new UrlMessage('https://example.com');
new StickerMessage(40_100);
new RichMediaMessage(buttons: [Button::make()->text('Buy')->actionBody('buy')]);

Keyboards

use Sashalenz\ViberBotApi\Keyboards\{Keyboard, Button, SharePhoneButton};

$keyboard = Keyboard::make()
    ->button(Button::make()->text('Yes')->actionType('reply')->actionBody('yes'))
    ->button(Button::make()->text('No')->actionType('reply')->actionBody('no'))
    ->toArray();

ViberBotApi::messages()->send($id, new TextMessage('Confirm?', $keyboard));

// onboarding: ask the user to share their phone (binds a Viber id to a CRM record)
ViberBotApi::messages()->send(
    $id,
    new TextMessage('Share your number', (new SharePhoneButton)->toArray()),
);

Account / webhook

$info = ViberBotApi::account()->info();   // read-only — safe on a live bot
$info->webhook;                            // current webhook url
$info->subscribers_count;

ViberBotApi::account()->setWebhook('https://example.com/viber-bot-api/webhook');
ViberBotApi::account()->removeWebhook();   // rollback

⚠️ A Viber bot has exactly one webhook. setWebhook overwrites the previous one — there is no parallel delivery.

Users

$details = ViberBotApi::users()->details($viberUserId); // cache: max 2 calls/12h per user
$details->user;                                          // id, name, avatar, country, …

ViberBotApi::users()->online([$id1, $id2]);             // ≤ 100 ids per call

Inbound

The package registers POST /{prefix}/{webhook_key} (default /viber-bot-api/webhook), guarded by the VerifyViberSignature middleware (HMAC-SHA256 of the raw body against your token). Prefix, domain, extra middleware, and on/off are configurable. The controller verifies the signature, parses the payload into a typed event, dispatches it through the container-bound Bot\Viber engine, and always responds 200 fast (Viber retries any non-200).

Registering handlers

Bot\Viber is bound as a singleton, so register handlers once — e.g. in a service provider's boot():

use Closure;
use Sashalenz\ViberBotApi\Bot\Viber;
use Sashalenz\ViberBotApi\Dto\Events\MessageEvent;
use Sashalenz\ViberBotApi\Dto\Update;
use Sashalenz\ViberBotApi\Messages\TextMessage;

$bot = app(Viber::class);

// middleware runs before/after, in registration order, and can short-circuit
$bot->middleware(fn (Update $update, Closure $next) => $next($update));

$bot->onText('/start', fn (MessageEvent $e, Viber $bot) => $bot->reply(new TextMessage('Hi!')));
$bot->onContact(fn (MessageEvent $e) => logger()->info('phone', [$e->message->contact?->phone_number]));
$bot->onMessage(fn (MessageEvent $e, Viber $bot) => $bot->reply(new TextMessage('echo: '.$e->message->text)));

$bot->onSubscribed(fn ($e) => /* … */ null);
$bot->onDelivered(fn ($e) => /* … */ null);   // also onSeen / onFailed / onUnsubscribed

The first matching handler (in registration order) wins. Handlers receive the typed event plus the bot instance; $bot->reply(...) sends a send_message back to the user behind the current update. onText($pattern, ...) matches the message text against an anchored unicode regex.

conversation_started

This event is special: the user is not subscribed yet, so a real send_message is rejected. Return a MessageContract (or payload array) from the handler and the controller emits it inline in the HTTP 200 response, wrapped with the sender envelope:

$bot->onConversationStarted(fn ($e) => new TextMessage('Welcome 👋'));

Console commands

php artisan viber:get-account-info            # read-only PA snapshot
php artisan viber:set-webhook {url?} --force  # register webhook (destructive — overwrites)
php artisan viber:delete-webhook --force      # detach webhook (rollback)

set-webhook defaults to the package webhook route URL when no argument is given, and prompts for confirmation unless --force is passed.

Typed request DTOs (optional)

If you prefer typed request payloads over the array/builder surface, use the RequestData DTOs:

use Sashalenz\ViberBotApi\RequestData\{SendMessageData, SetWebhookData};
use Sashalenz\ViberBotApi\Messages\TextMessage;

ViberBotApi::messages()->sendData(new SendMessageData(
    receiver: $viberUserId,
    message: new TextMessage('Привіт'),
    trackingData: 'order-42',
));

ViberBotApi::account()->setWebhookData(new SetWebhookData(
    url: 'https://example.com/viber-bot-api/webhook',  // must be HTTPS
    eventTypes: ['message', 'conversation_started'],
));

Testing

composer test        # Pest
composer analyse     # PHPStan (level 6)
composer format      # Pint

Viber gotchas baked into the design

  • User ids are opaque strings, not numbers.
  • conversation_started: the user is not yet subscribed — you can only greet by returning a send_message-shaped body in the HTTP response (within 5 min).
  • Media is URL-based (not binary uploads).
  • get_user_details is capped at 2 calls / 12h per user — cache it.
  • Commercial: customer-initiated session messages (24h window) are free; business-initiated messages are paid.

License

MIT. See LICENSE.md.

统计信息

  • 总下载量: 1
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 1
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-06-17

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固