chen-zhanjie / hyperf-wechat-clawbot
Hyperf WeChat ClawBot SDK — iLink Bot API wrapper
Package info
github.com/chen-zhanjie/hyperf-wechat-clawbot
Type:hyperf-extension
pkg:composer/chen-zhanjie/hyperf-wechat-clawbot
Requires
- php: >=8.1
- psr/log: ^2.0|^3.0
Requires (Dev)
- phpunit/phpunit: ^10.0
README
简体中文 | English
A Hyperf extension that wraps the WeChat iLink Bot HTTP API, enabling PHP developers to build WeChat bot applications without dealing with low-level protocol details.
Composer: chen-zhanjie/hyperf-wechat-clawbot
PHP: >=8.1 | Framework: Hyperf (Swoole coroutine)
Features
- QR code login flow with auto-refresh
- Long-polling message loop with session expiry detection
- AES-128-ECB encryption for media upload/download
- CDN file upload pipeline with retry logic
- Streaming text delivery with automatic chunking
- Typing indicator lifecycle management
- 27 typed events across 8 categories
- Multi-bot architecture with isolated dependency graphs
- SaaS-friendly split lifecycle (bind / completeBind / startPolling)
Installation
composer require chen-zhanjie/hyperf-wechat-clawbot
Publish the config file:
php bin/hyperf.php vendor:publish chen-zhanjie/hyperf-wechat-clawbot
Quick Start
1. Configure
Edit config/autoload/wechat-clawbot/clawbot.php:
return [ 'bots' => [ 'default' => [ 'poll_timeout' => 35, 'stream' => [ 'char_threshold' => 200, 'idle_timeout' => 3.0, ], ], ], ];
2. Create a Message Handler
use ChenZhanjie\WechatClawbot\Contract\MessageHandlerInterface; use ChenZhanjie\WechatClawbot\Contract\BotInterface; use ChenZhanjie\WechatClawbot\Entity\WeixinMessage; class EchoHandler implements MessageHandlerInterface { public function handle(WeixinMessage $msg, BotInterface $bot): void { $bot->sendText($msg->replyTarget(), 'You said: ' . $msg->getTextBody()); } }
3. Start the Bot
php bin/hyperf.php clawbot:start
Start a specific bot:
php bin/hyperf.php clawbot:start --bot=default
SaaS Usage (HTTP-triggered)
use ChenZhanjie\WechatClawbot\Facade\BotManager; class BotController { public function bind(BotManager $manager): Response { $name = 'user_' . auth()->id(); $clawBot = $manager->add($name, []); $qr = $clawBot->bind(); return json(['qr_url' => $qr->qrCodeImgContent]); } public function unbind(BotManager $manager): Response { $name = 'user_' . auth()->id(); $manager->remove($name); return json(['status' => 'unbound']); } }
Events
Register event listeners on a bot instance:
use ChenZhanjie\WechatClawbot\Entity\Enum\BotEventType; use ChenZhanjie\WechatClawbot\Entity\BotEvent; $clawBot->on(BotEventType::MESSAGE_RECEIVED, function (BotEvent $event) { logger()->info('Message from ' . $event->message->fromUserID); }); $clawBot->once(BotEventType::SESSION_EXPIRED, function (BotEvent $event) { logger()->warning('Session expired for ' . $event->accountId); });
Available Events (27 types, 8 categories)
| Category | Events |
|---|---|
| Lifecycle | SESSION_STARTED, SESSION_EXPIRED, SESSION_PAUSED, SESSION_RESUMED, SESSION_STOPPED |
| Messaging | MESSAGE_RECEIVED, MESSAGE_SENT, MESSAGE_FAILED, MESSAGE_QUEUED |
| Media | MEDIA_UPLOAD_STARTED, MEDIA_UPLOAD_PROGRESS, MEDIA_UPLOAD_COMPLETED, MEDIA_UPLOAD_FAILED, MEDIA_DOWNLOAD_COMPLETED |
| Streaming | STREAM_STARTED, STREAM_CHUNK_SENT, STREAM_CLOSED |
| Typing | TYPING_STARTED, TYPING_CANCELLED |
| Login | QR_CODE_FETCHED, QR_CODE_SCANNED, QR_CODE_REFRESHED, QR_CODE_REDIRECTED |
| Polling | POLL_SUCCESS, POLL_ERROR, POLL_BACKOFF |
| Quota | QUOTA_WARNING |
Architecture
Layer 1: Contract/ -- Interfaces, DTOs, enums (zero dependencies)
Layer 2: Subsystem/ -- HttpClient, Crypto, PollLoop, MediaUpload
Layer 3: Core/ -- Bot (orchestrator), Session, StreamSender
Layer 4: Facade/ -- ClawBot (entry point), BotManager (multi-bot)
Layer 5: Entry/ -- ConfigProvider, Commands
Dependencies flow downward only. Layer 1 has zero upstream dependencies.
Documentation
| Document | Description |
|---|---|
| Getting Started | Installation and quick start guide |
| API Reference | Full interface and class reference |
| Architecture | 5-layer architecture overview |
简体中文文档:README.zh-CN.md | docs/zh/
Message Types
| Type | Value | Description |
|---|---|---|
| Text | 1 | Plain text messages |
| Image | 2 | CDN-referenced images |
| Voice | 3 | Audio with optional transcription |
| File | 4 | File attachments |
| Video | 5 | Video with thumbnail |
Key Concepts
contextToken
Conversation context token. Strongly recommended — omitting it breaks quote-reply features. Changes per message; must persist across restarts. SDK auto-extracts from inbound messages and injects on send.
typingTicket
Optional credential for typing indicators. Auto-disappears after ~seconds; SDK resends every 5s during streaming.
Message Quota
After a user sends a message, the bot has a 24h window to send up to 10 messages. Streaming bubbles each consume 1 quota.
Testing
vendor/bin/phpunit
License
MIT