├── 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 | 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 | ![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ep3pc4jsna9pzagfouj8.png) 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 | --------------------------------------------------------------------------------