Skip to content

Commit 8444b30

Browse files
authored
Merge pull request #173 from ricardoapaes/add-zoho-cliq-integration
✨ Feature: Add Support for Zoho Cliq Notification Service
2 parents 17d5bfe + d9ddccf commit 8444b30

File tree

8 files changed

+273
-3
lines changed

8 files changed

+273
-3
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# notify
22

33
> [!NOTE]
4-
> Push notification SDK(AnPush、Bark、Chanify、DingTalk、Discord、Gitter、GoogleChat、IGot、Lark、Mattermost、MicrosoftTeams、NowPush、Ntfy、Push、Pushback、PushBullet、PushDeer、PushMe、Pushover、PushPlus、QQ、RocketChat、ServerChan、ShowdocPush、SimplePush、Slack、Telegram、WeWork、WPush、XiZhi、YiFengChuanHua、Zulip).
4+
> Push notification SDK(AnPush、Bark、Chanify、DingTalk、Discord、Gitter、GoogleChat、IGot、Lark、Mattermost、MicrosoftTeams、NowPush、Ntfy、Push、Pushback、PushBullet、PushDeer、PushMe、Pushover、PushPlus、QQ、RocketChat、ServerChan、ShowdocPush、SimplePush、Slack、Telegram、WeWork、WPush、XiZhi、YiFengChuanHua、ZohoCliq、Zulip).
55
66
[![tests](https://github.com/guanguans/notify/actions/workflows/tests.yml/badge.svg)](https://github.com/guanguans/notify/actions/workflows/tests.yml)
77
[![check & fix styling](https://github.com/guanguans/notify/actions/workflows/php-cs-fixer.yml/badge.svg)](https://github.com/guanguans/notify/actions/workflows/php-cs-fixer.yml)
@@ -49,6 +49,7 @@
4949
* [WPush](./src/WPush/README.md)
5050
* [XiZhi](./src/XiZhi/README.md)
5151
* [YiFengChuanHua](./src/YiFengChuanHua/README.md)
52+
* [ZohoCliq](./src/ZohoCliq/README.md)
5253
* [Zulip](./src/Zulip/README.md)
5354

5455
## Related repositories

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "guanguans/notify",
3-
"description": "Push notification SDK(AnPush、Bark、Chanify、DingTalk、Discord、Gitter、GoogleChat、IGot、Lark、Mattermost、MicrosoftTeams、NowPush、Ntfy、Push、Pushback、PushBullet、PushDeer、PushMe、Pushover、PushPlus、QQ、RocketChat、ServerChan、ShowdocPush、SimplePush、Slack、Telegram、WeWork、WPush、XiZhi、YiFengChuanHua、Zulip).",
3+
"description": "Push notification SDK(AnPush、Bark、Chanify、DingTalk、Discord、Gitter、GoogleChat、IGot、Lark、Mattermost、MicrosoftTeams、NowPush、Ntfy、Push、Pushback、PushBullet、PushDeer、PushMe、Pushover、PushPlus、QQ、RocketChat、ServerChan、ShowdocPush、SimplePush、Slack、Telegram、WeWork、WPush、XiZhi、YiFengChuanHua、ZohoCliq、Zulip).",
44
"license": "MIT",
55
"type": "library",
66
"keywords": [
@@ -52,6 +52,7 @@
5252
"WPush",
5353
"XiZhi",
5454
"YiFengChuanHua",
55+
"ZohoCliq",
5556
"Zulip"
5657
],
5758
"authors": [
@@ -89,7 +90,6 @@
8990
"ergebnis/license": "^2.6",
9091
"ergebnis/php-cs-fixer-config": "dev-main",
9192
"ergebnis/rector-rules": "^1.3",
92-
"guanguans/ai-commit": "dev-main",
9393
"guanguans/monorepo-builder-worker": "^1.4",
9494
"illuminate/collections": "^9.52 || ^10.0 || ^11.0 || ^12.0",
9595
"illuminate/support": "^9.52 || ^10.0 || ^11.0 || ^12.0",

src/ZohoCliq/Authenticator.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* Copyright (c) 2021-2025 guanguans<[email protected]>
7+
*
8+
* For the full copyright and license information, please view
9+
* the LICENSE file that was distributed with this source code.
10+
*
11+
* @see https://github.com/guanguans/notify
12+
*/
13+
14+
namespace Guanguans\Notify\ZohoCliq;
15+
16+
use Guanguans\Notify\Foundation\Authenticators\AggregateAuthenticator;
17+
use Guanguans\Notify\Foundation\Authenticators\BearerAuthenticator;
18+
use Guanguans\Notify\Foundation\Authenticators\UriTemplateAuthenticator;
19+
20+
class Authenticator extends AggregateAuthenticator
21+
{
22+
public function __construct(
23+
string $companyId,
24+
string $channelUniqueName,
25+
#[\SensitiveParameter]
26+
?string $authToken = null
27+
) {
28+
$authenticators = [
29+
new UriTemplateAuthenticator([
30+
'companyId' => $companyId,
31+
'channelUniqueName' => $channelUniqueName,
32+
]),
33+
];
34+
35+
if (null !== $authToken) {
36+
$authenticators[] = new BearerAuthenticator($authToken);
37+
}
38+
39+
parent::__construct(...$authenticators);
40+
}
41+
42+
public static function generateToken(string $clientId, string $clientSecret): string
43+
{
44+
$token = new Token($clientId, $clientSecret);
45+
46+
return $token->generateToken();
47+
}
48+
}

src/ZohoCliq/Client.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* Copyright (c) 2021-2025 guanguans<[email protected]>
7+
*
8+
* For the full copyright and license information, please view
9+
* the LICENSE file that was distributed with this source code.
10+
*
11+
* @see https://github.com/guanguans/notify
12+
*/
13+
14+
namespace Guanguans\Notify\ZohoCliq;
15+
16+
/**
17+
* @see https://www.zoho.com/cliq/help/restapi/v2/#Post_Message_Channel
18+
* @see https://www.zoho.com/cliq/help/platform/webhooks.html
19+
*/
20+
class Client extends \Guanguans\Notify\Foundation\Client
21+
{
22+
public function __construct(Authenticator $authenticator)
23+
{
24+
parent::__construct($authenticator);
25+
$this->baseUri('https://cliq.zoho.com/');
26+
}
27+
}

src/ZohoCliq/Messages/Message.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* Copyright (c) 2021-2025 guanguans<[email protected]>
7+
*
8+
* For the full copyright and license information, please view
9+
* the LICENSE file that was distributed with this source code.
10+
*
11+
* @see https://github.com/guanguans/notify
12+
*/
13+
14+
namespace Guanguans\Notify\ZohoCliq\Messages;
15+
16+
/**
17+
* @method self bot(array $bot)
18+
* @method self buttons(array $buttons)
19+
* @method self card(array $card)
20+
* @method self slides(array $slides)
21+
* @method self styles(array $styles)
22+
* @method self text(mixed $text)
23+
*/
24+
class Message extends \Guanguans\Notify\Foundation\Message
25+
{
26+
protected array $defined = [
27+
'text',
28+
'bot',
29+
'card',
30+
'slides',
31+
'buttons',
32+
'styles',
33+
];
34+
protected array $allowedTypes = [
35+
'bot' => 'array',
36+
'card' => 'array',
37+
'slides' => 'array',
38+
'buttons' => 'array',
39+
'styles' => 'array',
40+
];
41+
42+
public function toHttpUri(): string
43+
{
44+
return 'company/{companyId}/api/v2/channelsbyname/{channelUniqueName}/message';
45+
}
46+
}

src/ZohoCliq/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# ZohoCliq
2+
3+
## [Usage example](./../../tests/ZohoCliq/ClientTest.php)
4+
5+
## Related links
6+
7+
* [https://www.zoho.com/cliq/help/restapi/v2/#Post_Message_Channel](https://www.zoho.com/cliq/help/restapi/v2/#Post_Message_Channel)
8+
* [https://www.zoho.com/cliq/help/platform/webhooks.html](https://www.zoho.com/cliq/help/platform/webhooks.html)
9+
* [https://www.zoho.com/cliq/help/restapi/v2/#Message_Cards](https://www.zoho.com/cliq/help/restapi/v2/#Message_Cards)

src/ZohoCliq/Token.php

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* Copyright (c) 2021-2025 guanguans<[email protected]>
7+
*
8+
* For the full copyright and license information, please view
9+
* the LICENSE file that was distributed with this source code.
10+
*
11+
* @see https://github.com/guanguans/notify
12+
*/
13+
14+
namespace Guanguans\Notify\ZohoCliq;
15+
16+
use GuzzleHttp\Client;
17+
18+
class Token
19+
{
20+
private string $clientId;
21+
private string $clientSecret;
22+
23+
public function __construct(string $clientId, string $clientSecret)
24+
{
25+
$this->clientId = $clientId;
26+
$this->clientSecret = $clientSecret;
27+
}
28+
29+
public function generateToken(): string
30+
{
31+
$response = (new Client)->request(
32+
'POST',
33+
'https://accounts.zoho.com/oauth/v2/token',
34+
[
35+
'form_params' => [
36+
'client_id' => $this->clientId,
37+
'client_secret' => $this->clientSecret,
38+
'grant_type' => 'client_credentials',
39+
'scope' => 'ZohoCliq.Webhooks.CREATE',
40+
],
41+
]
42+
);
43+
44+
$body = (string) $response->getBody();
45+
$json = json_decode($body ?: '[]', true, 512, \JSON_THROW_ON_ERROR);
46+
47+
return $json['access_token'];
48+
}
49+
}

tests/ZohoCliq/ClientTest.php

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<?php
2+
3+
/** @noinspection AnonymousFunctionStaticInspection */
4+
/** @noinspection NullPointerExceptionInspection */
5+
/** @noinspection PhpPossiblePolymorphicInvocationInspection */
6+
/** @noinspection PhpUnhandledExceptionInspection */
7+
/** @noinspection StaticClosureCanBeUsedInspection */
8+
9+
declare(strict_types=1);
10+
11+
/**
12+
* Copyright (c) 2021-2025 guanguans<[email protected]>
13+
*
14+
* For the full copyright and license information, please view
15+
* the LICENSE file that was distributed with this source code.
16+
*
17+
* @see https://github.com/guanguans/notify
18+
*/
19+
20+
namespace Guanguans\NotifyTests\ZohoCliq;
21+
22+
use Guanguans\Notify\ZohoCliq\Authenticator;
23+
use Guanguans\Notify\ZohoCliq\Client;
24+
use Guanguans\Notify\ZohoCliq\Messages\Message;
25+
26+
it('can send message', function (): void {
27+
// $token = Authenticator::generateToken('client-id', 'client-secret');
28+
$authenticator = new Authenticator('company-id', 'your-channel', 'use $token');
29+
$client = new Client($authenticator);
30+
$message = Message::make([
31+
'text' => 'This is a test message from ZohoCliq integration.',
32+
]);
33+
34+
expect($client)
35+
->mock([
36+
response(faker()->text()),
37+
])
38+
->assertCanSendMessage($message);
39+
})->group(__DIR__, __FILE__);
40+
41+
it('can send message with bot customization', function (): void {
42+
// $token = Authenticator::generateToken('client-id', 'client-secret');
43+
$authenticator = new Authenticator('company-id', 'your-channel', 'use $token');
44+
$client = new Client($authenticator);
45+
$message = Message::make([
46+
'text' => 'Hello from custom bot!',
47+
'bot' => [
48+
'name' => 'Custom Bot',
49+
'image' => 'https://example.com/bot-icon.png',
50+
],
51+
]);
52+
53+
expect($client)
54+
->mock([
55+
response(faker()->text()),
56+
])
57+
->assertCanSendMessage($message);
58+
})->group(__DIR__, __FILE__);
59+
60+
it('can send message with card', function (): void {
61+
// $token = Authenticator::generateToken('client-id', 'client-secret');
62+
$authenticator = new Authenticator('company-id', 'your-channel', 'use $token');
63+
$client = new Client($authenticator);
64+
$message = Message::make([
65+
'text' => 'Check out this notification!',
66+
'card' => [
67+
'title' => 'Important Update',
68+
'theme' => 'modern-inline',
69+
'thumbnail' => 'https://example.com/notification-icon.png',
70+
],
71+
'buttons' => [
72+
[
73+
'label' => 'View Details',
74+
'type' => '+',
75+
'action' => [
76+
'type' => 'open.url',
77+
'data' => [
78+
'web' => 'https://example.com/details',
79+
],
80+
],
81+
],
82+
],
83+
]);
84+
85+
expect($client)
86+
->mock([
87+
response(faker()->text()),
88+
])
89+
->assertCanSendMessage($message);
90+
})->group(__DIR__, __FILE__);

0 commit comments

Comments
 (0)