diff --git a/README.md b/README.md index 9041093..6a0c546 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,9 @@ $otp = new OtpVerifier('966000000000'); $otp->send(); ``` +- WhatsApp:\ + Add a message template named `otp_code`, type (`Authentication`) with your app supported languages. + --- ## Contributing diff --git a/composer.json b/composer.json index ab3114d..4e2c213 100644 --- a/composer.json +++ b/composer.json @@ -20,6 +20,7 @@ "prefer-stable":true, "require": { "php": ">=7.1|^8.0", + "adrii/whatsapp-api": "^0.7.0", "guzzlehttp/guzzle": "^7.3", "illuminate/contracts": "^6|^7|^8|^9|^10", "illuminate/support": "^6|^7|^8|^9|^10" diff --git a/config/sendables.php b/config/sendables.php index 7d1c24f..48d33cf 100644 --- a/config/sendables.php +++ b/config/sendables.php @@ -100,5 +100,16 @@ 'firebase' => [ 'apiKey' => '', ], + + /** + * WhatsApp + * + * URL: https://business.facebook.com + */ + 'whatsapp' => [ + 'phoneNumberId' => '', + 'accessToken' => '', + 'graphVersion' => '', + ], ] ]; diff --git a/src/Services/WhatsApp/WhatsAppOtpProvidor.php b/src/Services/WhatsApp/WhatsAppOtpProvidor.php new file mode 100644 index 0000000..c14c8d7 --- /dev/null +++ b/src/Services/WhatsApp/WhatsAppOtpProvidor.php @@ -0,0 +1,24 @@ +mobile); + } + + public function getClientType(): string + { + return 'whatsapp'; + } + + public function getCodeDigitsCount(): int + { + return 6; + } +} diff --git a/src/Services/WhatsApp/WhatsAppOtpTemplateProvider.php b/src/Services/WhatsApp/WhatsAppOtpTemplateProvider.php new file mode 100644 index 0000000..ef66de7 --- /dev/null +++ b/src/Services/WhatsApp/WhatsAppOtpTemplateProvider.php @@ -0,0 +1,115 @@ +message = $message; + $this->code = $code; + $this->mobileNumbers = is_array($mobileNumbers) ? $mobileNumbers : [$mobileNumbers]; + + $this->initWhatsApp(); + } + + public function send(): void + { + foreach ($this->mobileNumbers as $mobileNumber) { + $this->sendWhatsAppMessage($mobileNumber); + } + } + + public function isSent(): bool + { + return $this->isMassageSent; + } + + protected function getPhoneNumberId(): string + { + return $this->getConfigValue('phoneNumberId'); + } + + protected function getAccessToken(): string + { + return $this->getConfigValue('accessToken'); + } + + protected function getGraphVersion(): string + { + return $this->getConfigValue('graphVersion'); + } + + protected function sendWhatsAppMessage(string $mobileNumber): void + { + try { + $bodyComponent = [ + 'type' => 'body', + 'parameters' => [ + [ + 'type' => 'text', + 'text' => $this->code, + ], + ], + ]; + + $buttonComponent = [ + 'type' => 'button', + 'sub_type' => 'url', + 'index' => '0', + 'parameters' => [ + [ + 'type' => 'text', + 'text' => $this->code, + ], + ], + ]; + + $this->ws->send_message() + ->addComponent($bodyComponent, $buttonComponent); + + $response = $this->ws->send_message() + ->template('otp_code', $mobileNumber, SendablesHelpers::getCurrentLocale()); + + $this->isMassageSent = isset($response[2]) && $response[2] === 'OK'; + + if (!$this->isMassageSent) { + throw new \Exception('OTP not sent, response: ' . json_encode($response)); + } + } catch (Throwable $ex) { + $class = self::class; + \Log::error("Error in `$class`: " . $ex->getMessage()); + } + } + + protected function initWhatsApp(): void + { + $this->ws = new Whatsapp( + $this->getPhoneNumberId(), + $this->getAccessToken(), + $this->getGraphVersion() + ); + } + + protected function getConfigValue(string $key): ?string + { + return config("sendables.services.whatsapp.$key"); + } +} diff --git a/src/helpers.php b/src/helpers.php index 2901c0c..a7336b0 100644 --- a/src/helpers.php +++ b/src/helpers.php @@ -54,4 +54,14 @@ public static function removeLeadingPlus($value) { return ltrim($value, '+'); } + + /** + * Get app current locale + * + * @return string + */ + public static function getCurrentLocale() + { + return config('app.locale'); + } }