balfour/ whatsapp-client
一个用于通过chat-api.com API处理WhatsApp通信的库
Requires
- php: >=7.3.0
- guzzlehttp/guzzle: ^6.3
- nesbot/carbon: ^2.0
This package is auto-updated.
Last update: 2022-05-24 16:04:39 UTC
README
一个用于通过非官方chat-api.com WhatsApp API处理WhatsApp通信的库。
此库处于早期发布阶段,正在等待单元测试。
法律声明
此代码与WhatsApp及其关联公司或子公司无关,未经授权、维护、赞助或认可。这是一个仅用于教育目的的独立非官方API,应自行承担风险使用。
目录
安装
composer require balfour/whatsapp-client
使用
有关chat-api的更多文档,请参阅https://chat-api.com/en/swagger.html
创建客户端
use Balfour\WhatsApp\WhatsApp; use GuzzleHttp\Client; $guzzle = new Client(); $client = new WhatsApp( $guzzle, 'https://euXXXX.chat-api.com/instanceXXXXXX', 'your-api-token' );
发送消息
$client->sendMessage('+27111111111', 'This is a test message.');
发送文件
use Balfour\WhatsApp\File; $file = new File('https://placehold.it/600x600', 'my_image.png'); $client->sendFile('+27111111111', $file);
检索消息
$messages = $client->getMessages(); foreach ($messages as $message) { var_dump($message->getChatId()); var_dump($message->getMessageId()); var_dump($message->getPhoneNumber()); var_dump($message->getType()); var_dump($message->getMessage()); var_dump($message->getMediaUrl()); var_dump($message->getDate()); var_dump($message->isOutbound()); var_dump($message->isInbound()); var_dump($message->getMessageNumber()); } // in order to only retrieve messages from a specific message number, you can pass a message number into // the getMessages() call $messages = $client->getMessages(12345);
重启虚拟机
$client->reboot();
构建机器人
以下提供了一个连接触发器、操作和中间件的完整使用示例。
操作
操作是在匹配触发器或菜单选项时执行的反应。
此包附带以下操作
SendMessageAction
此操作以消息作为响应。
use Balfour\WhatsApp\Bot\Actions\SendMessageAction; $action = new SendMessageAction('The weather in Cape Town, South Africa is 14°C.'); // or $callable = function ($message) { // retrieve weather conditions $city = 'Cape Town, South Africa'; $temperature = $myWeatherService->getTemperature($city); return sprintf('The weather in %s is %s', $city, $temperature); }; $action = new SendMessageAction($callable);
SendFileAction
此操作以附加文件(或图像)作为响应。
use Balfour\WhatsApp\Bot\Actions\SendFileAction; use Balfour\WhatsApp\File; $file = new File('https://placehold.it/600x600', 'my_image.png'); $action = new SendFileAction($file);
SendMenuAction
请参阅菜单
EscapeMenuAction
请参阅菜单
SendAndActivateMenuAction
请参阅菜单
自定义
您可以通过创建一个实现ActionInterface
的自定义类来自定义操作。
use Balfour\WhatsApp\Message; use Balfour\WhatsApp\WhatsApp; interface ActionInterface { /** * @param WhatsApp $client * @param Message $message */ public function execute(WhatsApp $client, Message $message): void; /** * @param Message $message * @return string|null */ public function emulate(Message $message): ?string; }
以下是一个重复接收消息的示例操作。
use Balfour\WhatsApp\Bot\Actions\ActionInterface; use Balfour\WhatsApp\Message; use Balfour\WhatsApp\WhatsApp; class RepeatAndSendMessageAction implements ActionInterface { /** * @param Message $message * @return string */ protected function getResponse(Message $message): string { return sprintf('You said: %s', $message->getMessage()); } /** * @param WhatsApp $client * @param Message $message * @throws \GuzzleHttp\Exception\GuzzleException */ public function execute(WhatsApp $client, Message $message): void { $client->sendMessage($message->getPhoneNumber(), $this->getResponse($message)); } /** * @param Message $message * @return string|null */ public function emulate(Message $message): ?string { return sprintf( "Sending message to <%s>:\n\n%s", $message->getPhoneNumber(), $this->getResponse($message) ); } }
触发器
触发器是指执行操作的入站关键词或短语。
以下触发器被支持
StringTrigger
入站消息必须是完全匹配的。
use Balfour\WhatsApp\Bot\Actions\SendMessageAction; use Balfour\WhatsApp\Bot\Triggers\StringTrigger; // when the bot sees "!weather", it will respond with the current temperature // the default is a case insensitive string comparison // eg: will match !WEATHER, !weather or !Weather $trigger = new StringTrigger( '!weather', new SendMessageAction('The weather in Cape Town, South Africa is 14°C.') ); // if you want to do a case sensitive match, you can pass in true as the 3rd parameter $trigger = new StringTrigger( '!weather', new SendMessageAction('The weather in Cape Town, South Africa is 14°C.'), true );
StartsWithTrigger
入站消息必须以指定的字符串开头。
use Balfour\WhatsApp\Bot\Actions\SendMessageAction; use Balfour\WhatsApp\Bot\Triggers\StartsWithTrigger; $trigger = new StartsWithTrigger( 'call', new SendMessageAction("We'll give you a call shortly!") ); // this will match any inbound message which starts with 'call', eg: 'call', or 'call me' // just like the StringTrigger, the matching is case insensitive by default // you can force a case sensitive match by passing true as the 3rd parameter
RegexTrigger
入站消息必须匹配给定的正则表达式模式。
use Balfour\WhatsApp\Bot\Actions\SendMessageAction; use Balfour\WhatsApp\Bot\Triggers\RegexTrigger; $trigger = new RegexTrigger( '/^(hi|hello|howzit)$/i', new SendMessageAction("Hi There!") );
菜单
单个菜单
这是一个单个菜单的示例。
必须使用触发器来激活菜单。(完整示例见文末)
use Balfour\WhatsApp\Bot\Actions\SendMessageAction; use Balfour\WhatsApp\Bot\Menu\Menu; use Balfour\WhatsApp\Bot\Menu\Option; $options = [ new Option( '1', 'Get a random cat fact', new SendMessageAction('Cats can rotate their ears 180 degrees.') ), new Option( '2', 'Fetch my available balance', new SendMessageAction('Your available balance is $10.00.') ), ]; $menu = new Menu( "Hello! I'm your friendly WhatsApp bot.", "You can press # to return to the main menu, or 'quit' to exit the menu.", $options ); // this example returns an error message when the user messages an invalid menu option $menu = new Menu( "Hello! I'm your friendly WhatsApp bot.", "You can press # to return to the main menu, or 'quit' to exit the menu.", $options, null, true, "I don't understand what you mean" );
嵌套菜单
这是一个包含多个嵌套菜单的更复杂示例。
为了保持用户当前所在的菜单状态,我们必须使用一个实现MenuStateStoreInterface
的方案。出于测试目的,此包附带了一个InMemoryMenuStateStore
;然而在现实世界中,你可能会想使用一个可以在多个PHP进程之间持久化的存储,例如Redis缓存。
use Balfour\WhatsApp\Bot\Actions\SendMessageAction; use Balfour\WhatsApp\Bot\Actions\SendAndActivateMenuAction; use Balfour\WhatsApp\Bot\Menu\InMemoryMenuStateStore; use Balfour\WhatsApp\Bot\Menu\Menu; use Balfour\WhatsApp\Bot\Menu\Option; $menuStateStore = new InMemoryMenuStateStore(); // first, build parent menu without any options $root = new Menu( "Hello! I'm your friendly WhatsApp bot.", "You can press # to return to the main menu, or 'quit' to exit the menu." ); // now, create weather menu, linking it to parent menu $weatherOptions = [ new Option( '1', 'Cape Town, South Africa', new SendMessageAction('The weather in Cape Town, South Africa is 14°C.') ), new Option( '2', 'Johannesburg, South Africa', new SendMessageAction('The weather in Johannesburg, South Africa is 9°C.') ), ]; $weatherMenu = new Menu( "Please select your city.", "You can press # to return to the main menu, @ to return to the previous menu or 'quit' to exit the menu.", $weatherOptions, $root ); // add options to parent menu $root->addOptions([ new Option( '1', 'Check the weather', new SendAndActivateMenuAction($weatherMenu, $menuStateStore) ), new Option( '2', 'Fetch my available balance', new SendMessageAction('Your available balance is $10.00.') ), ]);
中间件
机器人使用中间件将入站消息匹配到触发器或菜单选项。分别称为ProcessTrigger
和ProcessMenuOption
。
您还可以通过创建一个实现了MiddlewareInterface
的类来编写自己的中间件。
use Balfour\WhatsApp\Bot\Actions\ActionInterface; use Balfour\WhatsApp\Message; interface MiddlewareInterface { /** * @param Message $message * @return ActionInterface|null */ public function getAction(Message $message): ?ActionInterface; }
完整示例
此示例是从emulate.php
脚本中复制的,可以使用php emulate.php
在本地上运行。
use Balfour\WhatsApp\Bot\Actions\SendMessageAction; use Balfour\WhatsApp\Bot\Actions\SendAndActivateMenuAction; use Balfour\WhatsApp\Bot\Bot; use Balfour\WhatsApp\Bot\Emulator; use Balfour\WhatsApp\Bot\Menu\InMemoryMenuStateStore; use Balfour\WhatsApp\Bot\Menu\Menu; use Balfour\WhatsApp\Bot\Menu\Option; use Balfour\WhatsApp\Bot\Middleware\ProcessMenuOption; use Balfour\WhatsApp\Bot\Middleware\ProcessTrigger; use Balfour\WhatsApp\Bot\Triggers\StringTrigger; use Balfour\WhatsApp\Bot\Triggers\TriggerRegistry; // create menus $menuStateStore = new InMemoryMenuStateStore(); // first, build parent menu without any options $root = new Menu( "Hello! I'm your friendly WhatsApp bot.", "You can press # to return to the main menu, or 'quit' to exit the menu." ); // now, create weather menu, linking it to parent menu $weatherOptions = [ new Option( '1', 'Cape Town, South Africa', new SendMessageAction('The weather in Cape Town, South Africa is 14°C.') ), new Option( '2', 'Johannesburg, South Africa', new SendMessageAction('The weather in Johannesburg, South Africa is 9°C.') ), ]; $weatherMenu = new Menu( "Please select your city.", "You can press # to return to the main menu, @ to return to the previous menu or 'quit' to exit the menu.", $weatherOptions, $root ); // add options to parent menu $root->addOptions([ new Option( '1', 'Check the weather', new SendAndActivateMenuAction($weatherMenu, $menuStateStore) ), new Option( '2', 'Fetch my available balance', new SendMessageAction('Your available balance is $10.00.') ), ]); // create triggers $triggers = new TriggerRegistry(); // when we get 'ping', we'll respond 'pong' $triggers->register(new StringTrigger('ping', new SendMessageAction('pong!'))); // we'll want to bring up our root menu when the user types "menu" $triggers->register(new StringTrigger('menu', new SendAndActivateMenuAction($root, $menuStateStore))); // create bot with middleware loaded $middleware = [ new ProcessTrigger($triggers), new ProcessMenuOption($root, $menuStateStore) ]; $bot = new Bot($middleware); // create & run emulator $emulator = new Emulator($bot); $emulator->run(); // if we were running this in the real world, we'll want to process any inbound message through the bot // eg: when a message is received (via polling or web hook) // $bot->process($message);
模拟器
此包包括一个模拟器脚本,允许您在不发送真实世界消息的情况下测试菜单选项和触发器。
您可以使用php emulate.php
运行模拟器。