diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..cd8eb86e --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +; This file is for unifying the coding style for different editors and IDEs. +; More information at http://editorconfig.org + +root = true + +[*] +charset = utf-8 +indent_size = 4 +indent_style = space +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..6a6b99e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +.idea +/vendor +build +.DS_Store +.phpunit.result.cache +Thumbs.db + +composer.phar +composer.lock + +phpunit.phar +/phpunit.xml + diff --git a/.styleci.yml b/.styleci.yml new file mode 100644 index 00000000..0285f179 --- /dev/null +++ b/.styleci.yml @@ -0,0 +1 @@ +preset: laravel diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..864ab276 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,7 @@ +# Changelog + +All notable changes to `bitrix-24` will be documented in this file + +## 1.0.0 - 201X-XX-XX + +- initial release diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..4da74e3f --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,55 @@ +# Contributing + +Contributions are **welcome** and will be fully **credited**. + +Please read and understand the contribution guide before creating an issue or pull request. + +## Etiquette + +This project is open source, and as such, the maintainers give their free time to build and maintain the source code +held within. They make the code freely available in the hope that it will be of use to other developers. It would be +extremely unfair for them to suffer abuse or anger for their hard work. + +Please be considerate towards maintainers when raising issues or presenting pull requests. Let's show the +world that developers are civilized and selfless people. + +It's the duty of the maintainer to ensure that all submissions to the project are of sufficient +quality to benefit the project. Many developers have different skillsets, strengths, and weaknesses. Respect the maintainer's decision, and do not be upset or abusive if your submission is not used. + +## Viability + +When requesting or submitting new features, first consider whether it might be useful to others. Open +source projects are used by many developers, who may have entirely different needs to your own. Think about +whether or not your feature is likely to be used by other users of the project. + +## Procedure + +Before filing an issue: + +- Attempt to replicate the problem, to ensure that it wasn't a coincidental incident. +- Check to make sure your feature suggestion isn't already present within the project. +- Check the pull requests tab to ensure that the bug doesn't have a fix in progress. +- Check the pull requests tab to ensure that the feature isn't already in progress. + +Before submitting a pull request: + +- Check the codebase to ensure that your feature doesn't already exist. +- Check the pull requests to ensure that another person hasn't already submitted the feature or fix. + +## Requirements + +If the project maintainer has any additional requirements, you will find them listed here. + +- **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](http://pear.php.net/package/PHP_CodeSniffer). + +- **Add tests!** - Your patch won't be accepted if it doesn't have tests. + +- **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date. + +- **Consider our release cycle** - We try to follow [SemVer v2.0.0](http://semver.org/). Randomly breaking public APIs is not an option. + +- **One pull request per feature** - If you want to do more than one thing, send multiple pull requests. + +- **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please [squash them](http://www.git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Changing-Multiple-Commit-Messages) before submitting. + +**Happy coding**! diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 00000000..20bc583e --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +# The MIT License (MIT) + +Copyright (c) Sergey Zhidkov + +> 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/README.md b/README.md index fa8362b7..12521908 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,141 @@ -# New Notification Channels +# Laravel Notification to Bitrix24 -### Suggesting a new channel -Have a suggestion or working on a new channel? Please create a new issue for that service. +[![Latest Version on Packagist](https://img.shields.io/packagist/v/laravel-notification-channels/bitrix-24.svg?style=flat-square)](https://packagist.org/packages/laravel-notification-channels/bitrix-24) +[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE.md) +[![Build Status](https://img.shields.io/travis/laravel-notification-channels/bitrix-24/master.svg?style=flat-square)](https://travis-ci.org/laravel-notification-channels/bitrix-24) +[![StyleCI](https://styleci.io/repos/229822475/shield)](https://styleci.io/repos/229822475) +[![Quality Score](https://img.shields.io/scrutinizer/g/laravel-notification-channels/bitrix-24.svg?style=flat-square)](https://scrutinizer-ci.com/g/laravel-notification-channels/bitrix-24) +[![Code Coverage](https://img.shields.io/scrutinizer/coverage/g/laravel-notification-channels/bitrix-24/master.svg?style=flat-square)](https://scrutinizer-ci.com/g/laravel-notification-channels/bitrix-24/?branch=master) +[![Total Downloads](https://img.shields.io/packagist/dt/laravel-notification-channels/bitrix-24.svg?style=flat-square)](https://packagist.org/packages/laravel-notification-channels/bitrix-24) -### I'm working on a new channel -Please create an issue for it if it does not already exist, then PR you code for review. +This package makes it easy to send notifications to bitrix24 with Laravel 5.5+ and 6.0 -## Workflow for new channels -1) Head over to the [skeleton repo](https://github.com/laravel-notification-channels/skeleton) download a ZIP copy. This is important, to ensure you start from a fresh commit history. -2) Use find/replace to replace all of the placeholders with the correct values (package name, author name, email, etc). -3) Implement to logic for the channel & add tests. -4) Fork this repo, add it as a remote and push your new channel to a branch. -5) Submit a new PR against this repo for review. +## Contents -Take a look at our [FAQ](http://laravel-notification-channels.com/) to see our small list of rules, to provide top-notch notification channels. +- [Installation](#installation) + - [Setting up the config](#setting-up-the-config) +- [Usage](#usage) + - [Available Message methods](#available-message-methods) +- [Changelog](#changelog) +- [Testing](#testing) +- [Security](#security) +- [Contributing](#contributing) +- [Credits](#credits) +- [License](#license) + + +## Installation + +Run: +```php + composer require "laravel-notification-channels/bitrix-24" +``` + +### Setting up the config + +Publish config: + +```php + php artisan vendor:publish --provider="NotificationChannels\Bitrix24\Bitrix24ServiceProvider" +``` + +To implement notifications, a webhook system based on the Bitrix24 REST API is used (read more about webhooks in the official documentation [Bitrix24](https://dev.1c-bitrix.ru/learning/course/?COURSE_ID=99&LESSON_ID=8581)). This means that you must add a webhook on your Bitrix24 portal yourself and get its token. This token must be entered in the configuration file `config/bitrix24_notice.php`. +It is also necessary to enter the Bitrix24 user ID in the configuration file, on behalf of which notifications will be sent, and the subdomain of your company in Bitrix24. + +> In the configuration file, you must fill in all the fields described above, otherwise the notifications will not work. + +## Usage + +In your `via()` you can use a channel: + +```php + use NotificationChannels\Bitrix24\Bitrix24Channel; + use NotificationChannels\Bitrix24\Bitrix24Message; + use Illuminate\Notifications\Notification; + + class BitrixNotice extends Notification + { + protected $invoice; + + public function __construct($invoice) + { + $this->invoice = $invoice; + } + + public function via($notifiable) + { + return [Bitrix24Channel::class]; + } + + public function toBitrix24($notifiable) + { + $data = [ + 'invoice' => $this->invoice, + ]; + + return (new Bitrix24Message) + ->view('notice', $data) + ->toUser(); + } + } +``` + +The package expects to be given the ID of the chat to send the message to, or the ID of the user being notified. + +For example, if the bitrix24 user ID is `56`, you can create a notification for It like this: + +```php + Notification::send(56, new BitrixNotice($invoice)); +``` + +or + +```php + Notification::route('bitrix24', '56') + ->notify(new BitrixNotice($invoice)); +``` + +If you use your model data for notification, you should add the following function to the notified model, which should return a number - the chat ID or user ID: + +```php + public function routeNotificationForBitrix24(): int + { + return $this->bitrix_id; + } +``` + +### Available Message methods + +`view()` You can use the Blade template as a notification. The method takes the name of the template and an array of data that will be used in the template. When using a template, you should still use the formatting described in the [documentation REST API](https://dev.1c-bitrix.ru/learning/course/index.php?COURSE_ID=93&LESSON_ID=7679) + +`text()` Simple notification text + +`toUser()` By default, notifications are sent to the chat whose ID was passed. If you want to send a message to a user, you must pass the user's ID, and call the 'toUser ()' method on the `new Bitrix24Message () ' object. Thus, this method determines whether the transmitted ID belongs to the chat or to the user. + +## Changelog + +Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently. + +## Testing + +``` bash +$ composer test +``` + +## Security + +If you discover any security related issues, please email zhidkoff@list.ru instead of using the issue tracker. + +## Contributing + +Please see [CONTRIBUTING](CONTRIBUTING.md) for details. + +## Credits + +- [Sergey Zhidkov](https://github.com/adiafora) +- [All Contributors](../../contributors) + +## License + +The MIT License (MIT). Please see [License File](LICENSE.md) for more information. diff --git a/composer.json b/composer.json new file mode 100644 index 00000000..bc1c066d --- /dev/null +++ b/composer.json @@ -0,0 +1,40 @@ +{ + "name": "laravel-notification-channels/bitrix-24", + "description": "Package for Laravel notification to Bitrix24", + "homepage": "https://github.com/laravel-notification-channels/bitrix-24", + "license": "MIT", + "authors": [ + { + "name": "Sergey Zhidkov", + "email": "zhidkoff@list.ru", + "role": "Developer" + } + ], + "require": { + "php": ">=7.2", + "illuminate/notifications": "~6.0 || ~7.0 || ~8.0", + "illuminate/support": "~6.0 || ~7.0 || ~8.0", + "ext-curl": "*" + }, + "require-dev": { + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^9.0" + }, + "autoload": { + "psr-4": { + "NotificationChannels\\Bitrix24\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "NotificationChannels\\Bitrix24\\Test\\": "tests" + } + }, + "scripts": { + "test": "phpunit", + "test:coverage": "phpunit --coverage-text --coverage-clover=coverage.clover" + }, + "config": { + "sort-packages": true + } +} diff --git a/config/bitrix24_notice.php b/config/bitrix24_notice.php new file mode 100644 index 00000000..787e687f --- /dev/null +++ b/config/bitrix24_notice.php @@ -0,0 +1,29 @@ + null, + + /* + | OAuth-token of webhook + | + */ + 'token' => '', + + /* + | Your company's subdomain + | + | An example is given for the company https://example.bitrix24.ru/ + | + */ + 'domain' => 'example', +]; diff --git a/src/Bitrix24Channel.php b/src/Bitrix24Channel.php new file mode 100644 index 00000000..0caeab37 --- /dev/null +++ b/src/Bitrix24Channel.php @@ -0,0 +1,59 @@ +bitrix24 = $bitrix24; + } + + /** + * Send the given notification. + * + * @param mixed $notifiable + * @param \Illuminate\Notifications\Notification $notification + * @return void + * @throws CouldNotSendNotification + */ + public function send($notifiable, Notification $notification) + { + $message = $notification->toBitrix24($notifiable); + + if (is_object($notifiable)) { + $notifiable = $notifiable->routeNotificationFor('bitrix24'); + } + + if (empty($notifiable)) { + throw CouldNotSendNotification::notChatId(); + } + + if ($message->toUser === true) { + $typeOfChat = 'USER_ID'; + } else { + $typeOfChat = 'CHAT_ID'; + } + + $params = [ + $typeOfChat => $notifiable, + 'MESSAGE' => $message->message, + ]; + + $this->bitrix24->send($params); + } +} diff --git a/src/Bitrix24Message.php b/src/Bitrix24Message.php new file mode 100644 index 00000000..f6368be8 --- /dev/null +++ b/src/Bitrix24Message.php @@ -0,0 +1,58 @@ +message = view($view, $data)->render(); + + return $this; + } + + /** + * Send a string as a message. + * + * @param string $message + * @return $this + */ + public function text(string $message) + { + $this->message = $message; + + return $this; + } + + /** + * The message is intended for the user, not for the chat. + * + * @return $this + */ + public function toUser() + { + $this->toUser = true; + + return $this; + } +} diff --git a/src/Bitrix24ServiceProvider.php b/src/Bitrix24ServiceProvider.php new file mode 100644 index 00000000..d2f4fc6b --- /dev/null +++ b/src/Bitrix24ServiceProvider.php @@ -0,0 +1,23 @@ +publishes([__DIR__.'/../config/' => config_path().'/']); + } + + /** + * Register the application services. + */ + public function register() + { + } +} diff --git a/src/Exceptions/CouldNotSendNotification.php b/src/Exceptions/CouldNotSendNotification.php new file mode 100644 index 00000000..1b2a64b7 --- /dev/null +++ b/src/Exceptions/CouldNotSendNotification.php @@ -0,0 +1,48 @@ +token = config('bitrix24_notice.token'); + + if (empty($this->token)) { + throw CouldNotSendNotification::notToken(); + } + + $this->fromUserId = (int) config('bitrix24_notice.fromUserId'); + + if (empty($this->fromUserId)) { + throw CouldNotSendNotification::notUserId(); + } + + $this->domain = config('bitrix24_notice.domain'); + + if (empty($this->domain)) { + throw CouldNotSendNotification::notDomain(); + } + } + + /** + * Preparing and executing a request to the Bitrix24 API. + * + * @param array $params + * @return void + * @throws CouldNotSendNotification + */ + public function send(array $params) + { + try { + $curl = curl_init(); + curl_setopt($curl, CURLOPT_URL, $this->geuUrlForSend()); + curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 10); + curl_setopt($curl, CURLOPT_TIMEOUT, 10); + curl_setopt($curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_HTTPHEADER, $this->getHeaders()); + curl_setopt($curl, CURLOPT_POST, true); + curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($params, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)); + } catch (\Exception $e) { + throw CouldNotSendNotification::notConnect($e->getMessage()); + } + } + + /** + * Service address for sending JSON requests (case-sensitive). + * + * @return string + */ + private function geuUrlForSend(): string + { + return 'https://'.$this->domain.'.bitrix24.ru/rest/'.$this->fromUserId.'/'.$this->token.'/im.message.add.json'; + } + + /** + * Headers for sending JSON requests. + * + * @return array + */ + private function getHeaders(): array + { + return [ + 'Accept-Language: ru', + 'Content-Type: application/json; charset=utf-8', + ]; + } +} diff --git a/tests/Bitrix24ChannelTest.php b/tests/Bitrix24ChannelTest.php new file mode 100644 index 00000000..5f23d0cb --- /dev/null +++ b/tests/Bitrix24ChannelTest.php @@ -0,0 +1,62 @@ +bitrix24 = Mockery::mock(Bitrix24::class); + + $this->channel = new Bitrix24Channel($this->bitrix24); + } + + /** @test */ + public function it_can_send_a_notification() + { + $this->bitrix24->shouldReceive('send')->with([ + 'USER_ID' => 56, + 'MESSAGE' => 'message', + ])->once(); + + $result = $this->channel->send(new TestNotifiable(), new TestNotification()); + + $this->assertNull($result); + } +} + +class TestNotifiable +{ + use Notifiable; + + public function routeNotificationForBitrix24(): int + { + return 56; + } +} + +class TestNotification extends Notification +{ + public function toBitrix24($notifiable) + { + return (new Bitrix24Message()) + ->text('message') + ->toUser(); + } +}