diff --git a/src/Symfony/Component/Notifier/Bridge/LightSms/LICENSE b/src/Symfony/Component/Notifier/Bridge/LightSms/LICENSE new file mode 100644 index 0000000000..ad85e17374 --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/LightSms/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2020-2021 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/src/Symfony/Component/Notifier/Bridge/LightSms/LightSmsTransport.php b/src/Symfony/Component/Notifier/Bridge/LightSms/LightSmsTransport.php new file mode 100644 index 0000000000..f49dafd6a2 --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/LightSms/LightSmsTransport.php @@ -0,0 +1,153 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Notifier\Bridge\LightSms; + +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Notifier\Exception\TransportException; +use Symfony\Component\Notifier\Exception\UnsupportedMessageTypeException; +use Symfony\Component\Notifier\Message\MessageInterface; +use Symfony\Component\Notifier\Message\SentMessage; +use Symfony\Component\Notifier\Message\SmsMessage; +use Symfony\Component\Notifier\Transport\AbstractTransport; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; +use Symfony\Contracts\HttpClient\HttpClientInterface; + +/** + * @author Vasilij Duško + */ +final class LightSmsTransport extends AbstractTransport +{ + protected const HOST = 'www.lightsms.com/external/get/send.php'; + + private $login; + private $password; + private $phone; + /** + * @var MessageInterface + */ + private $message; + + private $errorCodes = [ + '000' => 'Service unavailable', + '1' => 'Signature not specified', + '2' => 'Login not specified', + '3' => 'Text not specified', + '4' => 'Phone number not specified', + '5' => 'Sender not specified', + '6' => 'Invalid signature', + '7' => 'Invalid login', + '8' => 'Invalid sender name', + '9' => 'Sender name not registered', + '10' => 'Sender name not approved', + '11' => 'There are forbidden words in the text', + '12' => 'Error in SMS sending', + '13' => 'Phone number is in the blackist. SMS sending to this number is forbidden.', + '14' => 'There are more than 50 numbers in the request', + '15' => 'List not specified', + '16' => 'Invalid phone number', + '17' => 'SMS ID not specified', + '18' => 'Status not obtained', + '19' => 'Empty response', + '20' => 'The number already exists', + '21' => 'No name', + '22' => 'Template already exists', + '23' => 'Month not specifies (Format: YYYY-MM)', + '24' => 'Timestamp not specified', + '25' =>'Error in access to the list', + '26' => 'There are no numbers in the list', + '27' => 'No valid numbers', + '28' => 'Date of start not specified (Format: YYYY-MM-DD)', + '29' => 'Date of end not specified (Format: YYYY-MM-DD)', + '30' => 'No date (format: YYYY-MM-DD)', + '31' => 'Closing direction to the user', + '32' => 'Not enough money', + '33' => 'Phone number is not set', + '34' => 'Phone is in stop list', + '35' => 'Not enough money', + '36' => 'Can not obtain information about phone', + '37' => 'Base Id is not set', + '38' => 'Phone number is already exist in this base', + '39' => 'Phone number is not exist in this base', + ]; + + public function __construct( + string $login, + string $password, + string $phone, + HttpClientInterface $client = null, + EventDispatcherInterface $dispatcher = null + ) { + $this->login = $login; + $this->password = $password; + $this->phone = $phone; + + parent::__construct($client, $dispatcher); + } + + public function __toString(): string + { + return sprintf('lightsms://%s?phone=%s', $this->getEndpoint(), $this->phone); + } + + public function supports(MessageInterface $message): bool + { + return $message instanceof SmsMessage && $this->phone === str_replace('+', '', $message->getPhone()); + } + + protected function doSend(MessageInterface $message): void + { + if (!$message instanceof SmsMessage) { + throw new LogicException(sprintf('The "%s" transport only supports instances of "%s" (instance of "%s" given).', __CLASS__, SmsMessage::class, \get_class($message))); + } + + $this->message = $message; + + $signature = $this->getSignature(); + + $endpoint = sprintf( + 'https://%s?login=%s&signature=%s&phone=%s&text=%s&sender=%s×tamp=%s', + $this->getEndpoint(), + $this->login, + $signature, + str_replace('+', '', $message->getPhone()), + $message->getSubject(), + $this->phone, + time() + ); + + + $response = $this->client->request('GET', $endpoint); + + $content = $response->toArray(false); + + if (isset($content['error'])) { + throw new TransportException('Unable to send the SMS: '.$this->errorCodes[$content['error']], $response); + } + } + + private function getSignature(): string + { + + $params = [ + 'timestamp' => time(), + 'login' => $this->login, + 'phone' => str_replace('+', '', $this->message->getPhone()), + 'sender' => $this->phone, + 'text' => $this->message->getSubject(), + ]; + + ksort($params); + reset($params); + + return md5(implode($params) . $this->password); + } +} diff --git a/src/Symfony/Component/Notifier/Bridge/LightSms/LightSmsTransportFactory.php b/src/Symfony/Component/Notifier/Bridge/LightSms/LightSmsTransportFactory.php new file mode 100644 index 0000000000..e364b20c25 --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/LightSms/LightSmsTransportFactory.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Notifier\Bridge\LightSms; + +use Symfony\Component\Notifier\Exception\UnsupportedSchemeException; +use Symfony\Component\Notifier\Transport\AbstractTransportFactory; +use Symfony\Component\Notifier\Transport\Dsn; +use Symfony\Component\Notifier\Transport\TransportInterface; + +/** + * @author Vasilij Duško + */ +final class LightSmsTransportFactory extends AbstractTransportFactory +{ + /** + * @return LightSmsTransport + */ + public function create(Dsn $dsn): TransportInterface + { + $scheme = $dsn->getScheme(); + + if ('lightsms' !== $scheme) { + throw new UnsupportedSchemeException($dsn, 'lightsms', $this->getSupportedSchemes()); + } + + $login = $this->getUser($dsn); + $token = $this->getPassword($dsn); + $phone = $dsn->getOption('phone'); + + $host = 'default' === $dsn->getHost() ? null : $dsn->getHost(); + $port = $dsn->getPort(); + + return (new LightSmsTransport($login, $token, $phone, $this->client, $this->dispatcher))->setHost($host)->setPort($port); + } + + protected function getSupportedSchemes(): array + { + return ['lightsms']; + } +} diff --git a/src/Symfony/Component/Notifier/Bridge/LightSms/README.md b/src/Symfony/Component/Notifier/Bridge/LightSms/README.md new file mode 100644 index 0000000000..cea0c5d4ec --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/LightSms/README.md @@ -0,0 +1,28 @@ +LightSms Notifier +==================== + +Provides [LightSms](https://www.lightsms.com/) integration for Symfony Notifier. + +This provider allows you to receive an SMS notification on your mobile number. + +DSN example +----------- + +``` +LIGHTSMS_DSN=lightsms://LOGIN:TOKEN@default?phone=PHONE +``` + +where: + - `LOGIN` is your LightSms login + - `TOKEN` is the token displayed in your account + - `PHONE` is your LightSms phone number + +See your account info at https://www.lightsms.com/external/client/api/ + +Resources +--------- + + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/src/Symfony/Component/Notifier/Bridge/LightSms/composer.json b/src/Symfony/Component/Notifier/Bridge/LightSms/composer.json new file mode 100644 index 0000000000..56575559c8 --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/LightSms/composer.json @@ -0,0 +1,30 @@ +{ + "name": "symfony/lightsms-notifier", + "type": "symfony-bridge", + "description": "Symfony LightSms Notifier Bridge", + "keywords": ["sms", "LightSms", "notifier"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Vasilij Duško", + "email": "vasilij@d4d.lt" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=7.2.5", + "symfony/http-client": "^4.3|^5.0", + "symfony/notifier": "~5.0.0" + }, + "autoload": { + "psr-4": { "Symfony\\Component\\Notifier\\Bridge\\LightSms\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev" +} diff --git a/src/Symfony/Component/Notifier/Bridge/LightSms/phpunit.xml.dist b/src/Symfony/Component/Notifier/Bridge/LightSms/phpunit.xml.dist new file mode 100644 index 0000000000..6eddaf643a --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/LightSms/phpunit.xml.dist @@ -0,0 +1,31 @@ + + + + + + + + + + ./Tests/ + + + + + + ./ + + ./Resources + ./Tests + ./vendor + + + +