├── README.md
├── composer.json
├── composer.lock
├── composer.phar
└── public
├── config.php
├── files
├── file-example_PDF_500_kB.pdf
├── file_example_JPG_100kB.jpg
├── file_example_MP3_1MG.mp3
├── file_example_MP4_480_1_5MG.mp4
└── sample-vcard.txt
└── index.php
/README.md:
--------------------------------------------------------------------------------
1 | # PHP Whatsapp ChatBot
2 | WhatsApp PHP Bot. Basic functionality that the WhatsApp bot needs: send and receive messages, send image/file/docs/video, as well as creating a group and sending a message to the WhatsApp groupю
3 |
4 | We'll show you how to write a simple PHP bot using our Cloud API.
5 | The demo bot will react and respond to commands sent to it in the form of regular WhatsApp messages to your number. You can get a token for the bot by registering at https://panel.whapi.cloud/register
6 |
7 | ## Whapi.Cloud Php WhatsApp Integration
8 | This example of the WhatsApp bot implementation touches in detail on the most frequently used functionality: send message, send file, create group, send message to WhatsApp Group. This will allow you to adapt WhatsApp API and source code to your tasks and needs, or take it as a basis for creating any other integration.
9 | In the source code of the bot you will find the following functionality:
10 |
11 | - Respond to an unfamiliar command, this could be an instruction or your welcome message;
12 | - Send regular message;
13 | - Send image;
14 | - Send file;
15 | - Send video;
16 | - Send contact (vCard);
17 | - Send product;
18 | - Create new group, send an invitation and send message to the group;
19 | - Receive and reading incoming messages;
20 |
21 |
22 | For the bot to work, it is NOT REQUIRED that the phone is turned on or online. Connect the number and test the integration comfortably!
And if you need any help, just write to us in the support chat on any page of the site: https://whapi.cloud/features
23 |
24 | ## Getting Started
25 |
26 | ### Step 1: Install Composer
27 | Composer is a dependency manager for PHP. To install it: Visit the official Composer website https://getcomposer.org.
28 | Download and run Composer-Setup.exe for Windows or follow the installation instructions for MacOS or Linux.
29 |
30 | ### Step 2: Install Dependencies
31 | After installing Composer, install the necessary dependencies for your bot: Open the command line or terminal. Navigate to your project directory where the composer.json file is located.
32 | Run the command:
33 | ```sh
34 | composer install
35 | ```
36 | This reads the composer.json file, downloads the required libraries, and creates an autoload.php file that auto-loads all libraries in your project.
37 |
38 | ### Step 3: Configure the Project
39 | Configure your project settings: Open the config.php file in your IDE. Set up configurations such as your API token and webhook URL
40 |
41 | ### Step 4: Launch the Bot
42 | Now that dependencies are installed and the project is configured, you can launch the bot on your server or local machine. Ensure your server supports PHP and is accessible from the internet if you plan to use webhooks.
43 | Learn more about how to configure the webhook to work locally here: https://support.whapi.cloud/help-desk/receiving/webhooks/how-to-check-the-webhook#how-to-test-webhook-locally
44 |
45 |
46 | ### How to Connect to Whapi.Cloud and get API Token
47 | Registration: https://panel.whapi.cloud/register
48 | The first step is to register on the Whapi.Cloud website and create an account. It's free and doesn't require you to enter a credit card.
49 | After registration you will immediately have access to a test channel with a small limitation. Wait for it to start (it usually takes about a minute). You will need to connect your phone for Whatsapp automation. It is from the connected phone that messages will be sent. The big advantage of the service is that it takes only a couple of minutes to launch and start working.
50 |
51 | 
52 |
53 | To connect your phone, use the QR code available when you click on your trial channel in your personal account. Then open WhatsApp on your mobile device, go to Settings -> Connected devices -> Connect device -> Scan QR code.
54 |
55 | In the second and third steps, the service will ask you to customize the channel: write its name for your convenience, set webhooks, change settings. All these steps can be skipped, and we will come back to webhooks a little later. After launching, you will find in the center block under the information about limits, your API KEY, that is Token. This token will be used to authenticate your API requests. Generally, it's added to the request headers as a Bearer Token or simply as a request parameter, depending on the API method you're using.
56 |
57 | Paste the token into /public/config.php in the "token" line
58 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "require": {
3 | "guzzlehttp/guzzle": "^7.8",
4 | "slim/slim": "3.*"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/composer.lock:
--------------------------------------------------------------------------------
1 | {
2 | "_readme": [
3 | "This file locks the dependencies of your project to a known state",
4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
5 | "This file is @generated automatically"
6 | ],
7 | "content-hash": "a1440e02ea7aad80f39dca6f1e00938b",
8 | "packages": [
9 | {
10 | "name": "guzzlehttp/guzzle",
11 | "version": "7.8.0",
12 | "source": {
13 | "type": "git",
14 | "url": "https://github.com/guzzle/guzzle.git",
15 | "reference": "1110f66a6530a40fe7aea0378fe608ee2b2248f9"
16 | },
17 | "dist": {
18 | "type": "zip",
19 | "url": "https://api.github.com/repos/guzzle/guzzle/zipball/1110f66a6530a40fe7aea0378fe608ee2b2248f9",
20 | "reference": "1110f66a6530a40fe7aea0378fe608ee2b2248f9",
21 | "shasum": ""
22 | },
23 | "require": {
24 | "ext-json": "*",
25 | "guzzlehttp/promises": "^1.5.3 || ^2.0.1",
26 | "guzzlehttp/psr7": "^1.9.1 || ^2.5.1",
27 | "php": "^7.2.5 || ^8.0",
28 | "psr/http-client": "^1.0",
29 | "symfony/deprecation-contracts": "^2.2 || ^3.0"
30 | },
31 | "provide": {
32 | "psr/http-client-implementation": "1.0"
33 | },
34 | "require-dev": {
35 | "bamarni/composer-bin-plugin": "^1.8.1",
36 | "ext-curl": "*",
37 | "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999",
38 | "php-http/message-factory": "^1.1",
39 | "phpunit/phpunit": "^8.5.29 || ^9.5.23",
40 | "psr/log": "^1.1 || ^2.0 || ^3.0"
41 | },
42 | "suggest": {
43 | "ext-curl": "Required for CURL handler support",
44 | "ext-intl": "Required for Internationalized Domain Name (IDN) support",
45 | "psr/log": "Required for using the Log middleware"
46 | },
47 | "type": "library",
48 | "extra": {
49 | "bamarni-bin": {
50 | "bin-links": true,
51 | "forward-command": false
52 | }
53 | },
54 | "autoload": {
55 | "files": [
56 | "src/functions_include.php"
57 | ],
58 | "psr-4": {
59 | "GuzzleHttp\\": "src/"
60 | }
61 | },
62 | "notification-url": "https://packagist.org/downloads/",
63 | "license": [
64 | "MIT"
65 | ],
66 | "authors": [
67 | {
68 | "name": "Graham Campbell",
69 | "email": "hello@gjcampbell.co.uk",
70 | "homepage": "https://github.com/GrahamCampbell"
71 | },
72 | {
73 | "name": "Michael Dowling",
74 | "email": "mtdowling@gmail.com",
75 | "homepage": "https://github.com/mtdowling"
76 | },
77 | {
78 | "name": "Jeremy Lindblom",
79 | "email": "jeremeamia@gmail.com",
80 | "homepage": "https://github.com/jeremeamia"
81 | },
82 | {
83 | "name": "George Mponos",
84 | "email": "gmponos@gmail.com",
85 | "homepage": "https://github.com/gmponos"
86 | },
87 | {
88 | "name": "Tobias Nyholm",
89 | "email": "tobias.nyholm@gmail.com",
90 | "homepage": "https://github.com/Nyholm"
91 | },
92 | {
93 | "name": "Márk Sági-Kazár",
94 | "email": "mark.sagikazar@gmail.com",
95 | "homepage": "https://github.com/sagikazarmark"
96 | },
97 | {
98 | "name": "Tobias Schultze",
99 | "email": "webmaster@tubo-world.de",
100 | "homepage": "https://github.com/Tobion"
101 | }
102 | ],
103 | "description": "Guzzle is a PHP HTTP client library",
104 | "keywords": [
105 | "client",
106 | "curl",
107 | "framework",
108 | "http",
109 | "http client",
110 | "psr-18",
111 | "psr-7",
112 | "rest",
113 | "web service"
114 | ],
115 | "support": {
116 | "issues": "https://github.com/guzzle/guzzle/issues",
117 | "source": "https://github.com/guzzle/guzzle/tree/7.8.0"
118 | },
119 | "funding": [
120 | {
121 | "url": "https://github.com/GrahamCampbell",
122 | "type": "github"
123 | },
124 | {
125 | "url": "https://github.com/Nyholm",
126 | "type": "github"
127 | },
128 | {
129 | "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle",
130 | "type": "tidelift"
131 | }
132 | ],
133 | "time": "2023-08-27T10:20:53+00:00"
134 | },
135 | {
136 | "name": "guzzlehttp/promises",
137 | "version": "2.0.1",
138 | "source": {
139 | "type": "git",
140 | "url": "https://github.com/guzzle/promises.git",
141 | "reference": "111166291a0f8130081195ac4556a5587d7f1b5d"
142 | },
143 | "dist": {
144 | "type": "zip",
145 | "url": "https://api.github.com/repos/guzzle/promises/zipball/111166291a0f8130081195ac4556a5587d7f1b5d",
146 | "reference": "111166291a0f8130081195ac4556a5587d7f1b5d",
147 | "shasum": ""
148 | },
149 | "require": {
150 | "php": "^7.2.5 || ^8.0"
151 | },
152 | "require-dev": {
153 | "bamarni/composer-bin-plugin": "^1.8.1",
154 | "phpunit/phpunit": "^8.5.29 || ^9.5.23"
155 | },
156 | "type": "library",
157 | "extra": {
158 | "bamarni-bin": {
159 | "bin-links": true,
160 | "forward-command": false
161 | }
162 | },
163 | "autoload": {
164 | "psr-4": {
165 | "GuzzleHttp\\Promise\\": "src/"
166 | }
167 | },
168 | "notification-url": "https://packagist.org/downloads/",
169 | "license": [
170 | "MIT"
171 | ],
172 | "authors": [
173 | {
174 | "name": "Graham Campbell",
175 | "email": "hello@gjcampbell.co.uk",
176 | "homepage": "https://github.com/GrahamCampbell"
177 | },
178 | {
179 | "name": "Michael Dowling",
180 | "email": "mtdowling@gmail.com",
181 | "homepage": "https://github.com/mtdowling"
182 | },
183 | {
184 | "name": "Tobias Nyholm",
185 | "email": "tobias.nyholm@gmail.com",
186 | "homepage": "https://github.com/Nyholm"
187 | },
188 | {
189 | "name": "Tobias Schultze",
190 | "email": "webmaster@tubo-world.de",
191 | "homepage": "https://github.com/Tobion"
192 | }
193 | ],
194 | "description": "Guzzle promises library",
195 | "keywords": [
196 | "promise"
197 | ],
198 | "support": {
199 | "issues": "https://github.com/guzzle/promises/issues",
200 | "source": "https://github.com/guzzle/promises/tree/2.0.1"
201 | },
202 | "funding": [
203 | {
204 | "url": "https://github.com/GrahamCampbell",
205 | "type": "github"
206 | },
207 | {
208 | "url": "https://github.com/Nyholm",
209 | "type": "github"
210 | },
211 | {
212 | "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises",
213 | "type": "tidelift"
214 | }
215 | ],
216 | "time": "2023-08-03T15:11:55+00:00"
217 | },
218 | {
219 | "name": "guzzlehttp/psr7",
220 | "version": "2.6.1",
221 | "source": {
222 | "type": "git",
223 | "url": "https://github.com/guzzle/psr7.git",
224 | "reference": "be45764272e8873c72dbe3d2edcfdfcc3bc9f727"
225 | },
226 | "dist": {
227 | "type": "zip",
228 | "url": "https://api.github.com/repos/guzzle/psr7/zipball/be45764272e8873c72dbe3d2edcfdfcc3bc9f727",
229 | "reference": "be45764272e8873c72dbe3d2edcfdfcc3bc9f727",
230 | "shasum": ""
231 | },
232 | "require": {
233 | "php": "^7.2.5 || ^8.0",
234 | "psr/http-factory": "^1.0",
235 | "psr/http-message": "^1.1 || ^2.0",
236 | "ralouphie/getallheaders": "^3.0"
237 | },
238 | "provide": {
239 | "psr/http-factory-implementation": "1.0",
240 | "psr/http-message-implementation": "1.0"
241 | },
242 | "require-dev": {
243 | "bamarni/composer-bin-plugin": "^1.8.1",
244 | "http-interop/http-factory-tests": "^0.9",
245 | "phpunit/phpunit": "^8.5.29 || ^9.5.23"
246 | },
247 | "suggest": {
248 | "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
249 | },
250 | "type": "library",
251 | "extra": {
252 | "bamarni-bin": {
253 | "bin-links": true,
254 | "forward-command": false
255 | }
256 | },
257 | "autoload": {
258 | "psr-4": {
259 | "GuzzleHttp\\Psr7\\": "src/"
260 | }
261 | },
262 | "notification-url": "https://packagist.org/downloads/",
263 | "license": [
264 | "MIT"
265 | ],
266 | "authors": [
267 | {
268 | "name": "Graham Campbell",
269 | "email": "hello@gjcampbell.co.uk",
270 | "homepage": "https://github.com/GrahamCampbell"
271 | },
272 | {
273 | "name": "Michael Dowling",
274 | "email": "mtdowling@gmail.com",
275 | "homepage": "https://github.com/mtdowling"
276 | },
277 | {
278 | "name": "George Mponos",
279 | "email": "gmponos@gmail.com",
280 | "homepage": "https://github.com/gmponos"
281 | },
282 | {
283 | "name": "Tobias Nyholm",
284 | "email": "tobias.nyholm@gmail.com",
285 | "homepage": "https://github.com/Nyholm"
286 | },
287 | {
288 | "name": "Márk Sági-Kazár",
289 | "email": "mark.sagikazar@gmail.com",
290 | "homepage": "https://github.com/sagikazarmark"
291 | },
292 | {
293 | "name": "Tobias Schultze",
294 | "email": "webmaster@tubo-world.de",
295 | "homepage": "https://github.com/Tobion"
296 | },
297 | {
298 | "name": "Márk Sági-Kazár",
299 | "email": "mark.sagikazar@gmail.com",
300 | "homepage": "https://sagikazarmark.hu"
301 | }
302 | ],
303 | "description": "PSR-7 message implementation that also provides common utility methods",
304 | "keywords": [
305 | "http",
306 | "message",
307 | "psr-7",
308 | "request",
309 | "response",
310 | "stream",
311 | "uri",
312 | "url"
313 | ],
314 | "support": {
315 | "issues": "https://github.com/guzzle/psr7/issues",
316 | "source": "https://github.com/guzzle/psr7/tree/2.6.1"
317 | },
318 | "funding": [
319 | {
320 | "url": "https://github.com/GrahamCampbell",
321 | "type": "github"
322 | },
323 | {
324 | "url": "https://github.com/Nyholm",
325 | "type": "github"
326 | },
327 | {
328 | "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7",
329 | "type": "tidelift"
330 | }
331 | ],
332 | "time": "2023-08-27T10:13:57+00:00"
333 | },
334 | {
335 | "name": "nikic/fast-route",
336 | "version": "v1.3.0",
337 | "source": {
338 | "type": "git",
339 | "url": "https://github.com/nikic/FastRoute.git",
340 | "reference": "181d480e08d9476e61381e04a71b34dc0432e812"
341 | },
342 | "dist": {
343 | "type": "zip",
344 | "url": "https://api.github.com/repos/nikic/FastRoute/zipball/181d480e08d9476e61381e04a71b34dc0432e812",
345 | "reference": "181d480e08d9476e61381e04a71b34dc0432e812",
346 | "shasum": ""
347 | },
348 | "require": {
349 | "php": ">=5.4.0"
350 | },
351 | "require-dev": {
352 | "phpunit/phpunit": "^4.8.35|~5.7"
353 | },
354 | "type": "library",
355 | "autoload": {
356 | "files": [
357 | "src/functions.php"
358 | ],
359 | "psr-4": {
360 | "FastRoute\\": "src/"
361 | }
362 | },
363 | "notification-url": "https://packagist.org/downloads/",
364 | "license": [
365 | "BSD-3-Clause"
366 | ],
367 | "authors": [
368 | {
369 | "name": "Nikita Popov",
370 | "email": "nikic@php.net"
371 | }
372 | ],
373 | "description": "Fast request router for PHP",
374 | "keywords": [
375 | "router",
376 | "routing"
377 | ],
378 | "support": {
379 | "issues": "https://github.com/nikic/FastRoute/issues",
380 | "source": "https://github.com/nikic/FastRoute/tree/master"
381 | },
382 | "time": "2018-02-13T20:26:39+00:00"
383 | },
384 | {
385 | "name": "pimple/pimple",
386 | "version": "v3.5.0",
387 | "source": {
388 | "type": "git",
389 | "url": "https://github.com/silexphp/Pimple.git",
390 | "reference": "a94b3a4db7fb774b3d78dad2315ddc07629e1bed"
391 | },
392 | "dist": {
393 | "type": "zip",
394 | "url": "https://api.github.com/repos/silexphp/Pimple/zipball/a94b3a4db7fb774b3d78dad2315ddc07629e1bed",
395 | "reference": "a94b3a4db7fb774b3d78dad2315ddc07629e1bed",
396 | "shasum": ""
397 | },
398 | "require": {
399 | "php": ">=7.2.5",
400 | "psr/container": "^1.1 || ^2.0"
401 | },
402 | "require-dev": {
403 | "symfony/phpunit-bridge": "^5.4@dev"
404 | },
405 | "type": "library",
406 | "extra": {
407 | "branch-alias": {
408 | "dev-master": "3.4.x-dev"
409 | }
410 | },
411 | "autoload": {
412 | "psr-0": {
413 | "Pimple": "src/"
414 | }
415 | },
416 | "notification-url": "https://packagist.org/downloads/",
417 | "license": [
418 | "MIT"
419 | ],
420 | "authors": [
421 | {
422 | "name": "Fabien Potencier",
423 | "email": "fabien@symfony.com"
424 | }
425 | ],
426 | "description": "Pimple, a simple Dependency Injection Container",
427 | "homepage": "https://pimple.symfony.com",
428 | "keywords": [
429 | "container",
430 | "dependency injection"
431 | ],
432 | "support": {
433 | "source": "https://github.com/silexphp/Pimple/tree/v3.5.0"
434 | },
435 | "time": "2021-10-28T11:13:42+00:00"
436 | },
437 | {
438 | "name": "psr/container",
439 | "version": "1.1.2",
440 | "source": {
441 | "type": "git",
442 | "url": "https://github.com/php-fig/container.git",
443 | "reference": "513e0666f7216c7459170d56df27dfcefe1689ea"
444 | },
445 | "dist": {
446 | "type": "zip",
447 | "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea",
448 | "reference": "513e0666f7216c7459170d56df27dfcefe1689ea",
449 | "shasum": ""
450 | },
451 | "require": {
452 | "php": ">=7.4.0"
453 | },
454 | "type": "library",
455 | "autoload": {
456 | "psr-4": {
457 | "Psr\\Container\\": "src/"
458 | }
459 | },
460 | "notification-url": "https://packagist.org/downloads/",
461 | "license": [
462 | "MIT"
463 | ],
464 | "authors": [
465 | {
466 | "name": "PHP-FIG",
467 | "homepage": "https://www.php-fig.org/"
468 | }
469 | ],
470 | "description": "Common Container Interface (PHP FIG PSR-11)",
471 | "homepage": "https://github.com/php-fig/container",
472 | "keywords": [
473 | "PSR-11",
474 | "container",
475 | "container-interface",
476 | "container-interop",
477 | "psr"
478 | ],
479 | "support": {
480 | "issues": "https://github.com/php-fig/container/issues",
481 | "source": "https://github.com/php-fig/container/tree/1.1.2"
482 | },
483 | "time": "2021-11-05T16:50:12+00:00"
484 | },
485 | {
486 | "name": "psr/http-client",
487 | "version": "1.0.3",
488 | "source": {
489 | "type": "git",
490 | "url": "https://github.com/php-fig/http-client.git",
491 | "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90"
492 | },
493 | "dist": {
494 | "type": "zip",
495 | "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90",
496 | "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90",
497 | "shasum": ""
498 | },
499 | "require": {
500 | "php": "^7.0 || ^8.0",
501 | "psr/http-message": "^1.0 || ^2.0"
502 | },
503 | "type": "library",
504 | "extra": {
505 | "branch-alias": {
506 | "dev-master": "1.0.x-dev"
507 | }
508 | },
509 | "autoload": {
510 | "psr-4": {
511 | "Psr\\Http\\Client\\": "src/"
512 | }
513 | },
514 | "notification-url": "https://packagist.org/downloads/",
515 | "license": [
516 | "MIT"
517 | ],
518 | "authors": [
519 | {
520 | "name": "PHP-FIG",
521 | "homepage": "https://www.php-fig.org/"
522 | }
523 | ],
524 | "description": "Common interface for HTTP clients",
525 | "homepage": "https://github.com/php-fig/http-client",
526 | "keywords": [
527 | "http",
528 | "http-client",
529 | "psr",
530 | "psr-18"
531 | ],
532 | "support": {
533 | "source": "https://github.com/php-fig/http-client"
534 | },
535 | "time": "2023-09-23T14:17:50+00:00"
536 | },
537 | {
538 | "name": "psr/http-factory",
539 | "version": "1.0.2",
540 | "source": {
541 | "type": "git",
542 | "url": "https://github.com/php-fig/http-factory.git",
543 | "reference": "e616d01114759c4c489f93b099585439f795fe35"
544 | },
545 | "dist": {
546 | "type": "zip",
547 | "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35",
548 | "reference": "e616d01114759c4c489f93b099585439f795fe35",
549 | "shasum": ""
550 | },
551 | "require": {
552 | "php": ">=7.0.0",
553 | "psr/http-message": "^1.0 || ^2.0"
554 | },
555 | "type": "library",
556 | "extra": {
557 | "branch-alias": {
558 | "dev-master": "1.0.x-dev"
559 | }
560 | },
561 | "autoload": {
562 | "psr-4": {
563 | "Psr\\Http\\Message\\": "src/"
564 | }
565 | },
566 | "notification-url": "https://packagist.org/downloads/",
567 | "license": [
568 | "MIT"
569 | ],
570 | "authors": [
571 | {
572 | "name": "PHP-FIG",
573 | "homepage": "https://www.php-fig.org/"
574 | }
575 | ],
576 | "description": "Common interfaces for PSR-7 HTTP message factories",
577 | "keywords": [
578 | "factory",
579 | "http",
580 | "message",
581 | "psr",
582 | "psr-17",
583 | "psr-7",
584 | "request",
585 | "response"
586 | ],
587 | "support": {
588 | "source": "https://github.com/php-fig/http-factory/tree/1.0.2"
589 | },
590 | "time": "2023-04-10T20:10:41+00:00"
591 | },
592 | {
593 | "name": "psr/http-message",
594 | "version": "1.1",
595 | "source": {
596 | "type": "git",
597 | "url": "https://github.com/php-fig/http-message.git",
598 | "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba"
599 | },
600 | "dist": {
601 | "type": "zip",
602 | "url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba",
603 | "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba",
604 | "shasum": ""
605 | },
606 | "require": {
607 | "php": "^7.2 || ^8.0"
608 | },
609 | "type": "library",
610 | "extra": {
611 | "branch-alias": {
612 | "dev-master": "1.1.x-dev"
613 | }
614 | },
615 | "autoload": {
616 | "psr-4": {
617 | "Psr\\Http\\Message\\": "src/"
618 | }
619 | },
620 | "notification-url": "https://packagist.org/downloads/",
621 | "license": [
622 | "MIT"
623 | ],
624 | "authors": [
625 | {
626 | "name": "PHP-FIG",
627 | "homepage": "http://www.php-fig.org/"
628 | }
629 | ],
630 | "description": "Common interface for HTTP messages",
631 | "homepage": "https://github.com/php-fig/http-message",
632 | "keywords": [
633 | "http",
634 | "http-message",
635 | "psr",
636 | "psr-7",
637 | "request",
638 | "response"
639 | ],
640 | "support": {
641 | "source": "https://github.com/php-fig/http-message/tree/1.1"
642 | },
643 | "time": "2023-04-04T09:50:52+00:00"
644 | },
645 | {
646 | "name": "ralouphie/getallheaders",
647 | "version": "3.0.3",
648 | "source": {
649 | "type": "git",
650 | "url": "https://github.com/ralouphie/getallheaders.git",
651 | "reference": "120b605dfeb996808c31b6477290a714d356e822"
652 | },
653 | "dist": {
654 | "type": "zip",
655 | "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822",
656 | "reference": "120b605dfeb996808c31b6477290a714d356e822",
657 | "shasum": ""
658 | },
659 | "require": {
660 | "php": ">=5.6"
661 | },
662 | "require-dev": {
663 | "php-coveralls/php-coveralls": "^2.1",
664 | "phpunit/phpunit": "^5 || ^6.5"
665 | },
666 | "type": "library",
667 | "autoload": {
668 | "files": [
669 | "src/getallheaders.php"
670 | ]
671 | },
672 | "notification-url": "https://packagist.org/downloads/",
673 | "license": [
674 | "MIT"
675 | ],
676 | "authors": [
677 | {
678 | "name": "Ralph Khattar",
679 | "email": "ralph.khattar@gmail.com"
680 | }
681 | ],
682 | "description": "A polyfill for getallheaders.",
683 | "support": {
684 | "issues": "https://github.com/ralouphie/getallheaders/issues",
685 | "source": "https://github.com/ralouphie/getallheaders/tree/develop"
686 | },
687 | "time": "2019-03-08T08:55:37+00:00"
688 | },
689 | {
690 | "name": "slim/slim",
691 | "version": "3.12.5",
692 | "source": {
693 | "type": "git",
694 | "url": "https://github.com/slimphp/Slim.git",
695 | "reference": "565632b2d9b64ecedf89546edbbf4f3648089f0c"
696 | },
697 | "dist": {
698 | "type": "zip",
699 | "url": "https://api.github.com/repos/slimphp/Slim/zipball/565632b2d9b64ecedf89546edbbf4f3648089f0c",
700 | "reference": "565632b2d9b64ecedf89546edbbf4f3648089f0c",
701 | "shasum": ""
702 | },
703 | "require": {
704 | "ext-json": "*",
705 | "ext-libxml": "*",
706 | "ext-simplexml": "*",
707 | "nikic/fast-route": "^1.0",
708 | "php": ">=5.5.0",
709 | "pimple/pimple": "^3.0",
710 | "psr/container": "^1.0",
711 | "psr/http-message": "^1.0"
712 | },
713 | "provide": {
714 | "psr/http-message-implementation": "1.0"
715 | },
716 | "require-dev": {
717 | "phpunit/phpunit": "^4.0",
718 | "squizlabs/php_codesniffer": "^3.6.0"
719 | },
720 | "type": "library",
721 | "autoload": {
722 | "psr-4": {
723 | "Slim\\": "Slim"
724 | }
725 | },
726 | "notification-url": "https://packagist.org/downloads/",
727 | "license": [
728 | "MIT"
729 | ],
730 | "authors": [
731 | {
732 | "name": "Josh Lockhart",
733 | "email": "hello@joshlockhart.com",
734 | "homepage": "https://joshlockhart.com"
735 | },
736 | {
737 | "name": "Andrew Smith",
738 | "email": "a.smith@silentworks.co.uk",
739 | "homepage": "http://silentworks.co.uk"
740 | },
741 | {
742 | "name": "Rob Allen",
743 | "email": "rob@akrabat.com",
744 | "homepage": "http://akrabat.com"
745 | },
746 | {
747 | "name": "Gabriel Manricks",
748 | "email": "gmanricks@me.com",
749 | "homepage": "http://gabrielmanricks.com"
750 | }
751 | ],
752 | "description": "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs",
753 | "homepage": "https://slimframework.com",
754 | "keywords": [
755 | "api",
756 | "framework",
757 | "micro",
758 | "router"
759 | ],
760 | "support": {
761 | "issues": "https://github.com/slimphp/Slim/issues",
762 | "source": "https://github.com/slimphp/Slim/tree/3.12.5"
763 | },
764 | "funding": [
765 | {
766 | "url": "https://opencollective.com/slimphp",
767 | "type": "open_collective"
768 | },
769 | {
770 | "url": "https://tidelift.com/funding/github/packagist/slim/slim",
771 | "type": "tidelift"
772 | }
773 | ],
774 | "time": "2023-07-23T04:32:51+00:00"
775 | },
776 | {
777 | "name": "symfony/deprecation-contracts",
778 | "version": "v3.0.2",
779 | "source": {
780 | "type": "git",
781 | "url": "https://github.com/symfony/deprecation-contracts.git",
782 | "reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c"
783 | },
784 | "dist": {
785 | "type": "zip",
786 | "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/26954b3d62a6c5fd0ea8a2a00c0353a14978d05c",
787 | "reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c",
788 | "shasum": ""
789 | },
790 | "require": {
791 | "php": ">=8.0.2"
792 | },
793 | "type": "library",
794 | "extra": {
795 | "branch-alias": {
796 | "dev-main": "3.0-dev"
797 | },
798 | "thanks": {
799 | "name": "symfony/contracts",
800 | "url": "https://github.com/symfony/contracts"
801 | }
802 | },
803 | "autoload": {
804 | "files": [
805 | "function.php"
806 | ]
807 | },
808 | "notification-url": "https://packagist.org/downloads/",
809 | "license": [
810 | "MIT"
811 | ],
812 | "authors": [
813 | {
814 | "name": "Nicolas Grekas",
815 | "email": "p@tchwork.com"
816 | },
817 | {
818 | "name": "Symfony Community",
819 | "homepage": "https://symfony.com/contributors"
820 | }
821 | ],
822 | "description": "A generic function and convention to trigger deprecation notices",
823 | "homepage": "https://symfony.com",
824 | "support": {
825 | "source": "https://github.com/symfony/deprecation-contracts/tree/v3.0.2"
826 | },
827 | "funding": [
828 | {
829 | "url": "https://symfony.com/sponsor",
830 | "type": "custom"
831 | },
832 | {
833 | "url": "https://github.com/fabpot",
834 | "type": "github"
835 | },
836 | {
837 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
838 | "type": "tidelift"
839 | }
840 | ],
841 | "time": "2022-01-02T09:55:41+00:00"
842 | }
843 | ],
844 | "packages-dev": [],
845 | "aliases": [],
846 | "minimum-stability": "stable",
847 | "stability-flags": [],
848 | "prefer-stable": false,
849 | "prefer-lowest": false,
850 | "platform": [],
851 | "platform-dev": [],
852 | "plugin-api-version": "2.6.0"
853 | }
854 |
--------------------------------------------------------------------------------
/composer.phar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Whapi-Cloud/php-whatsapp-chatbot/ed19119ccfacd986726715b194d475f1da88cbf9/composer.phar
--------------------------------------------------------------------------------
/public/config.php:
--------------------------------------------------------------------------------
1 | "https://gate.whapi.cloud",
5 | // API token from your channel
6 | "token" => "YOUR CHANNEL TOKEN ",
7 | // The ID of the group to which we will send the message. Use to find out the ID: https://whapi.readme.io/reference/getgroups
8 | "group" => '120363167596599603@g.us',
9 | // The ID of the product we will send for the example. Create a product in your WhatsApp and find out the product ID: https://whapi.readme.io/reference/getproducts
10 | "product" => '6559353560856703',
11 | // Bot`s URL - Link to your server. At ( {server link}/hook ), when POST is requested, processing occurs in index.php
12 | "botUrl" => "https://yoursite.com/hook"
13 | ];
14 |
--------------------------------------------------------------------------------
/public/files/file-example_PDF_500_kB.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Whapi-Cloud/php-whatsapp-chatbot/ed19119ccfacd986726715b194d475f1da88cbf9/public/files/file-example_PDF_500_kB.pdf
--------------------------------------------------------------------------------
/public/files/file_example_JPG_100kB.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Whapi-Cloud/php-whatsapp-chatbot/ed19119ccfacd986726715b194d475f1da88cbf9/public/files/file_example_JPG_100kB.jpg
--------------------------------------------------------------------------------
/public/files/file_example_MP3_1MG.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Whapi-Cloud/php-whatsapp-chatbot/ed19119ccfacd986726715b194d475f1da88cbf9/public/files/file_example_MP3_1MG.mp3
--------------------------------------------------------------------------------
/public/files/file_example_MP4_480_1_5MG.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Whapi-Cloud/php-whatsapp-chatbot/ed19119ccfacd986726715b194d475f1da88cbf9/public/files/file_example_MP4_480_1_5MG.mp4
--------------------------------------------------------------------------------
/public/files/sample-vcard.txt:
--------------------------------------------------------------------------------
1 | BEGIN:VCARD
2 | VERSION:3.0
3 | N:Gump;Forrest;;Mr.;
4 | FN:Forrest Gump
5 | ORG:Bubba Gump Shrimp Co.
6 | TITLE:Shrimp Man
7 | TEL;TYPE=WORK,VOICE:(111) 555-1212
8 | TEL;TYPE=HOME,VOICE:(404) 555-1212
9 | ADR;TYPE=WORK,PREF:;;100 Waters Edge;Baytown;LA;30314;United States of America
10 | LABEL;TYPE=WORK,PREF:100 Waters Edge\nBaytown\, LA 30314\nUnited States of America
11 | ADR;TYPE=HOME:;;42 Plantation St.;Baytown;LA;30314;United States of America
12 | LABEL;TYPE=HOME:42 Plantation St.\nBaytown\, LA 30314\nUnited States of America
13 | EMAIL:forrestgump@example.com
14 | REV:2008-04-24T19:52:43Z
15 | END:VCARD
16 |
--------------------------------------------------------------------------------
/public/index.php:
--------------------------------------------------------------------------------
1 | $config['apiUrl']
14 | ]);
15 |
16 | // Commands
17 | const COMMANDS = [
18 | 'TEXT' => 'Simple text message',
19 | 'IMAGE' => 'Send image',
20 | 'DOCUMENT' => 'Send document',
21 | 'VIDEO' => 'Send video',
22 | 'CONTACT' => 'Send contact',
23 | 'PRODUCT' => 'Send product',
24 | 'GROUP_CREATE' => 'Create group',
25 | 'GROUP_TEXT' => 'Simple text message for the group',
26 | 'GROUPS_IDS' => 'Get the id\'s of your three groups'
27 | ];
28 |
29 | // Url files
30 | const FILES = [
31 | 'IMAGE' => './files/file_example_JPG_100kB.jpg',
32 | 'DOCUMENT' => './files/file-example_PDF_500_kB.pdf',
33 | 'VIDEO' => './files/file_example_MP4_480_1_5MG.mp4',
34 | 'VCARD' => './files/sample-vcard.txt'
35 | ];
36 |
37 | function sendWhapiRequest($endpoint, $params = [], $method = 'POST')
38 | {
39 | global $config, $client;
40 |
41 | $url = $config['apiUrl'] . '/' . $endpoint;
42 | $options = [
43 | 'headers' => [
44 | 'Authorization' => 'Bearer ' . $config['token'],
45 | ],
46 | ];
47 |
48 | if ($params && count($params) > 0) {
49 | if ($method === 'GET') {
50 | $url .= '?' . http_build_query($params);
51 | } else {
52 | if(isset($params['media'])){
53 | $options['multipart'] = toFormData($params);
54 | }else{
55 | $options['headers']['Content-Type'] = 'application/json';
56 | $options['body'] = json_encode($params);
57 | }
58 | }
59 | }
60 |
61 | echo '$options: ' . print_r($options, true);
62 | $response = $client->request($method, $url, $options);
63 | $json = json_decode($response->getBody()->getContents(), true);
64 | echo 'Whapi response: ' . print_r($json, true);
65 | return $json;
66 | }
67 |
68 | function toFormData($params)
69 | {
70 | $multipart = [];
71 | foreach ($params as $name => $contents) {
72 | $multipart[] = ['name' => $name, 'contents' => $contents];
73 | }
74 | return $multipart;
75 | }
76 | // Call this function if you want to setup a webhook through the API. In this example it is not called: you will need to go to the channel settings in your personal cabinet and set the webhook link like {link to your server}/messages
77 | function setHook()
78 | {
79 | global $config;
80 | if ($config['botUrl']) {
81 | sendWhapiRequest('settings', [
82 | 'webhooks' => [
83 | [
84 | 'url' => $config['botUrl'],
85 | 'events' => [
86 | [
87 | 'type' => 'messages',
88 | 'method' => 'post'
89 | ]
90 | ],
91 | 'mode' => 'method'
92 | ]
93 | ]
94 | ], 'PATCH');
95 | }
96 | }
97 |
98 | $app->get('/', function (Request $request, Response $response) {
99 | return $response->write('Bot is running');
100 | });
101 |
102 | $app->post('/hook/messages', function (Request $request, Response $response) use ($config) {
103 | $data = json_decode($request->getBody(), true);
104 | $messages = $data['messages'] ?? [];
105 |
106 | foreach ($messages as $message) {
107 | if ($message['from_me']) {
108 | continue;
109 | }
110 |
111 | $sender = ['to' => $message['chat_id']];
112 | $endpoint = 'messages/text';
113 | $textBody = trim($message['text']['body'] ?? '');
114 | $commandIndex = is_numeric($textBody) ? (int)$textBody - 1 : null;
115 | $commands = array_keys(COMMANDS);
116 | $command = $commands[$commandIndex] ?? null;
117 |
118 | switch ($command) {
119 | case 'TEXT':
120 | $sender['body'] = 'Simple text message';
121 | break;
122 |
123 | case 'IMAGE':
124 | $sender['caption'] = 'Text under the photo.';
125 | $sender['media'] = fopen(FILES['IMAGE'], 'r');
126 | $endpoint = 'messages/image';
127 | break;
128 |
129 | case 'DOCUMENT':
130 | $sender['caption'] = 'Text under the document.';
131 | $sender['media'] = fopen(FILES['DOCUMENT'], 'r');
132 | $endpoint = 'messages/document';
133 | break;
134 |
135 | case 'VIDEO':
136 | $sender['caption'] = 'Text under the video.';
137 | $sender['media'] = fopen(FILES['VIDEO'], 'r');
138 | $endpoint = 'messages/video';
139 | break;
140 |
141 | case 'CONTACT':
142 | $sender['name'] = 'Whapi Test';
143 | $sender['vcard'] = file_get_contents(FILES['VCARD']);
144 | $endpoint = 'messages/contact';
145 | break;
146 |
147 | case 'PRODUCT':
148 | // Replace with your product ID
149 | $endpoint = "business/products/{$config['product']}";
150 | break;
151 |
152 | case 'GROUP_CREATE':
153 | $groupSettings = [
154 | 'subject' => 'Whapi.Cloud Test',
155 | 'participants' => [$message['from']]
156 | ];
157 | $groupResponse = sendWhapiRequest('groups', $groupSettings, 'POST');
158 | $sender['body'] = $groupResponse['group_id'] ? "Group created. Group id: {$groupResponse['group_id']}" : 'Error';
159 | $endpoint = 'messages/text';
160 | break;
161 |
162 | case 'GROUP_TEXT':
163 | $sender['to'] = $config['group'];
164 | $sender['body'] = 'Simple text message for the group';
165 | break;
166 |
167 | case 'GROUPS_IDS':
168 | $groupsResponse = sendWhapiRequest('groups', ['count' => 3], 'GET');
169 | if (!empty($groupsResponse['groups'])) {
170 | $groupIds = array_map(function ($group, $i) {
171 | return ($i + 1) . ". {$group['id']} - {$group['name']}";
172 | }, $groupsResponse['groups'], array_keys($groupsResponse['groups']));
173 | $sender['body'] = implode(",\n ", $groupIds);
174 | } else {
175 | $sender['body'] = 'No groups';
176 | }
177 | break;
178 |
179 | default:
180 | $sender['body'] = "Hi. Send me a number from the list. Don't forget to change the actual data in the code! \n\n" .
181 | implode("\n", array_map(function ($text) {
182 | static $i = 0;
183 | $i++;
184 | return ($i) . ". $text";
185 | }, COMMANDS, array_keys(COMMANDS)));
186 | break;
187 | }
188 |
189 | try {
190 | sendWhapiRequest($endpoint, $sender);
191 | } catch (\Exception $e) {
192 | error_log($e->getMessage());
193 | return $response->withStatus(500)->write('Error: ' . $e->getMessage());
194 | }
195 |
196 | }
197 |
198 | return $response->withStatus(200)->write('Ok');
199 | });
200 |
201 |
202 | $app->run();
203 |
--------------------------------------------------------------------------------